From beaefb764b8f568b65e970aed9984c5d525322df Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Fri, 7 Jul 2023 11:35:24 +0200 Subject: [PATCH 01/57] dragonboard: fix example and documentation (#977) --- examples/dragonboard_button.go | 4 ++-- platforms/chip/README.md | 37 +---------------------------- platforms/dragonboard/README.md | 42 ++++----------------------------- 3 files changed, 7 insertions(+), 76 deletions(-) diff --git a/examples/dragonboard_button.go b/examples/dragonboard_button.go index 101ec5003..1a7f01fff 100644 --- a/examples/dragonboard_button.go +++ b/examples/dragonboard_button.go @@ -11,11 +11,11 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/chip" + "gobot.io/x/gobot/v2/platforms/dragonboard" ) func main() { - dragonAdaptor := chip.NewAdaptor() + dragonAdaptor := dragonboard.NewAdaptor() button := gpio.NewButtonDriver(dragonAdaptor, "GPIO_A") work := func() { diff --git a/platforms/chip/README.md b/platforms/chip/README.md index 4b62bbc83..40f6e79ce 100644 --- a/platforms/chip/README.md +++ b/platforms/chip/README.md @@ -40,43 +40,8 @@ Reboot the device to make sure the init script loads the overlay on boot. ## How to Use +Please refer to one example for your platform, e.g. [chip_button.go](https://github.com/hybridgroup/gobot/blob/release/examples/chip_button.go). The pin numbering used by your Gobot program should match the way your board is labeled right on the board itself. - -```go -package main - -import ( - "fmt" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/chip" -) - -func main() { - chipAdaptor := chip.NewAdaptor() - button := gpio.NewButtonDriver(chipAdaptor, "XIO-P0") - - work := func() { - gobot.On(button.Event("push"), func(data interface{}) { - fmt.Println("button pressed") - }) - - gobot.On(button.Event("release"), func(data interface{}) { - fmt.Println("button released") - }) - } - - robot := gobot.NewRobot("buttonBot", - []gobot.Connection{chipAdaptor}, - []gobot.Device{button}, - work, - ) - - robot.Start() -} -``` - If you want to use the C.H.I.P. Pro, use the `NewProAdaptor()` function like this: ```go diff --git a/platforms/dragonboard/README.md b/platforms/dragonboard/README.md index 30862006a..f7911b2a9 100644 --- a/platforms/dragonboard/README.md +++ b/platforms/dragonboard/README.md @@ -16,43 +16,9 @@ transfer the final executable to your DragonBoard and run the program on the Dra ## How to Use +Please refer to one example for your platform, e.g. [dragonboard_button.go](https://github.com/hybridgroup/gobot/blob/release/examples/dragonboard_button.go). The pin numbering used by your Gobot program should match the way your board is labeled right on the board itself. See [here](https://www.96boards.org/db410c-getting-started/HardwareDocs/HWUserManual.md/). -```go -package main - -import ( - "fmt" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/dragonboard" -) - -func main() { - dragonAdaptor := dragonboard.NewAdaptor() - button := gpio.NewButtonDriver(dragonAdaptor, "GPIO_A") - - work := func() { - gobot.On(button.Event("push"), func(data interface{}) { - fmt.Println("button pressed") - }) - - gobot.On(button.Event("release"), func(data interface{}) { - fmt.Println("button released") - }) - } - - robot := gobot.NewRobot("buttonBot", - []gobot.Connection{chipAdaptor}, - []gobot.Device{button}, - work, - ) - - robot.Start() -} -``` - ## How to Connect ### Compiling @@ -60,13 +26,13 @@ func main() { Compile your Gobot program on your workstation like this: ```sh -GOARCH=arm64 GOOS=linux go build examples/dragon_button.go +GOARCH=arm64 GOOS=linux go build examples/dragonboard_button.go ``` Once you have compiled your code, you can you can upload your program and execute it on the DragonBoard from your workstation using the `scp` and `ssh` commands like this: ```sh -scp dragon_button root@192.168.1.xx: -ssh -t root@192.168.1.xx "./dragon_button" +scp dragonboard_button root@192.168.1.xx: +ssh -t root@192.168.1.xx "./dragonboard_button" ``` From cd653e9ea150b260d0b3df45a0e7046fb0d014fe Mon Sep 17 00:00:00 2001 From: Ron Evans Date: Sat, 23 Sep 2023 12:32:31 +0200 Subject: [PATCH 02/57] joystick(core): replace sdl with 0xcafed00d/joystick package (#988) --- .circleci/config.yml | 12 +- Makefile | 6 +- appveyor.yml | 4 + examples/ardrone_ps3.go | 2 +- examples/bebop_ps3.go | 2 +- examples/bebop_ps3_video.go | 2 +- examples/joystick_ps3.go | 26 ++- examples/joystick_ps4.go | 2 +- examples/joystick_ps5.go | 2 +- examples/joystick_xbox360.go | 2 +- examples/joystick_xbox360_rock_band_drums.go | 2 +- examples/joystick_xboxone.go | 2 +- examples/minidrone_mambo_ps3.go | 2 +- examples/minidrone_ps3.go | 2 +- examples/tello_facetracker.go | 2 +- examples/tello_ps3.go | 2 +- go.mod | 4 +- go.sum | 8 +- platforms/joystick/LICENSE | 2 +- platforms/joystick/README.md | 52 +---- platforms/joystick/bin/scanner.go | 140 +++++++----- platforms/joystick/configs/dualshock3.json | 12 +- platforms/joystick/doc.go | 12 +- platforms/joystick/joystick_adaptor.go | 33 +-- platforms/joystick/joystick_adaptor_test.go | 19 +- platforms/joystick/joystick_driver.go | 178 ++++++++------- platforms/joystick/joystick_driver_test.go | 211 ++++++++++++------ platforms/joystick/joystick_dualsense.go | 1 - ...hock3.go => joystick_dualshock3_darwin.go} | 35 ++- .../joystick/joystick_dualshock3_linux.go | 94 ++++++++ .../joystick/joystick_dualshock3_windows.go | 86 +++++++ .../joystick/joystick_dualshock4_darwin.go | 90 ++++++++ ...shock4.go => joystick_dualshock4_linux.go} | 35 +-- .../joystick/joystick_dualshock4_windows.go | 94 ++++++++ .../joystick/joystick_nintendo_joycon.go | 1 - platforms/joystick/joystick_shield.go | 27 --- .../joystick/joystick_tflight_hotas_x.go | 7 - platforms/joystick/joystick_xbox360.go | 47 ---- .../joystick_xbox360_rock_band_drums.go | 1 - platforms/joystick/joystick_xboxone.go | 27 --- platforms/joystick/test_helper.go | 15 +- 41 files changed, 839 insertions(+), 464 deletions(-) rename platforms/joystick/{joystick_dualshock3.go => joystick_dualshock3_darwin.go} (94%) create mode 100644 platforms/joystick/joystick_dualshock3_linux.go create mode 100644 platforms/joystick/joystick_dualshock3_windows.go create mode 100644 platforms/joystick/joystick_dualshock4_darwin.go rename platforms/joystick/{joystick_dualshock4.go => joystick_dualshock4_linux.go} (78%) create mode 100644 platforms/joystick/joystick_dualshock4_windows.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 2727f9153..e09013af6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,10 +38,10 @@ jobs: name: Debug version command: go version - run: - # digispark needs libusb, joystick needs sdl2, opencv needs opencv - name: Platform tests (except digispark, joystick, opencv) + # digispark needs libusb, opencv needs opencv + name: Platform tests (except digispark and opencv) command: | - go test -v $(go list ./platforms/... | grep -v platforms/digispark | grep -v platforms/joystick | grep -v platforms/opencv) + go test -v $(go list ./platforms/... | grep -v platforms/digispark | grep -v platforms/opencv) "check_examples": docker: @@ -52,11 +52,11 @@ jobs: name: Debug version command: go version - run: - # digispark needs libusb, joystick needs sdl2, opencv needs opencv - name: Check examples (except digispark, joystick, opencv) + # digispark needs libusb, opencv needs opencv + name: Check examples (except digispark, opencv) command: | ALL=$(grep -l -r --include "*.go" 'build example' ./) - SOME=$(grep -L 'digispark' $(grep -L 'joystick' $(grep -L 'gocv' ${ALL}))) + SOME=$(grep -L 'digispark' $(grep -L 'gocv' ${ALL})) for e in ${SOME} ; do go vet "${e}" ; done workflows: diff --git a/Makefile b/Makefile index 4d7c4b56d..7454c03ba 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,8 @@ ALL_EXAMPLES := $(shell grep -l -r --include "*.go" 'build example' ./) # prevent examples with gocv (opencv) dependencies EXAMPLES_NO_GOCV := $(shell grep -L 'gocv' $(ALL_EXAMPLES)) -# prevent examples with joystick (sdl2) dependencies -EXAMPLES_NO_JOYSTICK := $(shell grep -L 'joystick' $(ALL_EXAMPLES)) -# prevent examples with joystick (sdl2) and gocv (opencv) dependencies -EXAMPLES_NO_GOCV_JOYSTICK := $(shell grep -L 'joystick' $$(grep -L 'gocv' $(EXAMPLES_NO_GOCV))) # used examples -EXAMPLES := $(EXAMPLES_NO_GOCV_JOYSTICK) +EXAMPLES := $(EXAMPLES_NO_GOCV) .PHONY: test test_race test_cover robeaux version_check fmt_check fmt_fix examples examples_check $(EXAMPLES) diff --git a/appveyor.yml b/appveyor.yml index a2abb7d93..1bc2f7642 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,6 +16,10 @@ build_script: - go test -v -cpu=2 . - go test -v -cpu=2 ./drivers/aio/... - go test -v -cpu=2 ./drivers/i2c/... + - go test -v -cpu=2 ./platforms/dji/... - go test -v -cpu=2 ./platforms/firmata/... - go test -v -cpu=2 ./platforms/ble/... + - go test -v -cpu=2 ./platforms/joystick/... + - go test -v -cpu=2 ./platforms/parrot/... + - go test -v -cpu=2 ./platforms/sphero/... - cd .. diff --git a/examples/ardrone_ps3.go b/examples/ardrone_ps3.go index d7aad83e0..37dd20131 100644 --- a/examples/ardrone_ps3.go +++ b/examples/ardrone_ps3.go @@ -25,7 +25,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") ardroneAdaptor := ardrone.NewAdaptor() diff --git a/examples/bebop_ps3.go b/examples/bebop_ps3.go index 93b514348..743b7b0f2 100644 --- a/examples/bebop_ps3.go +++ b/examples/bebop_ps3.go @@ -25,7 +25,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") bebopAdaptor := bebop.NewAdaptor() diff --git a/examples/bebop_ps3_video.go b/examples/bebop_ps3_video.go index 74b38b672..007e782e3 100644 --- a/examples/bebop_ps3_video.go +++ b/examples/bebop_ps3_video.go @@ -83,7 +83,7 @@ func ffmpeg() (stdin io.WriteCloser, stderr io.ReadCloser, err error) { } func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") bebopAdaptor := bebop.NewAdaptor() diff --git a/examples/joystick_ps3.go b/examples/joystick_ps3.go index 2cdb55bc4..1d2f3a2ce 100644 --- a/examples/joystick_ps3.go +++ b/examples/joystick_ps3.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Dualshock3) work := func() { @@ -64,15 +64,27 @@ func main() { stick.On(joystick.RightPress, func(data interface{}) { fmt.Println("right_press") }) + stick.On(joystick.RightRelease, func(data interface{}) { + fmt.Println("right_release") + }) stick.On(joystick.LeftPress, func(data interface{}) { fmt.Println("left_press") }) + stick.On(joystick.LeftRelease, func(data interface{}) { + fmt.Println("left_release") + }) stick.On(joystick.UpPress, func(data interface{}) { fmt.Println("up_press") }) + stick.On(joystick.UpRelease, func(data interface{}) { + fmt.Println("up_release") + }) stick.On(joystick.DownPress, func(data interface{}) { fmt.Println("down_press") }) + stick.On(joystick.DownRelease, func(data interface{}) { + fmt.Println("down_release") + }) // joysticks stick.On(joystick.LeftX, func(data interface{}) { @@ -92,15 +104,27 @@ func main() { stick.On(joystick.R1Press, func(data interface{}) { fmt.Println("R1Press", data) }) + stick.On(joystick.R1Release, func(data interface{}) { + fmt.Println("R1Release", data) + }) stick.On(joystick.R2Press, func(data interface{}) { fmt.Println("R2Press", data) }) + stick.On(joystick.R2Release, func(data interface{}) { + fmt.Println("R2Release", data) + }) stick.On(joystick.L1Press, func(data interface{}) { fmt.Println("L1Press", data) }) + stick.On(joystick.L1Release, func(data interface{}) { + fmt.Println("L1Release", data) + }) stick.On(joystick.L2Press, func(data interface{}) { fmt.Println("L2Press", data) }) + stick.On(joystick.L2Release, func(data interface{}) { + fmt.Println("L2Release", data) + }) } robot := gobot.NewRobot("joystickBot", diff --git a/examples/joystick_ps4.go b/examples/joystick_ps4.go index 046c7bd0a..c824090d4 100644 --- a/examples/joystick_ps4.go +++ b/examples/joystick_ps4.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Dualshock4) work := func() { diff --git a/examples/joystick_ps5.go b/examples/joystick_ps5.go index fe8d1063b..d5cbf631b 100644 --- a/examples/joystick_ps5.go +++ b/examples/joystick_ps5.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Dualsense) work := func() { diff --git a/examples/joystick_xbox360.go b/examples/joystick_xbox360.go index 655cb3889..dff41efb3 100644 --- a/examples/joystick_xbox360.go +++ b/examples/joystick_xbox360.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Xbox360) work := func() { diff --git a/examples/joystick_xbox360_rock_band_drums.go b/examples/joystick_xbox360_rock_band_drums.go index a83c6993b..05c6bf0a2 100644 --- a/examples/joystick_xbox360_rock_band_drums.go +++ b/examples/joystick_xbox360_rock_band_drums.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Xbox360RockBandDrums) work := func() { diff --git a/examples/joystick_xboxone.go b/examples/joystick_xboxone.go index d29737c90..a680529e6 100644 --- a/examples/joystick_xboxone.go +++ b/examples/joystick_xboxone.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") joystick := joystick.NewDriver(joystickAdaptor, joystick.XboxOne) work := func() { diff --git a/examples/minidrone_mambo_ps3.go b/examples/minidrone_mambo_ps3.go index d38e4af6a..b7ccd9b3a 100644 --- a/examples/minidrone_mambo_ps3.go +++ b/examples/minidrone_mambo_ps3.go @@ -43,7 +43,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "./platforms/joystick/configs/dualshock3.json", ) diff --git a/examples/minidrone_ps3.go b/examples/minidrone_ps3.go index a09959ec9..7afd96053 100644 --- a/examples/minidrone_ps3.go +++ b/examples/minidrone_ps3.go @@ -43,7 +43,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") droneAdaptor := ble.NewClientAdaptor(os.Args[1]) diff --git a/examples/tello_facetracker.go b/examples/tello_facetracker.go index 1a65dfd65..38cc2bcc6 100644 --- a/examples/tello_facetracker.go +++ b/examples/tello_facetracker.go @@ -74,7 +74,7 @@ var ( flightData *tello.FlightData // joystick - joyAdaptor = joystick.NewAdaptor() + joyAdaptor = joystick.NewAdaptor("0") stick = joystick.NewDriver(joyAdaptor, "dualshock4") leftX, leftY, rightX, rightY atomic.Value ) diff --git a/examples/tello_ps3.go b/examples/tello_ps3.go index 5d4f998d0..fb0e2a7f1 100644 --- a/examples/tello_ps3.go +++ b/examples/tello_ps3.go @@ -37,7 +37,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") drone := tello.NewDriver("8888") diff --git a/go.mod b/go.mod index 044643eea..4338b5512 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module gobot.io/x/gobot/v2 go 1.18 require ( + github.com/0xcafed00d/joystick v1.0.1 github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 github.com/eclipse/paho.mqtt.golang v1.4.2 @@ -11,9 +12,9 @@ require ( github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e github.com/nats-io/nats.go v1.27.1 + github.com/nsf/termbox-go v1.1.1 github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f github.com/stretchr/testify v1.8.4 - github.com/veandco/go-sdl2 v0.4.35 github.com/warthog618/gpiod v0.8.1 go.bug.st/serial v1.5.0 gocv.io/x/gocv v0.33.0 @@ -34,6 +35,7 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/klauspost/compress v1.16.7 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 // indirect github.com/nats-io/nats-server/v2 v2.7.4 // indirect github.com/nats-io/nkeys v0.4.4 // indirect diff --git a/go.sum b/go.sum index f590e4b61..e77271270 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/0xcafed00d/joystick v1.0.1 h1:r4p2cRp4MHJWu1gArhGtumbkPxmr3tcOUTFqybEhplM= +github.com/0xcafed00d/joystick v1.0.1/go.mod h1:gzszjNgzP6jtCAeSdC9OqPVO5rO7TJuaw4P7eAjNzx8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/bgould/http v0.0.0-20190627042742-d268792bdee7/go.mod h1:BTqvVegvwifopl4KTEDth6Zezs9eR+lCWhvGKvkxJHE= github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f h1:gOO/tNZMjjvTKZWpY7YnXC72ULNLErRtp94LountVE8= @@ -52,6 +54,8 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/muka/go-bluetooth v0.0.0-20220830075246-0746e3a1ea53/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 h1:BuVRHr4HHJbk1DHyWkArJ7E8J/VA8ncCr/VLnQFazBo= @@ -67,6 +71,8 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY= +github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk= github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= @@ -100,8 +106,6 @@ github.com/tdakkota/win32metadata v0.1.0/go.mod h1:77e6YvX0LIVW+O81fhWLnXAxxcyu/ github.com/tinygo-org/cbgo v0.0.4 h1:3D76CRYbH03Rudi8sEgs/YO0x3JIMdyq8jlQtk/44fU= github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk= github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= -github.com/veandco/go-sdl2 v0.4.35 h1:NohzsfageDWGtCd9nf7Pc3sokMK/MOK+UA2QMJARWzQ= -github.com/veandco/go-sdl2 v0.4.35/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY= github.com/warthog618/gpiod v0.8.1 h1:+8iHpHd3fljAd6l4AT8jPbMDQNKdvBIpW/hmLgAcHiM= github.com/warthog618/gpiod v0.8.1/go.mod h1:A7v1hGR2eTsnkN+e9RoAPYgJG9bLJWtwyIIK+pgqC7s= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/platforms/joystick/LICENSE b/platforms/joystick/LICENSE index 257d22e97..f90ffa280 100644 --- a/platforms/joystick/LICENSE +++ b/platforms/joystick/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2018 The Hybrid Group +Copyright (c) 2014-2023 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. diff --git a/platforms/joystick/README.md b/platforms/joystick/README.md index 5e4b9d2cc..9f8f06740 100644 --- a/platforms/joystick/README.md +++ b/platforms/joystick/README.md @@ -1,6 +1,6 @@ # Joystick -You can use Gobot with any USB joystick or game controller that is compatible with [Simple DirectMedia Layer](http://www.libsdl.org/). +You can use Gobot with many USB joysticks and game controllers. Current configurations included: @@ -14,41 +14,24 @@ Current configurations included: ## How to Install -This package requires `sdl2` to be installed on your system +Any platform specific info here... ### macOS -To install `sdl2` on macOS using Homebrew: - -```sh -brew install sdl2 -``` - -To use an XBox360 controller on macOS, you will most likely need to install additional software such as [https://github.com/360Controller/360Controller](https://github.com/360Controller/360Controller). ### Linux (Ubuntu and Raspbian) -Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) -You must be running a Linux kernel that is v4.14+ in order for the various controller mappings to work as expected. +### Windows -Then you must install the latest SDL2 v2.0.8 or greater: - -```sh -wget https://www.libsdl.org/release/SDL2-2.0.8.tar.gz -tar -zxvf SDL2-2.0.8.tar.gz -cd SDL2-2.0.8/ -./configure && make && sudo make install -``` ## How to Use -Controller configurations are stored in Gobot it, but you can also use external file in JSON format. Take a look at the -`configs` directory for examples. +Controller configurations are stored in Gobot, but you can also use external file in JSON format. Take a look at the `configs` directory for examples. ## How to Connect -Plug your USB joystick or game controller into your USB port. If your device is supported by SDL, you are now ready. +Plug your USB joystick or game controller into your USB port. If your device is supported by your operating system, it might prompt you to install some system drivers. For the Dualshock4, you must pair the device with your computers Bluetooth interface first, before running your Gobot program. @@ -67,7 +50,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3", ) @@ -151,25 +134,4 @@ func main() { ## How to Add A New Joystick -In the `bin` directory for this package is a CLI utility program that scans for SDL joystick events, and displays the ID -and value: - -```sh -$ go run ./platforms/joystick/bin/scanner.go -Joystick 0 connected -[6625 ms] Axis: 1 value:-22686 -[6641 ms] Axis: 1 value:-32768 -[6836 ms] Axis: 1 value:-18317 -[6852 ms] Axis: 1 value:0 -[8663 ms] Axis: 3 value:-32768 -[8873 ms] Axis: 3 value:0 -[10183 ms] Axis: 0 value:-24703 -[10183 ms] Axis: 0 value:-32768 -[10313 ms] Axis: 1 value:-3193 -[10329 ms] Axis: 1 value:0 -[10345 ms] Axis: 0 value:0 -``` - -You can use the output from this program to create a JSON file for the various buttons and axes on your joystick/gamepad. -You could also create a file similar to `joystick_dualshock3.go` and submit a pull request with the new configuration so -others can use it as well. +You can create a file similar to `joystick_dualshock3.go` and submit a pull request with the new configuration so others can use it as well. diff --git a/platforms/joystick/bin/scanner.go b/platforms/joystick/bin/scanner.go index 66eff923d..ec74112c9 100644 --- a/platforms/joystick/bin/scanner.go +++ b/platforms/joystick/bin/scanner.go @@ -5,68 +5,108 @@ // Do not build by default. // // Joystick scanner -// Based on original code from Jacky Boen -// https://github.com/veandco/go-sdl2/blob/master/examples/events/events.go - +// Based on original code from +// https://github.com/0xcafed00d/joystick/blob/master/joysticktest/joysticktest.go +// Simple program that displays the state of the specified joystick +// +// go run joysticktest.go 2 +// displays state of joystick id 2 package main import ( "fmt" + "github.com/nsf/termbox-go" + "github.com/0xcafed00d/joystick" "os" - - "github.com/veandco/go-sdl2/sdl" + "strconv" + "time" ) -var joysticks [16]*sdl.Joystick - -func run() int { - var event sdl.Event - var running bool - - sdl.Init(sdl.INIT_JOYSTICK) - defer sdl.Quit() - - sdl.JoystickEventState(sdl.ENABLE) - - running = true - for running { - for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() { - switch t := event.(type) { - case *sdl.QuitEvent: - running = false - case *sdl.JoyAxisEvent: - fmt.Printf("[%d ms] Axis: %d\tvalue:%d\n", - t.Timestamp, t.Axis, t.Value) - case *sdl.JoyBallEvent: - fmt.Printf("[%d ms] Ball:%d\txrel:%d\tyrel:%d\n", - t.Timestamp, t.Ball, t.XRel, t.YRel) - case *sdl.JoyButtonEvent: - fmt.Printf("[%d ms] Button:%d\tstate:%d\n", - t.Timestamp, t.Button, t.State) - case *sdl.JoyHatEvent: - fmt.Printf("[%d ms] Hat:%d\tvalue:%d\n", - t.Timestamp, t.Hat, t.Value) - case *sdl.JoyDeviceAddedEvent: - joysticks[int(t.Which)] = sdl.JoystickOpen(int(t.Which)) - if joysticks[int(t.Which)] != nil { - fmt.Printf("Joystick %d connected\n", t.Which) - } - case *sdl.JoyDeviceRemovedEvent: - if joystick := joysticks[int(t.Which)]; joystick != nil { - joystick.Close() - } - fmt.Printf("Joystick %d disconnected\n", t.Which) - default: - fmt.Printf("Unknown event\n") - } +func printAt(x, y int, s string) { + for _, r := range s { + termbox.SetCell(x, y, r, termbox.ColorDefault, termbox.ColorDefault) + x++ + } +} + +func readJoystick(js joystick.Joystick) { + jinfo, err := js.Read() + + if err != nil { + printAt(1, 5, "Error: "+err.Error()) + return + } + + printAt(1, 5, "Buttons:") + for button := 0; button < js.ButtonCount(); button++ { + if jinfo.Buttons&(1< 1 { + i, err := strconv.Atoi(os.Args[1]) + if err != nil { + fmt.Println(err) + return + } + jsid = i + } + + js, jserr := joystick.Open(jsid) + + if jserr != nil { + fmt.Println(jserr) + return + } + + err := termbox.Init() + if err != nil { + panic(err) + } + defer termbox.Close() + + eventQueue := make(chan termbox.Event) + go func() { + for { + eventQueue <- termbox.PollEvent() + } + }() + + ticker := time.NewTicker(time.Millisecond * 40) + + for doQuit := false; !doQuit; { + select { + case ev := <-eventQueue: + if ev.Type == termbox.EventKey { + if ev.Ch == 'q' { + doQuit = true + } + } + if ev.Type == termbox.EventResize { + termbox.Flush() + } + + case <-ticker.C: + printAt(1, 0, "-- Press 'q' to Exit --") + printAt(1, 1, fmt.Sprintf("Joystick Name: %s", js.Name())) + printAt(1, 2, fmt.Sprintf(" Axis Count: %d", js.AxisCount())) + printAt(1, 3, fmt.Sprintf(" Button Count: %d", js.ButtonCount())) + readJoystick(js) + termbox.Flush() + } + } } diff --git a/platforms/joystick/configs/dualshock3.json b/platforms/joystick/configs/dualshock3.json index f74f5b963..24195932e 100644 --- a/platforms/joystick/configs/dualshock3.json +++ b/platforms/joystick/configs/dualshock3.json @@ -11,12 +11,20 @@ "id": 1 }, { - "name": "right_x", + "name": "l2", "id": 2 }, { - "name": "right_y", + "name": "right_x", "id": 3 + }, + { + "name": "right_y", + "id": 4 + }, + { + "name": "r2", + "id": 5 } ], "buttons": [ diff --git a/platforms/joystick/doc.go b/platforms/joystick/doc.go index c0f7c8f60..3b5fcd64e 100644 --- a/platforms/joystick/doc.go +++ b/platforms/joystick/doc.go @@ -1,11 +1,9 @@ /* -Package joystick provides the Gobot adaptor and drivers for game controllers that are compatible with SDL. +Package joystick provides the Gobot adaptor and drivers for game controllers and joysticks. Installing: - This package requires `sdl2` to be installed on your system - - Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) + Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) Example: @@ -19,10 +17,8 @@ Example: ) func main() { - joystickAdaptor := joystick.NewAdaptor() - joystick := joystick.NewDriver(joystickAdaptor, - "./platforms/joystick/configs/dualshock3.json", - ) + joystickAdaptor := joystick.NewAdaptor("0") + joystick := joystick.NewDriver(joystickAdaptor, "dualshock3") work := func() { joystick.On(joystick.Event("square_press"), func(data interface{}) { diff --git a/platforms/joystick/joystick_adaptor.go b/platforms/joystick/joystick_adaptor.go index 2d5f93789..fba07f6bd 100644 --- a/platforms/joystick/joystick_adaptor.go +++ b/platforms/joystick/joystick_adaptor.go @@ -1,38 +1,41 @@ package joystick import ( - "errors" + "fmt" + "strconv" "gobot.io/x/gobot/v2" - "github.com/veandco/go-sdl2/sdl" + js "github.com/0xcafed00d/joystick" ) -type joystick interface { - Close() - InstanceID() sdl.JoystickID -} - // Adaptor represents a connection to a joystick type Adaptor struct { name string - joystick joystick + id string + joystick js.Joystick connect func(*Adaptor) error } // NewAdaptor returns a new Joystick Adaptor. -func NewAdaptor() *Adaptor { +// Pass in the ID of the joystick you wish to connect to. +func NewAdaptor(id string) *Adaptor { return &Adaptor{ name: gobot.DefaultName("Joystick"), connect: func(j *Adaptor) error { - if err := sdl.Init(sdl.INIT_JOYSTICK); err != nil { - return err + i, err := strconv.Atoi(id) + if err != nil { + return fmt.Errorf("Invalid joystick ID: %v", err) } - if sdl.NumJoysticks() > 0 { - j.joystick = sdl.JoystickOpen(0) - return nil + + joy, err := js.Open(i) + if err != nil { + return fmt.Errorf("No joystick available: %v", err) } - return errors.New("No joystick available") + + j.id = id + j.joystick = joy + return nil }, } } diff --git a/platforms/joystick/joystick_adaptor_test.go b/platforms/joystick/joystick_adaptor_test.go index 4f11ca06a..3a96a2031 100644 --- a/platforms/joystick/joystick_adaptor_test.go +++ b/platforms/joystick/joystick_adaptor_test.go @@ -1,18 +1,18 @@ package joystick import ( - "errors" "strings" "testing" + "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) func initTestAdaptor() *Adaptor { - a := NewAdaptor() + a := NewAdaptor("6") a.connect = func(j *Adaptor) (err error) { j.joystick = &testJoystick{} return nil @@ -22,21 +22,22 @@ func initTestAdaptor() *Adaptor { func TestJoystickAdaptorName(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Joystick"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Joystick")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, a.Name(), "NewName") } func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) - a = NewAdaptor() - gobottest.Assert(t, a.Connect(), errors.New("No joystick available")) + a = NewAdaptor("6") + err := a.Connect() + assert.True(t, strings.HasPrefix(err.Error(), "No joystick available")) } func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() _ = a.Connect() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index 09634c234..c313f362d 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -6,7 +6,7 @@ import ( "os" "time" - "github.com/veandco/go-sdl2/sdl" + js "github.com/0xcafed00d/joystick" "gobot.io/x/gobot/v2" ) @@ -41,13 +41,15 @@ const ( // Driver represents a joystick type Driver struct { - name string - interval time.Duration - connection gobot.Connection - configPath string - config joystickConfig - poll func() sdl.Event - halt chan bool + name string + interval time.Duration + connection gobot.Connection + configPath string + config joystickConfig + buttonState map[int]bool + axisState map[int]int + + halt chan bool gobot.Eventer } @@ -57,20 +59,12 @@ type pair struct { ID int `json:"id"` } -// hat is a JSON representation of hat, name and id -type hat struct { - Hat int `json:"hat"` - Name string `json:"name"` - ID int `json:"id"` -} - // joystickConfig is a JSON representation of configuration values type joystickConfig struct { Name string `json:"name"` GUID string `json:"guid"` Axis []pair `json:"axis"` Buttons []pair `json:"buttons"` - Hats []hat `json:"Hats"` } // NewDriver returns a new Driver with a polling interval of @@ -82,13 +76,13 @@ type joystickConfig struct { // time.Duration: Interval at which the Driver is polled for new information func NewDriver(a *Adaptor, config string, v ...time.Duration) *Driver { d := &Driver{ - name: gobot.DefaultName("Joystick"), - connection: a, - Eventer: gobot.NewEventer(), - configPath: config, - poll: func() sdl.Event { - return sdl.PollEvent() - }, + name: gobot.DefaultName("Joystick"), + connection: a, + Eventer: gobot.NewEventer(), + configPath: config, + buttonState: make(map[int]bool), + axisState: make(map[int]int), + interval: 10 * time.Millisecond, halt: make(chan bool), } @@ -125,7 +119,43 @@ func (j *Driver) adaptor() *Adaptor { // [button]_press // [button]_release // [axis] -func (j *Driver) Start() (err error) { +func (j *Driver) Start() error { + if err := j.initConfig(); err != nil { + return err + } + + j.initEvents() + + go func() { + for { + state, err := j.adaptor().joystick.Read() + if err != nil { + j.Publish(j.Event("error"), err) + break + } + + // might just be missing a button definition, so keep going + if err := j.handleButtons(state); err != nil { + j.Publish(j.Event("error"), err) + } + + // might just be missing an axis definition, so keep going + if err := j.handleAxes(state); err != nil { + j.Publish(j.Event("error"), err) + } + + select { + case <-time.After(j.interval): + case <-j.halt: + return + } + } + }() + + return nil +} + +func (j *Driver) initConfig() error { switch j.configPath { case Dualshock3: j.config = dualshock3Config @@ -148,10 +178,14 @@ func (j *Driver) Start() (err error) { default: err := j.loadFile() if err != nil { - return err + return fmt.Errorf("loadfile error: %w", err) } } + return nil +} + +func (j *Driver) initEvents() { for _, value := range j.config.Buttons { j.AddEvent(fmt.Sprintf("%s_press", value.Name)) j.AddEvent(fmt.Sprintf("%s_release", value.Name)) @@ -159,26 +193,6 @@ func (j *Driver) Start() (err error) { for _, value := range j.config.Axis { j.AddEvent(value.Name) } - for _, value := range j.config.Hats { - j.AddEvent(fmt.Sprintf("%s_press", value.Name)) - j.AddEvent(fmt.Sprintf("%s_release", value.Name)) - } - - go func() { - for { - for event := j.poll(); event != nil; event = j.poll() { - if errs := j.handleEvent(event); errs != nil { - j.Publish(j.Event("error"), errs) - } - } - select { - case <-time.After(j.interval): - case <-j.halt: - return - } - } - }() - return } // Halt stops joystick driver @@ -187,48 +201,44 @@ func (j *Driver) Halt() (err error) { return } -var previousHat = "" - -// HandleEvent publishes an specific event according to data received -func (j *Driver) handleEvent(event sdl.Event) error { - switch data := event.(type) { - case *sdl.JoyAxisEvent: - if data.Which == j.adaptor().joystick.InstanceID() { - axis := j.findName(data.Axis, j.config.Axis) - if axis == "" { - return fmt.Errorf("Unknown Axis: %v", data.Axis) +func (j *Driver) handleButtons(state js.State) error { + for button := 0; button < j.adaptor().joystick.ButtonCount(); button++ { + buttonPressed := state.Buttons&(1< Date: Tue, 26 Sep 2023 11:26:07 -0700 Subject: [PATCH 03/57] sphero: Add support for calibration - Includes a sample program to show how it works. --- examples/sphero_calibration.go | 67 +++++++++++++++++++++++++++++++ platforms/sphero/sphero_driver.go | 35 ++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 examples/sphero_calibration.go diff --git a/examples/sphero_calibration.go b/examples/sphero_calibration.go new file mode 100644 index 000000000..d48d0542b --- /dev/null +++ b/examples/sphero_calibration.go @@ -0,0 +1,67 @@ +//go:build example +// +build example + +// +// Do not build by default. + +package main + +import ( + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/api" + "gobot.io/x/gobot/v2/platforms/keyboard" + "gobot.io/x/gobot/v2/platforms/sphero" +) + +func main() { + master := gobot.NewMaster() + a := api.NewAPI(master) + a.Start() + + ballConn := sphero.NewAdaptor("/dev/rfcomm0") + ball := sphero.NewSpheroDriver(ballConn) + + keys := keyboard.NewDriver() + + calibrating := false + + work := func() { + keys.On(keyboard.Key, func(data interface{}) { + key := data.(keyboard.KeyEvent) + + switch key.Key { + case keyboard.ArrowUp: + if calibrating { + break + } + ball.Roll(100, 0) + case keyboard.ArrowDown: + if calibrating { + break + } + ball.Roll(100, 100) + case keyboard.ArrowLeft: + ball.Roll(100, 270) + case keyboard.ArrowRight: + ball.Roll(100, 90) + case keyboard.Spacebar: + if calibrating { + ball.FinishCalibration() + } else { + ball.StartCalibration() + } + calibrating = !calibrating + } + }) + } + + robot := gobot.NewRobot("sphero-calibration", + []gobot.Connection{ballConn}, + []gobot.Device{ball, keys}, + work, + ) + + master.AddRobot(robot) + + master.Start() +} diff --git a/platforms/sphero/sphero_driver.go b/platforms/sphero/sphero_driver.go index 04b74f426..e1f568a98 100644 --- a/platforms/sphero/sphero_driver.go +++ b/platforms/sphero/sphero_driver.go @@ -37,6 +37,7 @@ type SpheroDriver struct { syncResponse [][]uint8 packetChannel chan *packet responseChannel chan []uint8 + originalColor []uint8 // Only used for calibration. gobot.Eventer gobot.Commander } @@ -322,6 +323,40 @@ func (s *SpheroDriver) ConfigureCollisionDetection(cc CollisionConfig) { s.packetChannel <- s.craftPacket([]uint8{cc.Method, cc.Xt, cc.Yt, cc.Xs, cc.Ys, cc.Dead}, 0x02, 0x12) } +// SetCalibration sets up Sphero for manual heading calibration. +// It does this by turning on the tail light (so you can tell where it's +// facing) and disabling stabilization (so you can adjust the heading). +// +// When done, call FinishCalibration to set the new heading, and re-enable +// stabilization. +func (s *SpheroDriver) StartCalibration() { + s.mtx.Lock() + s.originalColor = s.GetRGB() + s.SetRGB(0, 0, 0) + s.SetBackLED(127) + s.SetStabilization(false) + s.mtx.Unlock() +} + +// FinishCalibration ends Sphero's calibration mode, by setting +// the new heading as current, and re-enabling normal defaults. This is a NOP +// in case StartCalibration was not called. +func (s *SpheroDriver) FinishCalibration() { + s.mtx.Lock() + if s.originalColor == nil { + // Piggybacking on the original color being set to know if we are + // calibrating or not. + return + } + + s.SetHeading(0) + s.SetRGB(s.originalColor[0], s.originalColor[1], s.originalColor[2]) + s.SetBackLED(0) + s.SetStabilization(true) + s.originalColor = nil + s.mtx.Unlock() +} + func (s *SpheroDriver) enableStopOnDisconnect() { s.packetChannel <- s.craftPacket([]uint8{0x00, 0x00, 0x00, 0x01}, 0x02, 0x37) } From c73f0f2385b02235b376a8f103fc019c5764a459 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Wed, 18 Oct 2023 19:32:22 +0200 Subject: [PATCH 04/57] build(deps): module update (#992) --- go.mod | 31 +++++++------- go.sum | 130 ++++++++++++++------------------------------------------- 2 files changed, 45 insertions(+), 116 deletions(-) diff --git a/go.mod b/go.mod index 4338b5512..332e93d57 100644 --- a/go.mod +++ b/go.mod @@ -6,46 +6,43 @@ require ( github.com/0xcafed00d/joystick v1.0.1 github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 - github.com/eclipse/paho.mqtt.golang v1.4.2 + github.com/eclipse/paho.mqtt.golang v1.4.3 github.com/gofrs/uuid v4.4.0+incompatible github.com/hashicorp/go-multierror v1.1.1 github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e - github.com/nats-io/nats.go v1.27.1 + github.com/nats-io/nats.go v1.31.0 github.com/nsf/termbox-go v1.1.1 github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f github.com/stretchr/testify v1.8.4 - github.com/warthog618/gpiod v0.8.1 - go.bug.st/serial v1.5.0 - gocv.io/x/gocv v0.33.0 - golang.org/x/net v0.12.0 - golang.org/x/sys v0.10.0 + github.com/warthog618/gpiod v0.8.2 + go.bug.st/serial v1.6.1 + gocv.io/x/gocv v0.35.0 + golang.org/x/net v0.17.0 + golang.org/x/sys v0.13.0 periph.io/x/conn/v3 v3.7.0 periph.io/x/host/v3 v3.8.2 - tinygo.org/x/bluetooth v0.7.0 + tinygo.org/x/bluetooth v0.8.0 ) require ( github.com/creack/goselect v0.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/structs v1.1.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/golang/protobuf v1.5.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.1 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 // indirect - github.com/nats-io/nats-server/v2 v2.7.4 // indirect - github.com/nats-io/nkeys v0.4.4 // indirect + github.com/nats-io/nkeys v0.4.5 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/saltosystems/winrt-go v0.0.0-20230613063811-c792451fa808 // indirect + github.com/saltosystems/winrt-go v0.0.0-20231011131235-9071442c0c84 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/tinygo-org/cbgo v0.0.4 // indirect - golang.org/x/crypto v0.11.0 // indirect - golang.org/x/sync v0.3.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/sync v0.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e77271270..1b2be75a9 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ github.com/0xcafed00d/joystick v1.0.1 h1:r4p2cRp4MHJWu1gArhGtumbkPxmr3tcOUTFqybEhplM= github.com/0xcafed00d/joystick v1.0.1/go.mod h1:gzszjNgzP6jtCAeSdC9OqPVO5rO7TJuaw4P7eAjNzx8= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/bgould/http v0.0.0-20190627042742-d268792bdee7/go.mod h1:BTqvVegvwifopl4KTEDth6Zezs9eR+lCWhvGKvkxJHE= github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f h1:gOO/tNZMjjvTKZWpY7YnXC72ULNLErRtp94LountVE8= github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= @@ -11,32 +9,20 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 h1:C7t6eeMaEQVy6e8CarIhscYQlNmw5e3G36y7l7Y21Ao= github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw= -github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/eclipse/paho.mqtt.golang v1.4.2 h1:66wOzfUHSSI1zamx7jR6yMEI5EuHnT1G6rNA5PM12m4= -github.com/eclipse/paho.mqtt.golang v1.4.2/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2b7upDZMK9HRbFvCA= +github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik= +github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s= -github.com/glerchundi/subcommands v0.0.0-20181212083838-923a6ccb11f8/go.mod h1:r0g3O7Y5lrWXgDfcFBRgnAKzjmPgTzwoMC2ieB345FY= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hajimehoshi/go-jisx0208 v1.0.0/go.mod h1:yYxEStHL7lt9uL+AbdWgW9gBumwieDoZCiB1f/0X0as= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -46,27 +32,21 @@ github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 h1:7of6LJZ4 github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78/go.mod h1:YllNbhGM1UEcySxCv1BWK5lre7QLmJJ+O0ADUOo2nbc= github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e h1:xCcwD5FOXul+j1dn8xD16nbrhJkkum/Cn+jTd/u1LhY= github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM805MRKrioHYuU7iKLUyFPVKqVV6um5DAvCkUtXs= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g= +github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= -github.com/muka/go-bluetooth v0.0.0-20220830075246-0746e3a1ea53/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 h1:BuVRHr4HHJbk1DHyWkArJ7E8J/VA8ncCr/VLnQFazBo= github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= -github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296 h1:vU9tpM3apjYlLLeY23zRWJ9Zktr5jp+mloR942LEOpY= -github.com/nats-io/nats-server/v2 v2.7.4 h1:c+BZJ3rGzUKCBIM4IXO8uNT2u1vajGbD1kPA6wqCEaM= -github.com/nats-io/nats-server/v2 v2.7.4/go.mod h1:1vZ2Nijh8tcyNe8BDVyTviCd9NYzRbubQYiEHsvOQWc= -github.com/nats-io/nats.go v1.27.1 h1:OuYnal9aKVSnOzLQIzf7554OXMCG7KbaTkCSBHRcSoo= -github.com/nats-io/nats.go v1.27.1/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= -github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA= -github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= +github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= +github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= +github.com/nats-io/nkeys v0.4.5 h1:Zdz2BUlFm4fJlierwvGK+yl20IAKUm7eV6AAZXEhkPk= +github.com/nats-io/nkeys v0.4.5/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -75,106 +55,68 @@ github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY= github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk= -github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= -github.com/peterbourgon/ff/v3 v3.1.2/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE= -github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sago35/go-bdf v0.0.0-20200313142241-6c17821c91c4/go.mod h1:rOebXGuMLsXhZAC6mF/TjxONsm45498ZyzVhel++6KM= -github.com/saltosystems/winrt-go v0.0.0-20230510070731-e096b9afa761/go.mod h1:UvKm1lyhg+8ehk99i8g5Q7AX1LXUJgks0lRyAkG/ahQ= -github.com/saltosystems/winrt-go v0.0.0-20230613063811-c792451fa808 h1:OmW/lr7pviC5Fcsiz3qqc8dh0uo1r3EqqI/mDTSpGmc= -github.com/saltosystems/winrt-go v0.0.0-20230613063811-c792451fa808/go.mod h1:UvKm1lyhg+8ehk99i8g5Q7AX1LXUJgks0lRyAkG/ahQ= +github.com/saltosystems/winrt-go v0.0.0-20231011131235-9071442c0c84 h1:LX7qSkrsG8fKKVubiUnqfGdi/yBBnVTBR13LkqXycog= +github.com/saltosystems/winrt-go v0.0.0-20231011131235-9071442c0c84/go.mod h1:CIltaIm7qaANUIvzr0Vmz71lmQMAIbGJ7cvgzX7FMfA= github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f h1:1R9KdKjCNSd7F8iGTxIpoID9prlYH8nuNYKt0XvweHA= github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f/go.mod h1:vQhwQ4meQEDfahT5kd61wLAF5AAeh5ZPLVI4JJ/tYo8= github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/suapapa/go_eddystone v1.3.1/go.mod h1:bXC11TfJOS+3g3q/Uzd7FKd5g62STQEfeEIhcKe4Qy8= -github.com/tdakkota/win32metadata v0.1.0/go.mod h1:77e6YvX0LIVW+O81fhWLnXAxxcyu/wdZdG7iwed7Fyk= github.com/tinygo-org/cbgo v0.0.4 h1:3D76CRYbH03Rudi8sEgs/YO0x3JIMdyq8jlQtk/44fU= github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk= -github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= -github.com/warthog618/gpiod v0.8.1 h1:+8iHpHd3fljAd6l4AT8jPbMDQNKdvBIpW/hmLgAcHiM= -github.com/warthog618/gpiod v0.8.1/go.mod h1:A7v1hGR2eTsnkN+e9RoAPYgJG9bLJWtwyIIK+pgqC7s= +github.com/warthog618/go-gpiosim v0.1.0 h1:2rTMTcKUVZxpUuvRKsagnKAbKpd3Bwffp87xywEDVGI= +github.com/warthog618/gpiod v0.8.2 h1:2HgQ9pNowPp7W77sXhX5ut5Tqq1WoS3t7bXYDxtYvxc= +github.com/warthog618/gpiod v0.8.2/go.mod h1:O7BNpHjCn/4YS5yFVmoFZAlY1LuYuQ8vhPf0iy/qdi4= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.bug.st/serial v1.5.0 h1:ThuUkHpOEmCVXxGEfpoExjQCS2WBVV4ZcUKVYInM9T4= -go.bug.st/serial v1.5.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= -gocv.io/x/gocv v0.33.0 h1:WDtaBrq92AKrhepYzEktydDzNSm3t5k7ciawZK4rns8= -gocv.io/x/gocv v0.33.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU= +go.bug.st/serial v1.6.1 h1:VSSWmUxlj1T/YlRo2J104Zv3wJFrjHIl/T3NeruWAHY= +go.bug.st/serial v1.6.1/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= +gocv.io/x/gocv v0.35.0 h1:Qaxb5KdVyy8Spl4S4K0SMZ6CVmKtbfoSGQAxRD3FZlw= +gocv.io/x/gocv v0.35.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220617043117-41969df76e82/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -182,15 +124,5 @@ periph.io/x/conn/v3 v3.7.0 h1:f1EXLn4pkf7AEWwkol2gilCNZ0ElY+bxS4WE2PQXfrA= periph.io/x/conn/v3 v3.7.0/go.mod h1:ypY7UVxgDbP9PJGwFSVelRRagxyXYfttVh7hJZUHEhg= periph.io/x/host/v3 v3.8.2 h1:ayKUDzgUCN0g8+/xM9GTkWaOBhSLVcVHGTfjAOi8OsQ= periph.io/x/host/v3 v3.8.2/go.mod h1:yFL76AesNHR68PboofSWYaQTKmvPXsQH2Apvp/ls/K4= -tinygo.org/x/bluetooth v0.7.0 h1:7lU0VrauwccbLvb6AKHf4ZedFlxZIFwwqHWQD2fLWvA= -tinygo.org/x/bluetooth v0.7.0/go.mod h1:2hZPpfPDMR7Vvi6yMvyi83o8gYXeMKKsLfUnvmtBcjM= -tinygo.org/x/drivers v0.14.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI= -tinygo.org/x/drivers v0.15.1/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI= -tinygo.org/x/drivers v0.16.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI= -tinygo.org/x/drivers v0.19.0/go.mod h1:uJD/l1qWzxzLx+vcxaW0eY464N5RAgFi1zTVzASFdqI= -tinygo.org/x/drivers v0.25.0/go.mod h1:v+mXaA4cgpz/YZJ3ZPm/86bYQJAXTaYtMkHlVwbodbw= -tinygo.org/x/tinyfont v0.2.1/go.mod h1:eLqnYSrFRjt5STxWaMeOWJTzrKhXqpWw7nU3bPfKOAM= -tinygo.org/x/tinyfont v0.3.0/go.mod h1:+TV5q0KpwSGRWnN+ITijsIhrWYJkoUCp9MYELjKpAXk= -tinygo.org/x/tinyfont v0.4.0/go.mod h1:7nVj3j3geqBoPDzpFukAhF1C8AP9YocMsZy0HSAcGCA= -tinygo.org/x/tinyfs v0.1.0/go.mod h1:ysc8Y92iHfhTXeyEM9+c7zviUQ4fN9UCFgSOFfMWv20= -tinygo.org/x/tinyterm v0.1.0/go.mod h1:/DDhNnGwNF2/tNgHywvyZuCGnbH3ov49Z/6e8LPLRR4= +tinygo.org/x/bluetooth v0.8.0 h1:WmuRebsODcUUIlGhesyuNRIAEIUCErhKlrZ9K9aimdI= +tinygo.org/x/bluetooth v0.8.0/go.mod h1:cfsVc0/nGo3nzi6+CeQaXb+anNlmEnSABkKsxer8OAE= From 124499d9cea72c5db66e0ee003a115902df25aa5 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Thu, 19 Oct 2023 18:08:03 +0200 Subject: [PATCH 05/57] adaptors(PWM): fix wrong duty cycle after kill program (#994) --- platforms/adaptors/pwmpinsadaptor.go | 2 +- platforms/adaptors/pwmpinsadaptor_test.go | 21 +++++++++++++++++-- .../beaglebone/beaglebone_adaptor_test.go | 2 ++ platforms/chip/chip_adaptor_test.go | 10 +++++++++ platforms/upboard/up2/adaptor_test.go | 8 +++++++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/platforms/adaptors/pwmpinsadaptor.go b/platforms/adaptors/pwmpinsadaptor.go index 11c2969bf..914771940 100644 --- a/platforms/adaptors/pwmpinsadaptor.go +++ b/platforms/adaptors/pwmpinsadaptor.go @@ -191,7 +191,7 @@ func (a *PWMPinsAdaptor) getDefaultInitializer() func(gobot.PWMPinner) error { return err } } - if err := setPeriod(pin, a.periodDefault, false); err != nil { + if err := setPeriod(pin, a.periodDefault, a.adjustDutyOnSetPeriod); err != nil { return err } // period needs to be set >1 before all next statements diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index 87f8f2f58..0421dcb0f 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -2,6 +2,7 @@ package adaptors import ( "fmt" + "log" "runtime" "strconv" "strings" @@ -127,6 +128,8 @@ func TestPWMPinsFinalize(t *testing.T) { sys := system.NewAccesser() fs := sys.UseMockFilesystem(pwmMockPaths) a := NewPWMPinsAdaptor(sys, testPWMPinTranslator) + fs.Files[pwmPeriodPath].Contents = "0" + fs.Files[pwmDutyCyclePath].Contents = "0" // assert that finalize before connect is working gobottest.Assert(t, a.Finalize(), nil) // arrange @@ -270,12 +273,15 @@ func Test_PWMPin(t *testing.T) { var tests = map[string]struct { mockPaths []string period string + dutyCycle string translate func(string) (string, int, error) pin string wantErr string }{ "pin_ok": { mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmDutyCyclePath, pwmPolarityPath}, + period: "0", + dutyCycle: "0", translate: translator, pin: "33", }, @@ -293,18 +299,23 @@ func Test_PWMPin(t *testing.T) { wantErr: "SetEnabled(false) failed for id 44 with : /sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/enable: no such file", }, "init_setperiod_dutycycle_no_error": { - mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmPolarityPath}, + mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmDutyCyclePath, pwmPolarityPath}, + period: "0", + dutyCycle: "0", translate: translator, pin: "33", }, "init_setperiod_error": { - mockPaths: []string{pwmExportPath, pwmEnablePath}, + mockPaths: []string{pwmExportPath, pwmEnablePath, pwmDutyCyclePath}, + dutyCycle: "0", translate: translator, pin: "33", wantErr: "SetPeriod(10000000) failed for id 44 with : /sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/period: no such file", }, "init_setpolarity_error": { mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmDutyCyclePath}, + period: "0", + dutyCycle: "0", translate: translator, pin: "33", wantErr: "SetPolarity(normal) failed for id 44 with : /sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/polarity: no such file", @@ -322,6 +333,9 @@ func Test_PWMPin(t *testing.T) { if tc.period != "" { fs.Files[pwmPeriodPath].Contents = tc.period } + if tc.dutyCycle != "" { + fs.Files[pwmDutyCyclePath].Contents = tc.dutyCycle + } a := NewPWMPinsAdaptor(sys, tc.translate) if err := a.Connect(); err != nil { panic(err) @@ -333,6 +347,9 @@ func Test_PWMPin(t *testing.T) { gobottest.Assert(t, err, nil) gobottest.Refute(t, got, nil) } else { + if !strings.Contains(err.Error(), tc.wantErr) { + log.Println(err.Error()) + } gobottest.Assert(t, strings.Contains(err.Error(), tc.wantErr), true) gobottest.Assert(t, got, nil) } diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index ed5e5a38f..b64c75a61 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -54,6 +54,8 @@ func TestPWM(t *testing.T) { } a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) + fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents = "0" + fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/period"].Contents = "0" gobottest.Assert(t, a.PwmWrite("P9_99", 175), errors.New("'P9_99' is not a valid id for a PWM pin")) _ = a.PwmWrite("P9_21", 175) diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index 612b22164..4111d5482 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -81,6 +81,9 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() + fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" + fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" + gobottest.Assert(t, a.Connect(), nil) gobottest.Assert(t, a.PwmWrite("PWM0", 100), nil) @@ -122,6 +125,9 @@ func TestProDigitalIO(t *testing.T) { func TestPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() + fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" + fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" + _ = a.Connect() err := a.PwmWrite("PWM0", 100) @@ -130,17 +136,21 @@ func TestPWM(t *testing.T) { gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/export"].Contents, "0") gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents, "1") gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "3921568") + gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") // pwmPeriodDefault gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents, "normal") err = a.ServoWrite("PWM0", 0) gobottest.Assert(t, err, nil) gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "500000") + gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") err = a.ServoWrite("PWM0", 180) gobottest.Assert(t, err, nil) gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "2000000") + gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") // pwmPeriodDefault + gobottest.Assert(t, a.Finalize(), nil) } diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index 83ac48334..8b76f9766 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -82,6 +82,8 @@ func TestDigitalIO(t *testing.T) { func TestPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) + fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" + fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" err := a.PwmWrite("32", 100) gobottest.Assert(t, err, nil) @@ -89,17 +91,21 @@ func TestPWM(t *testing.T) { gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/export"].Contents, "0") gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents, "1") gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "3921568") + gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") // pwmPeriodDefault gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents, "normal") err = a.ServoWrite("32", 0) gobottest.Assert(t, err, nil) gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "500000") + gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") err = a.ServoWrite("32", 180) gobottest.Assert(t, err, nil) gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "2000000") + gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") + gobottest.Assert(t, a.Finalize(), nil) } @@ -116,6 +122,8 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) + fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" + fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" gobottest.Assert(t, a.PwmWrite("32", 1), nil) From 42d1446861e559c16d7a406aff0e98bf9483f0b4 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Thu, 19 Oct 2023 18:42:26 +0200 Subject: [PATCH 06/57] doc(roadmap): remove file ROADMAP.md after creating issues (#1005) --- ROADMAP.md | 56 ------------------------------------------------------ 1 file changed, 56 deletions(-) delete mode 100644 ROADMAP.md diff --git a/ROADMAP.md b/ROADMAP.md deleted file mode 100644 index fb199b62b..000000000 --- a/ROADMAP.md +++ /dev/null @@ -1,56 +0,0 @@ -# Roadmap - -This is the roadmap of what we as a community want to see happen with Gobot. It should be considered more as a statement of direction then a list of tasks. - -Requests for changes to the roadmap should be made in the form of pull requests to this document. - -Anything tied to any implementation, including requests for platform support, bug reports, or other specifics should still be made by creating a new issue here: - - - -## core - -- standardized logging -- use Context to allow for graceful exits. - -## api - -- ability to plug in your own router to handle API calls, for example to serve a custom web app. -- restrict API calls to only specific set of entrypoints. -- serve other transports/protocols other than HTTP/REST for example CoAP. - -## gpio - -- support for epoll/interrupt based gpio events. -- helper method for interrupts to handle "ping" timing-based devices. -- Windows 10 support. -- use variadic constructor functions to allow for additional params, similar to i2c drivers. - -## aio - -- support for epoll based aio events possible? -- Windows 10 support. -- use variadic constructor functions to allow for additional params, similar to i2c drivers. - -## i2c - -add support for the following i2c devices: - -- MAG3110 -- MMA8452 -- T5403 -- TMP006 -- VCNL4000 - -## 1-wire - -- add support for 1-wire protocol. - -## serial - -- create a common serial Adaptor, so different serial devices such as GPS, LIDAR etc only need to implement drivers. - -## ble - -- improve the ble package to allow support for multiple peripherals. -- Windows 10 support. From 3039b2c7cb9a8eb9e290de3cbfcd155305b15d96 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Fri, 20 Oct 2023 10:27:09 +0200 Subject: [PATCH 07/57] test(all): switch to test package stretchr testify (#1006) --- api/api_test.go | 84 +++---- api/basic_auth_test.go | 6 +- api/cors_test.go | 40 ++-- commander_test.go | 18 +- drivers/aio/analog_actuator_driver_test.go | 48 ++-- drivers/aio/analog_sensor_driver_test.go | 46 ++-- drivers/aio/grove_drivers_test.go | 10 +- .../grove_temperature_sensor_driver_test.go | 20 +- drivers/aio/temperature_sensor_driver_test.go | 34 +-- drivers/common/mfrc522/mfrc522_pcd_test.go | 68 +++--- drivers/gpio/aip1640_driver_test.go | 24 +- drivers/gpio/button_driver_test.go | 24 +- drivers/gpio/buzzer_driver_test.go | 23 +- drivers/gpio/direct_pin_driver_test.go | 60 ++--- drivers/gpio/easy_driver_test.go | 78 +++---- drivers/gpio/grove_drivers_test.go | 10 +- drivers/gpio/hd44780_driver_test.go | 66 +++--- drivers/gpio/led_driver_test.go | 28 +-- drivers/gpio/makey_button_driver_test.go | 20 +- drivers/gpio/max7219_driver_test.go | 10 +- drivers/gpio/motor_driver_test.go | 42 ++-- drivers/gpio/pir_motion_driver_test.go | 18 +- drivers/gpio/relay_driver_test.go | 78 +++---- drivers/gpio/rgb_led_driver_test.go | 36 +-- drivers/gpio/servo_driver_test.go | 32 +-- drivers/gpio/stepper_driver_test.go | 33 ++- drivers/gpio/tm1638_driver_test.go | 16 +- drivers/i2c/adafruit1109_driver_test.go | 102 ++++----- drivers/i2c/adafruit_driver_test.go | 84 +++---- drivers/i2c/ads1x15_driver_1015_test.go | 98 ++++----- drivers/i2c/ads1x15_driver_1115_test.go | 98 ++++----- drivers/i2c/ads1x15_driver_test.go | 27 ++- drivers/i2c/adxl345_driver_test.go | 106 ++++----- drivers/i2c/bh1750_driver_test.go | 26 +-- drivers/i2c/blinkm_driver_test.go | 40 ++-- drivers/i2c/bme280_driver_test.go | 52 ++--- drivers/i2c/bmp180_driver_test.go | 68 +++--- drivers/i2c/bmp280_driver_test.go | 98 ++++----- drivers/i2c/bmp388_driver_test.go | 88 ++++---- drivers/i2c/ccs811_driver_test.go | 52 ++--- drivers/i2c/drv2605l_driver_test.go | 46 ++-- drivers/i2c/generic_driver_test.go | 6 +- drivers/i2c/grove_drivers_test.go | 14 +- drivers/i2c/grovepi_driver_test.go | 40 ++-- drivers/i2c/hmc5883l_driver_test.go | 66 +++--- drivers/i2c/hmc6352_driver_test.go | 28 +-- drivers/i2c/i2c_config_test.go | 14 +- drivers/i2c/i2c_connection_test.go | 47 ++-- drivers/i2c/i2c_driver_test.go | 52 +++-- drivers/i2c/ina3221_driver_test.go | 38 ++-- drivers/i2c/jhd1313m1_driver_test.go | 66 +++--- drivers/i2c/l3gd20h_driver_test.go | 54 ++--- drivers/i2c/lidarlite_driver_test.go | 38 ++-- drivers/i2c/mcp23017_driver_test.go | 186 ++++++++-------- drivers/i2c/mma7660_driver_test.go | 36 +-- drivers/i2c/mpl115a2_driver_test.go | 52 ++--- drivers/i2c/mpu6050_driver_test.go | 76 +++---- drivers/i2c/pca9501_driver_test.go | 88 ++++---- drivers/i2c/pca953x_driver_test.go | 88 ++++---- drivers/i2c/pca9685_driver_test.go | 44 ++-- drivers/i2c/pcf8583_driver_test.go | 206 +++++++++--------- drivers/i2c/pcf8591_driver_test.go | 50 ++--- drivers/i2c/sht2x_driver_test.go | 45 ++-- drivers/i2c/sht3x_driver_test.go | 62 +++--- drivers/i2c/ssd1306_driver_test.go | 69 +++--- drivers/i2c/th02_driver_test.go | 62 +++--- drivers/i2c/tsl2561_driver_test.go | 134 ++++++------ drivers/i2c/wiichuck_driver_test.go | 116 +++++----- drivers/i2c/yl40_driver_test.go | 118 +++++----- drivers/spi/apa102_test.go | 8 +- drivers/spi/mcp3002_test.go | 16 +- drivers/spi/mcp3004_test.go | 16 +- drivers/spi/mcp3008_test.go | 16 +- drivers/spi/mcp3202_test.go | 16 +- drivers/spi/mcp3204_test.go | 16 +- drivers/spi/mcp3208_test.go | 16 +- drivers/spi/mcp3304_test.go | 16 +- drivers/spi/mfrc522_driver_test.go | 10 +- drivers/spi/spi_connection_test.go | 36 +-- drivers/spi/spi_driver_test.go | 12 +- drivers/spi/ssd1306_driver_test.go | 13 +- eventer_test.go | 4 +- gobottest/gobottest.go | 45 ---- gobottest/gobottest_test.go | 42 ---- master_test.go | 54 ++--- platforms/adaptors/digitalpinsadaptor_test.go | 92 ++++---- platforms/adaptors/i2cbusadaptor_test.go | 67 +++--- platforms/adaptors/pwmpinsadaptor_test.go | 138 ++++++------ platforms/adaptors/spibusadaptor_test.go | 65 +++--- platforms/audio/audio_adaptor_test.go | 35 +-- platforms/audio/audio_driver_test.go | 20 +- .../beaglebone/beaglebone_adaptor_test.go | 99 +++++---- platforms/ble/battery_driver_test.go | 12 +- platforms/ble/ble_client_adaptor_test.go | 8 +- .../ble/device_information_driver_test.go | 20 +- platforms/ble/generic_access_driver_test.go | 14 +- platforms/ble/serial_port_test.go | 4 +- platforms/chip/chip_adaptor_test.go | 81 ++++--- platforms/dexter/gopigo3/driver_test.go | 6 +- platforms/digispark/digispark_adaptor_test.go | 38 ++-- platforms/digispark/digispark_i2c_test.go | 171 ++++++++------- platforms/dji/tello/driver_test.go | 6 +- platforms/dji/tello/pitch_test.go | 8 +- .../dragonboard/dragonboard_adaptor_test.go | 33 ++- platforms/firmata/ble_firmata_adaptor_test.go | 4 +- platforms/firmata/client/client_test.go | 60 ++--- platforms/firmata/firmata_adaptor_test.go | 52 ++--- platforms/firmata/firmata_i2c_test.go | 101 +++++---- platforms/firmata/tcp_firmata_adaptor_test.go | 4 +- .../holystone/hs200/hs200_driver_test.go | 6 +- platforms/intel-iot/curie/imu_driver_test.go | 83 ++++--- .../intel-iot/edison/edison_adaptor_test.go | 136 ++++++------ .../intel-iot/joule/joule_adaptor_test.go | 45 ++-- platforms/jetson/jetson_adaptor_test.go | 67 +++--- platforms/jetson/pwm_pin_test.go | 35 ++- platforms/joystick/joystick_driver_test.go | 2 +- platforms/keyboard/keyboard_driver_test.go | 12 +- platforms/keyboard/keyboard_test.go | 44 ++-- platforms/leap/leap_motion_adaptor_test.go | 14 +- platforms/leap/leap_motion_driver_test.go | 36 +-- platforms/mavlink/mavlink_adaptor_test.go | 16 +- platforms/mavlink/mavlink_driver_test.go | 18 +- platforms/mavlink/mavlink_udp_adaptor_test.go | 20 +- .../microbit/accelerometer_driver_test.go | 16 +- platforms/microbit/button_driver_test.go | 10 +- platforms/microbit/io_pin_driver_test.go | 46 ++-- platforms/microbit/led_driver_test.go | 32 +-- .../microbit/magnetometer_driver_test.go | 16 +- platforms/microbit/temperature_driver_test.go | 12 +- platforms/mqtt/mqtt_adaptor_test.go | 55 +++-- platforms/mqtt/mqtt_driver_test.go | 22 +- platforms/nanopi/nanopi_adaptor_test.go | 112 +++++----- platforms/nats/nats_adaptor_test.go | 67 +++--- platforms/nats/nats_driver_test.go | 18 +- platforms/neurosky/neurosky_adaptor_test.go | 16 +- platforms/neurosky/neurosky_driver_test.go | 30 +-- platforms/opencv/camera_driver_test.go | 18 +- platforms/opencv/utils_test.go | 4 +- platforms/opencv/window_driver_test.go | 14 +- .../parrot/ardrone/ardrone_adaptor_test.go | 16 +- .../parrot/ardrone/ardrone_driver_test.go | 12 +- platforms/parrot/ardrone/pitch_test.go | 8 +- platforms/parrot/bebop/bebop_adaptor_test.go | 12 +- platforms/parrot/bebop/bebop_driver_test.go | 6 +- platforms/parrot/bebop/pitch_test.go | 8 +- .../parrot/minidrone/minidrone_driver_test.go | 110 +++++----- platforms/parrot/minidrone/pitch_test.go | 8 +- platforms/particle/adaptor_test.go | 62 +++--- platforms/pebble/pebble_adaptor_test.go | 8 +- platforms/pebble/pebble_driver_test.go | 22 +- platforms/raspi/pwm_pin_test.go | 35 ++- platforms/raspi/raspi_adaptor_test.go | 107 +++++---- platforms/rockpi/rockpi_adaptor_test.go | 14 +- platforms/sphero/bb8/bb8_driver_test.go | 10 +- platforms/sphero/ollie/ollie_driver_test.go | 12 +- platforms/sphero/sphero_adaptor_test.go | 26 +-- platforms/sphero/sphero_driver_test.go | 48 ++-- .../sphero/sprkplus/sprkplus_driver_test.go | 10 +- platforms/tinkerboard/adaptor_test.go | 112 +++++----- platforms/upboard/up2/adaptor_test.go | 79 ++++--- robot_test.go | 32 +-- system/digitalpin_access_test.go | 22 +- system/digitalpin_config_test.go | 87 +++++--- system/digitalpin_gpiod_test.go | 51 +++-- system/digitalpin_sysfs_test.go | 46 ++-- system/fs_mock_test.go | 48 ++-- system/fs_test.go | 8 +- system/i2c_device_test.go | 175 ++++++++------- system/pwmpin_sysfs_test.go | 58 ++--- system/spi_access_test.go | 6 +- system/system_test.go | 38 ++-- utils_test.go | 19 +- 172 files changed, 3785 insertions(+), 3878 deletions(-) delete mode 100644 gobottest/gobottest.go delete mode 100644 gobottest/gobottest_test.go diff --git a/api/api_test.go b/api/api_test.go index e7d0ce404..e8f4ffa53 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -11,8 +11,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) func initTestAPI() *API { @@ -46,7 +46,7 @@ func TestStartWithoutDefaults(t *testing.T) { request, _ := http.NewRequest("GET", "/", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) } func TestRobeaux(t *testing.T) { @@ -55,22 +55,22 @@ func TestRobeaux(t *testing.T) { request, _ := http.NewRequest("GET", "/index.html", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) // js assets request, _ = http.NewRequest("GET", "/js/script.js", nil) response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) // css assets request, _ = http.NewRequest("GET", "/css/application.css", nil) response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) // unknown asset request, _ = http.NewRequest("GET", "/js/fake/file.js", nil) response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 404) + assert.Equal(t, 404, response.Code) } func TestIndex(t *testing.T) { @@ -80,8 +80,8 @@ func TestIndex(t *testing.T) { a.ServeHTTP(response, request) - gobottest.Assert(t, http.StatusMovedPermanently, response.Code) - gobottest.Assert(t, "/index.html", response.Header()["Location"][0]) + assert.Equal(t, response.Code, http.StatusMovedPermanently) + assert.Equal(t, response.Header()["Location"][0], "/index.html") } func TestMcp(t *testing.T) { @@ -92,8 +92,8 @@ func TestMcp(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Refute(t, body["MCP"].(map[string]interface{})["robots"], nil) - gobottest.Refute(t, body["MCP"].(map[string]interface{})["commands"], nil) + assert.NotNil(t, body["MCP"].(map[string]interface{})["robots"]) + assert.NotNil(t, body["MCP"].(map[string]interface{})["commands"]) } func TestMcpCommands(t *testing.T) { @@ -104,7 +104,7 @@ func TestMcpCommands(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["commands"], []interface{}{"TestFunction"}) + assert.Equal(t, []interface{}{"TestFunction"}, body["commands"]) } func TestExecuteMcpCommand(t *testing.T) { @@ -121,7 +121,7 @@ func TestExecuteMcpCommand(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body.(map[string]interface{})["result"], "hey Beep Boop") + assert.Equal(t, "hey Beep Boop", body.(map[string]interface{})["result"]) // unknown command request, _ = http.NewRequest("GET", @@ -133,7 +133,7 @@ func TestExecuteMcpCommand(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body.(map[string]interface{})["error"], "Unknown Command") + assert.Equal(t, "Unknown Command", body.(map[string]interface{})["error"]) } func TestRobots(t *testing.T) { @@ -144,7 +144,7 @@ func TestRobots(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, len(body["robots"].([]interface{})), 3) + assert.Equal(t, 3, len(body["robots"].([]interface{}))) } func TestRobot(t *testing.T) { @@ -157,14 +157,14 @@ func TestRobot(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["robot"].(map[string]interface{})["name"].(string), "Robot1") + assert.Equal(t, "Robot1", body["robot"].(map[string]interface{})["name"].(string)) // unknown robot request, _ = http.NewRequest("GET", "/api/robots/UnknownRobot1", nil) a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["error"], "No Robot found with the name UnknownRobot1") + assert.Equal(t, "No Robot found with the name UnknownRobot1", body["error"]) } func TestRobotDevices(t *testing.T) { @@ -177,14 +177,14 @@ func TestRobotDevices(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, len(body["devices"].([]interface{})), 3) + assert.Equal(t, 3, len(body["devices"].([]interface{}))) // unknown robot request, _ = http.NewRequest("GET", "/api/robots/UnknownRobot1/devices", nil) a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["error"], "No Robot found with the name UnknownRobot1") + assert.Equal(t, "No Robot found with the name UnknownRobot1", body["error"]) } func TestRobotCommands(t *testing.T) { @@ -197,14 +197,14 @@ func TestRobotCommands(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["commands"], []interface{}{"robotTestFunction"}) + assert.Equal(t, []interface{}{"robotTestFunction"}, body["commands"]) // unknown robot request, _ = http.NewRequest("GET", "/api/robots/UnknownRobot1/commands", nil) a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["error"], "No Robot found with the name UnknownRobot1") + assert.Equal(t, "No Robot found with the name UnknownRobot1", body["error"]) } func TestExecuteRobotCommand(t *testing.T) { @@ -220,7 +220,7 @@ func TestExecuteRobotCommand(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body.(map[string]interface{})["result"], "hey Robot1, Beep Boop") + assert.Equal(t, "hey Robot1, Beep Boop", body.(map[string]interface{})["result"]) // unknown command request, _ = http.NewRequest("GET", @@ -232,7 +232,7 @@ func TestExecuteRobotCommand(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body.(map[string]interface{})["error"], "Unknown Command") + assert.Equal(t, "Unknown Command", body.(map[string]interface{})["error"]) // uknown robot request, _ = http.NewRequest("GET", @@ -243,7 +243,7 @@ func TestExecuteRobotCommand(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body.(map[string]interface{})["error"], "No Robot found with the name UnknownRobot1") + assert.Equal(t, "No Robot found with the name UnknownRobot1", body.(map[string]interface{})["error"]) } func TestRobotDevice(t *testing.T) { @@ -259,7 +259,7 @@ func TestRobotDevice(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["device"].(map[string]interface{})["name"].(string), "Device1") + assert.Equal(t, "Device1", body["device"].(map[string]interface{})["name"].(string)) // unknown device request, _ = http.NewRequest("GET", @@ -267,7 +267,7 @@ func TestRobotDevice(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["error"], "No Device found with the name UnknownDevice1") + assert.Equal(t, "No Device found with the name UnknownDevice1", body["error"]) } func TestRobotDeviceCommands(t *testing.T) { @@ -283,7 +283,7 @@ func TestRobotDeviceCommands(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, len(body["commands"].([]interface{})), 2) + assert.Equal(t, 2, len(body["commands"].([]interface{}))) // unknown device request, _ = http.NewRequest("GET", @@ -292,7 +292,7 @@ func TestRobotDeviceCommands(t *testing.T) { ) a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["error"], "No Device found with the name UnknownDevice1") + assert.Equal(t, "No Device found with the name UnknownDevice1", body["error"]) } func TestExecuteRobotDeviceCommand(t *testing.T) { @@ -309,7 +309,7 @@ func TestExecuteRobotDeviceCommand(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body.(map[string]interface{})["result"].(string), "hello human") + assert.Equal(t, "hello human", body.(map[string]interface{})["result"].(string)) // unknown command request, _ = http.NewRequest("GET", @@ -321,7 +321,7 @@ func TestExecuteRobotDeviceCommand(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body.(map[string]interface{})["error"], "Unknown Command") + assert.Equal(t, "Unknown Command", body.(map[string]interface{})["error"]) // unknown device request, _ = http.NewRequest("GET", @@ -332,7 +332,7 @@ func TestExecuteRobotDeviceCommand(t *testing.T) { a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body.(map[string]interface{})["error"], "No Device found with the name UnknownDevice1") + assert.Equal(t, "No Device found with the name UnknownDevice1", body.(map[string]interface{})["error"]) } @@ -346,14 +346,14 @@ func TestRobotConnections(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, len(body["connections"].([]interface{})), 3) + assert.Equal(t, 3, len(body["connections"].([]interface{}))) // unknown robot request, _ = http.NewRequest("GET", "/api/robots/UnknownRobot1/connections", nil) a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["error"], "No Robot found with the name UnknownRobot1") + assert.Equal(t, "No Robot found with the name UnknownRobot1", body["error"]) } func TestRobotConnection(t *testing.T) { @@ -369,7 +369,7 @@ func TestRobotConnection(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["connection"].(map[string]interface{})["name"].(string), "Connection1") + assert.Equal(t, "Connection1", body["connection"].(map[string]interface{})["name"].(string)) // unknown connection request, _ = http.NewRequest("GET", @@ -378,7 +378,7 @@ func TestRobotConnection(t *testing.T) { ) a.ServeHTTP(response, request) _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["error"], "No Connection found with the name UnknownConnection1") + assert.Equal(t, "No Connection found with the name UnknownConnection1", body["error"]) } func TestRobotDeviceEvent(t *testing.T) { @@ -412,7 +412,7 @@ func TestRobotDeviceEvent(t *testing.T) { case resp := <-respc: reader := bufio.NewReader(resp.Body) data, _ := reader.ReadString('\n') - gobottest.Assert(t, data, "data: \"event-data\"\n") + assert.Equal(t, "data: \"event-data\"\n", data) done = true case <-time.After(100 * time.Millisecond): t.Error("Not receiving data") @@ -427,7 +427,7 @@ func TestRobotDeviceEvent(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - gobottest.Assert(t, body["error"], "No Event found with the name UnknownEvent") + assert.Equal(t, "No Event found with the name UnknownEvent", body["error"]) } func TestAPIRouter(t *testing.T) { @@ -437,35 +437,35 @@ func TestAPIRouter(t *testing.T) { request, _ := http.NewRequest("HEAD", "/test", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) a.Get("/test", func(res http.ResponseWriter, req *http.Request) {}) request, _ = http.NewRequest("GET", "/test", nil) response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) a.Post("/test", func(res http.ResponseWriter, req *http.Request) {}) request, _ = http.NewRequest("POST", "/test", nil) response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) a.Put("/test", func(res http.ResponseWriter, req *http.Request) {}) request, _ = http.NewRequest("PUT", "/test", nil) response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) a.Delete("/test", func(res http.ResponseWriter, req *http.Request) {}) request, _ = http.NewRequest("DELETE", "/test", nil) response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) a.Options("/test", func(res http.ResponseWriter, req *http.Request) {}) request, _ = http.NewRequest("OPTIONS", "/test", nil) response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) } diff --git a/api/basic_auth_test.go b/api/basic_auth_test.go index acf0aa3cf..f00033f0c 100644 --- a/api/basic_auth_test.go +++ b/api/basic_auth_test.go @@ -5,7 +5,7 @@ import ( "net/http/httptest" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestBasicAuth(t *testing.T) { @@ -17,11 +17,11 @@ func TestBasicAuth(t *testing.T) { request.SetBasicAuth("admin", "password") response := httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 200) + assert.Equal(t, 200, response.Code) request, _ = http.NewRequest("GET", "/api/", nil) request.SetBasicAuth("admin", "wrongPassword") response = httptest.NewRecorder() a.ServeHTTP(response, request) - gobottest.Assert(t, response.Code, 401) + assert.Equal(t, 401, response.Code) } diff --git a/api/cors_test.go b/api/cors_test.go index 0e63674f6..cfd60eeb7 100644 --- a/api/cors_test.go +++ b/api/cors_test.go @@ -5,7 +5,7 @@ import ( "net/http/httptest" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestCORSIsOriginAllowed(t *testing.T) { @@ -13,50 +13,50 @@ func TestCORSIsOriginAllowed(t *testing.T) { cors.generatePatterns() // When all the origins are accepted - gobottest.Assert(t, cors.isOriginAllowed("http://localhost:8000"), true) - gobottest.Assert(t, cors.isOriginAllowed("http://localhost:3001"), true) - gobottest.Assert(t, cors.isOriginAllowed("http://server.com"), true) + assert.True(t, cors.isOriginAllowed("http://localhost:8000")) + assert.True(t, cors.isOriginAllowed("http://localhost:3001")) + assert.True(t, cors.isOriginAllowed("http://server.com")) // When one origin is accepted cors = &CORS{AllowOrigins: []string{"http://localhost:8000"}} cors.generatePatterns() - gobottest.Assert(t, cors.isOriginAllowed("http://localhost:8000"), true) - gobottest.Assert(t, cors.isOriginAllowed("http://localhost:3001"), false) - gobottest.Assert(t, cors.isOriginAllowed("http://server.com"), false) + assert.True(t, cors.isOriginAllowed("http://localhost:8000")) + assert.False(t, cors.isOriginAllowed("http://localhost:3001")) + assert.False(t, cors.isOriginAllowed("http://server.com")) // When several origins are accepted cors = &CORS{AllowOrigins: []string{"http://localhost:*", "http://server.com"}} cors.generatePatterns() - gobottest.Assert(t, cors.isOriginAllowed("http://localhost:8000"), true) - gobottest.Assert(t, cors.isOriginAllowed("http://localhost:3001"), true) - gobottest.Assert(t, cors.isOriginAllowed("http://server.com"), true) + assert.True(t, cors.isOriginAllowed("http://localhost:8000")) + assert.True(t, cors.isOriginAllowed("http://localhost:3001")) + assert.True(t, cors.isOriginAllowed("http://server.com")) // When several origins are accepted within the same domain cors = &CORS{AllowOrigins: []string{"http://*.server.com"}} cors.generatePatterns() - gobottest.Assert(t, cors.isOriginAllowed("http://localhost:8000"), false) - gobottest.Assert(t, cors.isOriginAllowed("http://localhost:3001"), false) - gobottest.Assert(t, cors.isOriginAllowed("http://foo.server.com"), true) - gobottest.Assert(t, cors.isOriginAllowed("http://api.server.com"), true) + assert.False(t, cors.isOriginAllowed("http://localhost:8000")) + assert.False(t, cors.isOriginAllowed("http://localhost:3001")) + assert.True(t, cors.isOriginAllowed("http://foo.server.com")) + assert.True(t, cors.isOriginAllowed("http://api.server.com")) } func TestCORSAllowedHeaders(t *testing.T) { cors := &CORS{AllowOrigins: []string{"*"}, AllowHeaders: []string{"Header1", "Header2"}} - gobottest.Assert(t, cors.AllowedHeaders(), "Header1,Header2") + assert.Equal(t, "Header1,Header2", cors.AllowedHeaders()) } func TestCORSAllowedMethods(t *testing.T) { cors := &CORS{AllowOrigins: []string{"*"}, AllowMethods: []string{"GET", "POST"}} - gobottest.Assert(t, cors.AllowedMethods(), "GET,POST") + assert.Equal(t, "GET,POST", cors.AllowedMethods()) cors.AllowMethods = []string{"GET", "POST", "PUT"} - gobottest.Assert(t, cors.AllowedMethods(), "GET,POST,PUT") + assert.Equal(t, "GET,POST,PUT", cors.AllowedMethods()) } func TestCORS(t *testing.T) { @@ -70,7 +70,7 @@ func TestCORS(t *testing.T) { request.Header.Set("Origin", allowedOrigin[0]) response := httptest.NewRecorder() api.ServeHTTP(response, request) - gobottest.Assert(t, response.Header()["Access-Control-Allow-Origin"], allowedOrigin) + assert.Equal(t, allowedOrigin, response.Header()["Access-Control-Allow-Origin"]) // Not accepted Origin disallowedOrigin := []string{"http://disallowed.com"} @@ -78,6 +78,6 @@ func TestCORS(t *testing.T) { request.Header.Set("Origin", disallowedOrigin[0]) response = httptest.NewRecorder() api.ServeHTTP(response, request) - gobottest.Refute(t, response.Header()["Access-Control-Allow-Origin"], disallowedOrigin) - gobottest.Refute(t, response.Header()["Access-Control-Allow-Origin"], allowedOrigin) + assert.NotEqual(t, disallowedOrigin, response.Header()["Access-Control-Allow-Origin"]) + assert.NotEqual(t, allowedOrigin, response.Header()["Access-Control-Allow-Origin"]) } diff --git a/commander_test.go b/commander_test.go index 074581c7a..e73021984 100644 --- a/commander_test.go +++ b/commander_test.go @@ -3,22 +3,18 @@ package gobot import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) -func TestCommaner(t *testing.T) { +func TestCommander(t *testing.T) { + // arrange c := NewCommander() c.AddCommand("test", func(map[string]interface{}) interface{} { return "hi" }) - if _, ok := c.Commands()["test"]; !ok { - t.Errorf("Could not add command to list of Commands") - } - - command := c.Command("test") - gobottest.Refute(t, command, nil) - - command = c.Command("booyeah") - gobottest.Assert(t, command, (func(map[string]interface{}) interface{})(nil)) + // act && assert + assert.Equal(t, 1, len(c.Commands())) + assert.NotNil(t, c.Command("test")) + assert.Nil(t, c.Command("booyeah")) } diff --git a/drivers/aio/analog_actuator_driver_test.go b/drivers/aio/analog_actuator_driver_test.go index 67c296ea8..ced579586 100644 --- a/drivers/aio/analog_actuator_driver_test.go +++ b/drivers/aio/analog_actuator_driver_test.go @@ -4,27 +4,27 @@ import ( "strings" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestAnalogActuatorDriver(t *testing.T) { a := newAioTestAdaptor() d := NewAnalogActuatorDriver(a, "47") - gobottest.Refute(t, d.Connection(), nil) - gobottest.Assert(t, d.Pin(), "47") + assert.NotNil(t, d.Connection()) + assert.Equal(t, "47", d.Pin()) err := d.RawWrite(100) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], 100) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, 100, a.written[0]) err = d.Write(247.0) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[1], 247) - gobottest.Assert(t, d.RawValue(), 247) - gobottest.Assert(t, d.Value(), 247.0) + assert.Nil(t, err) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, 247, a.written[1]) + assert.Equal(t, 247, d.RawValue()) + assert.Equal(t, 247.0, d.Value()) } func TestAnalogActuatorDriverWithScaler(t *testing.T) { @@ -34,14 +34,14 @@ func TestAnalogActuatorDriverWithScaler(t *testing.T) { d.SetScaler(func(input float64) int { return int((input + 3) / 2.5) }) err := d.Command("RawWrite")(map[string]interface{}{"val": "100"}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], 100) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, 100, a.written[0]) err = d.Command("Write")(map[string]interface{}{"val": "247.0"}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[1], 100) + assert.Nil(t, err) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, 100, a.written[1]) } func TestAnalogActuatorDriverLinearScaler(t *testing.T) { @@ -76,30 +76,30 @@ func TestAnalogActuatorDriverLinearScaler(t *testing.T) { // act err := d.Write(tt.input) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], tt.want) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, tt.want, a.written[0]) }) } } func TestAnalogActuatorDriverStart(t *testing.T) { d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestAnalogActuatorDriverHalt(t *testing.T) { d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestAnalogActuatorDriverDefaultName(t *testing.T) { d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "AnalogActuator"), true) + assert.True(t, strings.HasPrefix(d.Name(), "AnalogActuator")) } func TestAnalogActuatorDriverSetName(t *testing.T) { d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index 51371689c..12e94dc2f 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*AnalogSensorDriver)(nil) @@ -15,29 +15,29 @@ var _ gobot.Driver = (*AnalogSensorDriver)(nil) func TestAnalogSensorDriver(t *testing.T) { a := newAioTestAdaptor() d := NewAnalogSensorDriver(a, "1") - gobottest.Refute(t, d.Connection(), nil) + assert.NotNil(t, d.Connection()) // default interval - gobottest.Assert(t, d.interval, 10*time.Millisecond) + assert.Equal(t, 10*time.Millisecond, d.interval) // commands a = newAioTestAdaptor() d = NewAnalogSensorDriver(a, "42", 30*time.Second) d.SetScaler(func(input int) float64 { return 2.5*float64(input) - 3 }) - gobottest.Assert(t, d.Pin(), "42") - gobottest.Assert(t, d.interval, 30*time.Second) + assert.Equal(t, "42", d.Pin()) + assert.Equal(t, 30*time.Second, d.interval) a.TestAdaptorAnalogRead(func() (val int, err error) { val = 100 return }) ret := d.Command("ReadRaw")(nil).(map[string]interface{}) - gobottest.Assert(t, ret["val"].(int), 100) - gobottest.Assert(t, ret["err"], nil) + assert.Equal(t, 100, ret["val"].(int)) + assert.Nil(t, ret["err"]) ret = d.Command("Read")(nil).(map[string]interface{}) - gobottest.Assert(t, ret["val"].(float64), 247.0) - gobottest.Assert(t, ret["err"], nil) + assert.Equal(t, 247.0, ret["val"].(float64)) + assert.Nil(t, ret["err"]) // refresh value on read a = newAioTestAdaptor() @@ -46,12 +46,12 @@ func TestAnalogSensorDriver(t *testing.T) { val = 150 return }) - gobottest.Assert(t, d.Value(), 0.0) + assert.Equal(t, 0.0, d.Value()) val, err := d.Read() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, val, 150.0) - gobottest.Assert(t, d.Value(), 150.0) - gobottest.Assert(t, d.RawValue(), 150) + assert.Nil(t, err) + assert.Equal(t, 150.0, val) + assert.Equal(t, 150.0, d.Value()) + assert.Equal(t, 150, d.RawValue()) } func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { @@ -84,8 +84,8 @@ func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { // act got, err := d.Read() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, tt.want) + assert.Nil(t, err) + assert.Equal(t, tt.want, got) }) } } @@ -98,12 +98,12 @@ func TestAnalogSensorDriverStart(t *testing.T) { // expect data to be received _ = d.Once(d.Event(Data), func(data interface{}) { - gobottest.Assert(t, data.(int), 100) + assert.Equal(t, 100, data.(int)) sem <- true }) _ = d.Once(d.Event(Value), func(data interface{}) { - gobottest.Assert(t, data.(float64), 10000.0) + assert.Equal(t, 10000.0, data.(float64)) sem <- true }) @@ -113,7 +113,7 @@ func TestAnalogSensorDriverStart(t *testing.T) { return }) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) select { case <-sem: @@ -123,7 +123,7 @@ func TestAnalogSensorDriverStart(t *testing.T) { // expect error to be received _ = d.Once(d.Event(Error), func(data interface{}) { - gobottest.Assert(t, data.(error).Error(), "read error") + assert.Equal(t, "read error", data.(error).Error()) sem <- true }) @@ -169,7 +169,7 @@ func TestAnalogSensorDriverHalt(t *testing.T) { <-d.halt close(done) }() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) select { case <-done: case <-time.After(100 * time.Millisecond): @@ -179,11 +179,11 @@ func TestAnalogSensorDriverHalt(t *testing.T) { func TestAnalogSensorDriverDefaultName(t *testing.T) { d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "AnalogSensor"), true) + assert.True(t, strings.HasPrefix(d.Name(), "AnalogSensor")) } func TestAnalogSensorDriverSetName(t *testing.T) { d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go index a5395a3ed..dd7b7b64b 100644 --- a/drivers/aio/grove_drivers_test.go +++ b/drivers/aio/grove_drivers_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) type DriverAndPinner interface { @@ -33,8 +33,8 @@ func TestDriverDefaults(t *testing.T) { } for _, driver := range drivers { - gobottest.Assert(t, driver.Connection(), testAdaptor) - gobottest.Assert(t, driver.Pin(), pin) + assert.Equal(t, testAdaptor, driver.Connection()) + assert.Equal(t, pin, driver.Pin()) } } @@ -90,11 +90,11 @@ func TestDriverPublishesError(t *testing.T) { } testAdaptor.TestAdaptorAnalogRead(returnErr) - gobottest.Assert(t, driver.Start(), nil) + assert.Nil(t, driver.Start()) // expect error _ = driver.Once(driver.Event(Error), func(data interface{}) { - gobottest.Assert(t, data.(error).Error(), "read error") + assert.Equal(t, "read error", data.(error).Error()) close(sem) }) diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index d47f0fec1..2fe8f75e3 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*GroveTemperatureSensorDriver)(nil) @@ -15,9 +15,9 @@ var _ gobot.Driver = (*GroveTemperatureSensorDriver)(nil) func TestGroveTemperatureSensorDriver(t *testing.T) { testAdaptor := newAioTestAdaptor() d := NewGroveTemperatureSensorDriver(testAdaptor, "123") - gobottest.Assert(t, d.Connection(), testAdaptor) - gobottest.Assert(t, d.Pin(), "123") - gobottest.Assert(t, d.interval, 10*time.Millisecond) + assert.Equal(t, testAdaptor, d.Connection()) + assert.Equal(t, "123", d.Pin()) + assert.Equal(t, 10*time.Millisecond, d.interval) } func TestGroveTemperatureSensorDriverScaling(t *testing.T) { @@ -47,8 +47,8 @@ func TestGroveTemperatureSensorDriverScaling(t *testing.T) { // act got, err := d.Read() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, tt.want) + assert.Nil(t, err) + assert.Equal(t, tt.want, got) }) } } @@ -63,10 +63,10 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { return }) _ = d.Once(d.Event(Value), func(data interface{}) { - gobottest.Assert(t, fmt.Sprintf("%.2f", data.(float64)), "31.62") + assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) select { case <-sem: @@ -74,10 +74,10 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { t.Errorf("Grove Temperature Sensor Event \"Data\" was not published") } - gobottest.Assert(t, d.Temperature(), 31.61532462352477) + assert.Equal(t, 31.61532462352477, d.Temperature()) } func TestGroveTempDriverDefaultName(t *testing.T) { d := NewGroveTemperatureSensorDriver(newAioTestAdaptor(), "1") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "GroveTemperatureSensor"), true) + assert.True(t, strings.HasPrefix(d.Name(), "GroveTemperatureSensor")) } diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index b6012b7d3..0610364e1 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -7,15 +7,15 @@ import ( "testing" "time" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestTemperatureSensorDriver(t *testing.T) { testAdaptor := newAioTestAdaptor() d := NewTemperatureSensorDriver(testAdaptor, "123") - gobottest.Assert(t, d.Connection(), testAdaptor) - gobottest.Assert(t, d.Pin(), "123") - gobottest.Assert(t, d.interval, 10*time.Millisecond) + assert.Equal(t, testAdaptor, d.Connection()) + assert.Equal(t, "123", d.Pin()) + assert.Equal(t, 10*time.Millisecond, d.interval) } func TestTemperatureSensorDriverNtcScaling(t *testing.T) { @@ -48,8 +48,8 @@ func TestTemperatureSensorDriverNtcScaling(t *testing.T) { // act got, err := d.Read() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, tt.want) + assert.Nil(t, err) + assert.Equal(t, tt.want, got) }) } } @@ -83,8 +83,8 @@ func TestTemperatureSensorDriverLinearScaling(t *testing.T) { // act got, err := d.Read() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, tt.want) + assert.Nil(t, err) + assert.Equal(t, tt.want, got) }) } } @@ -101,10 +101,10 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.T) { return }) _ = d.Once(d.Event(Value), func(data interface{}) { - gobottest.Assert(t, fmt.Sprintf("%.2f", data.(float64)), "31.62") + assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) select { case <-sem: @@ -112,7 +112,7 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.T) { t.Errorf(" Temperature Sensor Event \"Data\" was not published") } - gobottest.Assert(t, d.Value(), 31.61532462352477) + assert.Equal(t, 31.61532462352477, d.Value()) } func TestTempSensorPublishesError(t *testing.T) { @@ -126,11 +126,11 @@ func TestTempSensorPublishesError(t *testing.T) { return }) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) // expect error _ = d.Once(d.Event(Error), func(data interface{}) { - gobottest.Assert(t, data.(error).Error(), "read error") + assert.Equal(t, "read error", data.(error).Error()) sem <- true }) @@ -148,7 +148,7 @@ func TestTempSensorHalt(t *testing.T) { <-d.halt close(done) }() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) select { case <-done: case <-time.After(100 * time.Millisecond): @@ -158,13 +158,13 @@ func TestTempSensorHalt(t *testing.T) { func TestTempDriverDefaultName(t *testing.T) { d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "TemperatureSensor"), true) + assert.True(t, strings.HasPrefix(d.Name(), "TemperatureSensor")) } func TestTempDriverSetName(t *testing.T) { d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1") d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } func TestTempDriver_initialize(t *testing.T) { @@ -208,7 +208,7 @@ func TestTempDriver_initialize(t *testing.T) { // act ntc.initialize() // assert - gobottest.Assert(t, ntc, tt.want) + assert.Equal(t, tt.want, ntc) }) } } diff --git a/drivers/common/mfrc522/mfrc522_pcd_test.go b/drivers/common/mfrc522/mfrc522_pcd_test.go index b640fe2a2..bf217a859 100644 --- a/drivers/common/mfrc522/mfrc522_pcd_test.go +++ b/drivers/common/mfrc522/mfrc522_pcd_test.go @@ -3,7 +3,7 @@ package mfrc522 import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) type busConnMock struct { @@ -49,7 +49,7 @@ func TestNewMFRC522Common(t *testing.T) { // act d := NewMFRC522Common() // assert - gobottest.Refute(t, d, nil) + assert.NotNil(t, d) } func TestInitialize(t *testing.T) { @@ -63,12 +63,12 @@ func TestInitialize(t *testing.T) { // act err := d.Initialize(c) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, d.connection, c) - gobottest.Assert(t, c.written[:3], wantSoftReset) - gobottest.Assert(t, c.written[3:21], wantInit) - gobottest.Assert(t, c.written[21:24], wantAntennaOn) - gobottest.Assert(t, c.written[24:], wantGain) + assert.Nil(t, err) + assert.Equal(t, c, d.connection) + assert.Equal(t, wantSoftReset, c.written[:3]) + assert.Equal(t, wantInit, c.written[3:21]) + assert.Equal(t, wantAntennaOn, c.written[21:24]) + assert.Equal(t, wantGain, c.written[24:]) } func Test_getVersion(t *testing.T) { @@ -80,9 +80,9 @@ func Test_getVersion(t *testing.T) { // act got, err := d.getVersion() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, want) - gobottest.Assert(t, c.written, wantWritten) + assert.Nil(t, err) + assert.Equal(t, want, got) + assert.Equal(t, wantWritten, c.written) } func Test_switchAntenna(t *testing.T) { @@ -120,8 +120,8 @@ func Test_switchAntenna(t *testing.T) { // act err := d.switchAntenna(tc.target) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, c.written, tc.wantWritten) + assert.Nil(t, err) + assert.Equal(t, tc.wantWritten, c.written) }) } } @@ -134,8 +134,8 @@ func Test_stopCrypto1(t *testing.T) { // act err := d.stopCrypto1() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, c.written, wantWritten) + assert.Nil(t, err) + assert.Equal(t, wantWritten, c.written) } func Test_communicateWithPICC(t *testing.T) { @@ -158,14 +158,14 @@ func Test_communicateWithPICC(t *testing.T) { // transceive, all 8 bits, no CRC err := d.communicateWithPICC(0x0C, dataToFifo, backData, 0x00, false) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, c.written[:8], writtenPrepare) - gobottest.Assert(t, c.written[8:12], writtenWriteFifo) - gobottest.Assert(t, c.written[12:16], writtenTransceive) - gobottest.Assert(t, c.written[16:19], writtenBitFramingStart) - gobottest.Assert(t, c.written[19:24], writtenWaitAndFinish) - gobottest.Assert(t, c.written[24:], writtenReadFifo) - gobottest.Assert(t, backData, []byte{0x11, 0x22}) + assert.Nil(t, err) + assert.Equal(t, writtenPrepare, c.written[:8]) + assert.Equal(t, writtenWriteFifo, c.written[8:12]) + assert.Equal(t, writtenTransceive, c.written[12:16]) + assert.Equal(t, writtenBitFramingStart, c.written[16:19]) + assert.Equal(t, writtenWaitAndFinish, c.written[19:24]) + assert.Equal(t, writtenReadFifo, c.written[24:]) + assert.Equal(t, []byte{0x11, 0x22}, backData) } func Test_calculateCRC(t *testing.T) { @@ -181,12 +181,12 @@ func Test_calculateCRC(t *testing.T) { // act err := d.calculateCRC(dataToFifo, gotCrcBack) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, c.written[:6], writtenPrepare) - gobottest.Assert(t, c.written[6:10], writtenFifo) - gobottest.Assert(t, c.written[10:15], writtenCalc) - gobottest.Assert(t, c.written[15:], writtenGetResult) - gobottest.Assert(t, gotCrcBack, []byte{0x11, 0x22}) + assert.Nil(t, err) + assert.Equal(t, writtenPrepare, c.written[:6]) + assert.Equal(t, writtenFifo, c.written[6:10]) + assert.Equal(t, writtenCalc, c.written[10:15]) + assert.Equal(t, writtenGetResult, c.written[15:]) + assert.Equal(t, []byte{0x11, 0x22}, gotCrcBack) } func Test_writeFifo(t *testing.T) { @@ -197,8 +197,8 @@ func Test_writeFifo(t *testing.T) { // act err := d.writeFifo(dataToFifo) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, c.written, wantWritten) + assert.Nil(t, err) + assert.Equal(t, wantWritten, c.written) } func Test_readFifo(t *testing.T) { @@ -210,7 +210,7 @@ func Test_readFifo(t *testing.T) { // act _, err := d.readFifo(backData) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, c.written, wantWritten) - gobottest.Assert(t, backData, c.simFifo) + assert.Nil(t, err) + assert.Equal(t, wantWritten, c.written) + assert.Equal(t, c.simFifo, backData) } diff --git a/drivers/gpio/aip1640_driver_test.go b/drivers/gpio/aip1640_driver_test.go index 796ba8b46..2b63ac39c 100644 --- a/drivers/gpio/aip1640_driver_test.go +++ b/drivers/gpio/aip1640_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*AIP1640Driver)(nil) @@ -32,62 +32,62 @@ func TestAIP1640Driver(t *testing.T) { func TestAIP1640DriverStart(t *testing.T) { d := initTestAIP1640Driver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestAIP1640DriverHalt(t *testing.T) { d := initTestAIP1640Driver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestAIP1640DriverDefaultName(t *testing.T) { d := initTestAIP1640Driver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "AIP1640Driver"), true) + assert.True(t, strings.HasPrefix(d.Name(), "AIP1640Driver")) } func TestAIP1640DriverSetName(t *testing.T) { d := initTestAIP1640Driver() d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } func TestAIP1640DriveDrawPixel(t *testing.T) { d := initTestAIP1640Driver() d.DrawPixel(2, 3, true) d.DrawPixel(0, 3, true) - gobottest.Assert(t, uint8(5), d.buffer[7-3]) + assert.Equal(t, d.buffer[7-3], uint8(5)) } func TestAIP1640DriverDrawRow(t *testing.T) { d := initTestAIP1640Driver() d.DrawRow(4, 0x3C) - gobottest.Assert(t, uint8(0x3C), d.buffer[7-4]) + assert.Equal(t, d.buffer[7-4], uint8(0x3C)) } func TestAIP1640DriverDrawMatrix(t *testing.T) { d := initTestAIP1640Driver() drawing := [8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} d.DrawMatrix(drawing) - gobottest.Assert(t, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}, d.buffer) + assert.Equal(t, d.buffer, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}) } func TestAIP1640DriverClear(t *testing.T) { d := initTestAIP1640Driver() drawing := [8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} d.DrawMatrix(drawing) - gobottest.Assert(t, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}, d.buffer) + assert.Equal(t, d.buffer, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}) d.Clear() - gobottest.Assert(t, [8]byte{}, d.buffer) + assert.Equal(t, d.buffer, [8]byte{}) } func TestAIP1640DriverSetIntensity(t *testing.T) { d := initTestAIP1640Driver() d.SetIntensity(3) - gobottest.Assert(t, uint8(3), d.intensity) + assert.Equal(t, d.intensity, uint8(3)) } func TestAIP1640DriverSetIntensityHigherThan7(t *testing.T) { d := initTestAIP1640Driver() d.SetIntensity(19) - gobottest.Assert(t, uint8(7), d.intensity) + assert.Equal(t, d.intensity, uint8(7)) } diff --git a/drivers/gpio/button_driver_test.go b/drivers/gpio/button_driver_test.go index aa458c88c..7910bc7bc 100644 --- a/drivers/gpio/button_driver_test.go +++ b/drivers/gpio/button_driver_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*ButtonDriver)(nil) @@ -23,15 +23,15 @@ func TestButtonDriverHalt(t *testing.T) { go func() { <-d.halt }() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestButtonDriver(t *testing.T) { d := NewButtonDriver(newGpioTestAdaptor(), "1") - gobottest.Refute(t, d.Connection(), nil) + assert.NotNil(t, d.Connection()) d = NewButtonDriver(newGpioTestAdaptor(), "1", 30*time.Second) - gobottest.Assert(t, d.interval, 30*time.Second) + assert.Equal(t, 30*time.Second, d.interval) } func TestButtonDriverStart(t *testing.T) { @@ -40,7 +40,7 @@ func TestButtonDriverStart(t *testing.T) { d := NewButtonDriver(a, "1") _ = d.Once(ButtonPush, func(data interface{}) { - gobottest.Assert(t, d.Active, true) + assert.True(t, d.Active) sem <- true }) @@ -49,7 +49,7 @@ func TestButtonDriverStart(t *testing.T) { return }) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) select { case <-sem: @@ -58,7 +58,7 @@ func TestButtonDriverStart(t *testing.T) { } _ = d.Once(ButtonRelease, func(data interface{}) { - gobottest.Assert(t, d.Active, false) + assert.False(t, d.Active) sem <- true }) @@ -113,7 +113,7 @@ func TestButtonDriverDefaultState(t *testing.T) { d.DefaultState = 1 _ = d.Once(ButtonPush, func(data interface{}) { - gobottest.Assert(t, d.Active, true) + assert.True(t, d.Active) sem <- true }) @@ -122,7 +122,7 @@ func TestButtonDriverDefaultState(t *testing.T) { return }) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) select { case <-sem: @@ -131,7 +131,7 @@ func TestButtonDriverDefaultState(t *testing.T) { } _ = d.Once(ButtonRelease, func(data interface{}) { - gobottest.Assert(t, d.Active, false) + assert.False(t, d.Active) sem <- true }) @@ -149,11 +149,11 @@ func TestButtonDriverDefaultState(t *testing.T) { func TestButtonDriverDefaultName(t *testing.T) { g := initTestButtonDriver() - gobottest.Assert(t, strings.HasPrefix(g.Name(), "Button"), true) + assert.True(t, strings.HasPrefix(g.Name(), "Button")) } func TestButtonDriverSetName(t *testing.T) { g := initTestButtonDriver() g.SetName("mybot") - gobottest.Assert(t, g.Name(), "mybot") + assert.Equal(t, "mybot", g.Name()) } diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index 3edb43ea5..94af0cc8f 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*BuzzerDriver)(nil) @@ -17,37 +17,37 @@ func initTestBuzzerDriver(conn DigitalWriter) *BuzzerDriver { func TestBuzzerDriverDefaultName(t *testing.T) { g := initTestBuzzerDriver(newGpioTestAdaptor()) - gobottest.Assert(t, strings.HasPrefix(g.Name(), "Buzzer"), true) + assert.True(t, strings.HasPrefix(g.Name(), "Buzzer")) } func TestBuzzerDriverSetName(t *testing.T) { g := initTestBuzzerDriver(newGpioTestAdaptor()) g.SetName("mybot") - gobottest.Assert(t, g.Name(), "mybot") + assert.Equal(t, "mybot", g.Name()) } func TestBuzzerDriverStart(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestBuzzerDriverHalt(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestBuzzerDriverToggle(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) _ = d.Off() _ = d.Toggle() - gobottest.Assert(t, d.State(), true) + assert.True(t, d.State()) _ = d.Toggle() - gobottest.Assert(t, d.State(), false) + assert.False(t, d.State()) } func TestBuzzerDriverTone(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - gobottest.Assert(t, d.Tone(100, 0.01), nil) + assert.Nil(t, d.Tone(100, 0.01)) } func TestBuzzerDriverOnError(t *testing.T) { @@ -57,7 +57,8 @@ func TestBuzzerDriverOnError(t *testing.T) { return errors.New("write error") }) - gobottest.Assert(t, d.On(), errors.New("write error")) + //assert.Errorf(t, d.On(), "write error") + assert.Errorf(t, d.On(), "write error") } func TestBuzzerDriverOffError(t *testing.T) { @@ -67,7 +68,7 @@ func TestBuzzerDriverOffError(t *testing.T) { return errors.New("write error") }) - gobottest.Assert(t, d.Off(), errors.New("write error")) + assert.Errorf(t, d.Off(), "write error") } func TestBuzzerDriverToneError(t *testing.T) { @@ -77,5 +78,5 @@ func TestBuzzerDriverToneError(t *testing.T) { return errors.New("write error") }) - gobottest.Assert(t, d.Tone(100, 0.01), errors.New("write error")) + assert.Errorf(t, d.Tone(100, 0.01), "write error") } diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index 2a0815a4e..1c8faaca1 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*DirectPinDriver)(nil) @@ -34,138 +34,138 @@ func TestDirectPinDriver(t *testing.T) { var err interface{} d := initTestDirectPinDriver() - gobottest.Assert(t, d.Pin(), "1") - gobottest.Refute(t, d.Connection(), nil) + assert.Equal(t, "1", d.Pin()) + assert.NotNil(t, d.Connection()) ret = d.Command("DigitalRead")(nil).(map[string]interface{}) - gobottest.Assert(t, ret["val"].(int), 1) - gobottest.Assert(t, ret["err"], nil) + assert.Equal(t, 1, ret["val"].(int)) + assert.Nil(t, ret["err"]) err = d.Command("DigitalWrite")(map[string]interface{}{"level": "1"}) - gobottest.Assert(t, err.(error), errors.New("write error")) + assert.Errorf(t, err.(error), "write error") err = d.Command("PwmWrite")(map[string]interface{}{"level": "1"}) - gobottest.Assert(t, err.(error), errors.New("write error")) + assert.Errorf(t, err.(error), "write error") err = d.Command("ServoWrite")(map[string]interface{}{"level": "1"}) - gobottest.Assert(t, err.(error), errors.New("write error")) + assert.Errorf(t, err.(error), "write error") } func TestDirectPinDriverStart(t *testing.T) { d := initTestDirectPinDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestDirectPinDriverHalt(t *testing.T) { d := initTestDirectPinDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestDirectPinDriverOff(t *testing.T) { d := initTestDirectPinDriver() - gobottest.Refute(t, d.Off(), nil) + assert.NotNil(t, d.Off()) a := newGpioTestAdaptor() d = NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.Off(), nil) + assert.Nil(t, d.Off()) } func TestDirectPinDriverOffNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.Off(), errors.New("DigitalWrite is not supported by this platform")) + assert.Errorf(t, d.Off(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverOn(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.On(), nil) + assert.Nil(t, d.On()) } func TestDirectPinDriverOnError(t *testing.T) { d := initTestDirectPinDriver() - gobottest.Refute(t, d.On(), nil) + assert.NotNil(t, d.On()) } func TestDirectPinDriverOnNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.On(), errors.New("DigitalWrite is not supported by this platform")) + assert.Errorf(t, d.On(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWrite(t *testing.T) { adaptor := newGpioTestAdaptor() d := NewDirectPinDriver(adaptor, "1") - gobottest.Assert(t, d.DigitalWrite(1), nil) + assert.Nil(t, d.DigitalWrite(1)) } func TestDirectPinDriverDigitalWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.DigitalWrite(1), errors.New("DigitalWrite is not supported by this platform")) + assert.Errorf(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWriteError(t *testing.T) { d := initTestDirectPinDriver() - gobottest.Refute(t, d.DigitalWrite(1), nil) + assert.NotNil(t, d.DigitalWrite(1)) } func TestDirectPinDriverDigitalRead(t *testing.T) { d := initTestDirectPinDriver() ret, err := d.DigitalRead() - gobottest.Assert(t, ret, 1) - gobottest.Assert(t, err, nil) + assert.Equal(t, 1, ret) + assert.Nil(t, err) } func TestDirectPinDriverDigitalReadNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") _, e := d.DigitalRead() - gobottest.Assert(t, e, errors.New("DigitalRead is not supported by this platform")) + assert.Errorf(t, e, "DigitalRead is not supported by this platform") } func TestDirectPinDriverPwmWrite(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.PwmWrite(1), nil) + assert.Nil(t, d.PwmWrite(1)) } func TestDirectPinDriverPwmWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.PwmWrite(1), errors.New("PwmWrite is not supported by this platform")) + assert.Errorf(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") } func TestDirectPinDriverPwmWriteError(t *testing.T) { d := initTestDirectPinDriver() - gobottest.Refute(t, d.PwmWrite(1), nil) + assert.NotNil(t, d.PwmWrite(1)) } func TestDirectPinDriverServoWrite(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.ServoWrite(1), nil) + assert.Nil(t, d.ServoWrite(1)) } func TestDirectPinDriverServoWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - gobottest.Assert(t, d.ServoWrite(1), errors.New("ServoWrite is not supported by this platform")) + assert.Errorf(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") } func TestDirectPinDriverServoWriteError(t *testing.T) { d := initTestDirectPinDriver() - gobottest.Refute(t, d.ServoWrite(1), nil) + assert.NotNil(t, d.ServoWrite(1)) } func TestDirectPinDriverDefaultName(t *testing.T) { d := initTestDirectPinDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Direct"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Direct")) } func TestDirectPinDriverSetName(t *testing.T) { d := initTestDirectPinDriver() d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/gpio/easy_driver_test.go b/drivers/gpio/easy_driver_test.go index baaf69170..669aeeb7b 100644 --- a/drivers/gpio/easy_driver_test.go +++ b/drivers/gpio/easy_driver_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) const ( @@ -22,18 +22,18 @@ func initEasyDriver() *EasyDriver { func TestEasyDriver_Connection(t *testing.T) { d := initEasyDriver() - gobottest.Assert(t, d.Connection(), adapter) + assert.Equal(t, adapter, d.Connection()) } func TestEasyDriverDefaultName(t *testing.T) { d := initEasyDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "EasyDriver"), true) + assert.True(t, strings.HasPrefix(d.Name(), "EasyDriver")) } func TestEasyDriverSetName(t *testing.T) { d := initEasyDriver() d.SetName("OtherDriver") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "OtherDriver"), true) + assert.True(t, strings.HasPrefix(d.Name(), "OtherDriver")) } func TestEasyDriverStart(t *testing.T) { @@ -45,142 +45,142 @@ func TestEasyDriverStart(t *testing.T) { func TestEasyDriverHalt(t *testing.T) { d := initEasyDriver() _ = d.Run() - gobottest.Assert(t, d.IsMoving(), true) + assert.True(t, d.IsMoving()) _ = d.Halt() - gobottest.Assert(t, d.IsMoving(), false) + assert.False(t, d.IsMoving()) } func TestEasyDriverMove(t *testing.T) { d := initEasyDriver() _ = d.Move(2) time.Sleep(2 * time.Millisecond) - gobottest.Assert(t, d.GetCurrentStep(), 4) - gobottest.Assert(t, d.IsMoving(), false) + assert.Equal(t, 4, d.GetCurrentStep()) + assert.False(t, d.IsMoving()) } func TestEasyDriverRun(t *testing.T) { d := initEasyDriver() _ = d.Run() - gobottest.Assert(t, d.IsMoving(), true) + assert.True(t, d.IsMoving()) _ = d.Run() - gobottest.Assert(t, d.IsMoving(), true) + assert.True(t, d.IsMoving()) } func TestEasyDriverStop(t *testing.T) { d := initEasyDriver() _ = d.Run() - gobottest.Assert(t, d.IsMoving(), true) + assert.True(t, d.IsMoving()) _ = d.Stop() - gobottest.Assert(t, d.IsMoving(), false) + assert.False(t, d.IsMoving()) } func TestEasyDriverStep(t *testing.T) { d := initEasyDriver() _ = d.Step() - gobottest.Assert(t, d.GetCurrentStep(), 1) + assert.Equal(t, 1, d.GetCurrentStep()) _ = d.Step() _ = d.Step() _ = d.Step() - gobottest.Assert(t, d.GetCurrentStep(), 4) + assert.Equal(t, 4, d.GetCurrentStep()) _ = d.SetDirection("ccw") _ = d.Step() - gobottest.Assert(t, d.GetCurrentStep(), 3) + assert.Equal(t, 3, d.GetCurrentStep()) } func TestEasyDriverSetDirection(t *testing.T) { d := initEasyDriver() - gobottest.Assert(t, d.dir, int8(1)) + assert.Equal(t, int8(1), d.dir) _ = d.SetDirection("cw") - gobottest.Assert(t, d.dir, int8(1)) + assert.Equal(t, int8(1), d.dir) _ = d.SetDirection("ccw") - gobottest.Assert(t, d.dir, int8(-1)) + assert.Equal(t, int8(-1), d.dir) _ = d.SetDirection("nothing") - gobottest.Assert(t, d.dir, int8(1)) + assert.Equal(t, int8(1), d.dir) } func TestEasyDriverSetDirectionNoPin(t *testing.T) { d := initEasyDriver() d.dirPin = "" err := d.SetDirection("cw") - gobottest.Refute(t, err, nil) + assert.NotNil(t, err) } func TestEasyDriverSetSpeed(t *testing.T) { d := initEasyDriver() - gobottest.Assert(t, d.rpm, uint(stepsPerRev/4)) // default speed of 720/4 + assert.Equal(t, uint(stepsPerRev/4), d.rpm) // default speed of 720/4 _ = d.SetSpeed(0) - gobottest.Assert(t, d.rpm, uint(1)) + assert.Equal(t, uint(1), d.rpm) _ = d.SetSpeed(200) - gobottest.Assert(t, d.rpm, uint(200)) + assert.Equal(t, uint(200), d.rpm) _ = d.SetSpeed(1000) - gobottest.Assert(t, d.rpm, uint(stepsPerRev)) + assert.Equal(t, uint(stepsPerRev), d.rpm) } func TestEasyDriverGetMaxSpeed(t *testing.T) { d := initEasyDriver() - gobottest.Assert(t, d.GetMaxSpeed(), uint(stepsPerRev)) + assert.Equal(t, uint(stepsPerRev), d.GetMaxSpeed()) } func TestEasyDriverSleep(t *testing.T) { // let's test basic functionality d := initEasyDriver() _ = d.Sleep() - gobottest.Assert(t, d.IsSleeping(), true) + assert.True(t, d.IsSleeping()) // let's make sure it stops first d = initEasyDriver() _ = d.Run() _ = d.Sleep() - gobottest.Assert(t, d.IsSleeping(), true) - gobottest.Assert(t, d.IsMoving(), false) + assert.True(t, d.IsSleeping()) + assert.False(t, d.IsMoving()) } func TestEasyDriverSleepNoPin(t *testing.T) { d := initEasyDriver() d.sleepPin = "" err := d.Sleep() - gobottest.Refute(t, err, nil) + assert.NotNil(t, err) err = d.Wake() - gobottest.Refute(t, err, nil) + assert.NotNil(t, err) } func TestEasyDriverWake(t *testing.T) { // let's test basic functionality d := initEasyDriver() _ = d.Sleep() - gobottest.Assert(t, d.IsSleeping(), true) + assert.True(t, d.IsSleeping()) _ = d.Wake() - gobottest.Assert(t, d.IsSleeping(), false) + assert.False(t, d.IsSleeping()) } func TestEasyDriverEnable(t *testing.T) { // let's test basic functionality d := initEasyDriver() _ = d.Disable() - gobottest.Assert(t, d.IsEnabled(), false) + assert.False(t, d.IsEnabled()) _ = d.Enable() - gobottest.Assert(t, d.IsEnabled(), true) + assert.True(t, d.IsEnabled()) } func TestEasyDriverEnableNoPin(t *testing.T) { d := initEasyDriver() d.enPin = "" err := d.Disable() - gobottest.Refute(t, err, nil) + assert.NotNil(t, err) err = d.Enable() - gobottest.Refute(t, err, nil) + assert.NotNil(t, err) } func TestEasyDriverDisable(t *testing.T) { // let's test basic functionality d := initEasyDriver() _ = d.Disable() - gobottest.Assert(t, d.IsEnabled(), false) + assert.False(t, d.IsEnabled()) // let's make sure it stops first d = initEasyDriver() _ = d.Run() _ = d.Disable() - gobottest.Assert(t, d.IsEnabled(), false) - gobottest.Assert(t, d.IsMoving(), false) + assert.False(t, d.IsEnabled()) + assert.False(t, d.IsMoving()) } diff --git a/drivers/gpio/grove_drivers_test.go b/drivers/gpio/grove_drivers_test.go index 35f3ac840..d201a41a3 100644 --- a/drivers/gpio/grove_drivers_test.go +++ b/drivers/gpio/grove_drivers_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) type DriverAndPinner interface { @@ -35,8 +35,8 @@ func TestDriverDefaults(t *testing.T) { } for _, driver := range drivers { - gobottest.Assert(t, driver.Connection(), testAdaptor) - gobottest.Assert(t, driver.Pin(), pin) + assert.Equal(t, testAdaptor, driver.Connection()) + assert.Equal(t, pin, driver.Pin()) } } @@ -91,11 +91,11 @@ func TestDriverPublishesError(t *testing.T) { } testAdaptor.testAdaptorDigitalRead = returnErr - gobottest.Assert(t, driver.Start(), nil) + assert.Nil(t, driver.Start()) // expect error _ = driver.Once(driver.Event(Error), func(data interface{}) { - gobottest.Assert(t, data.(error).Error(), "read error") + assert.Equal(t, "read error", data.(error).Error()) close(sem) }) diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index 5a4ccadb7..dc4c01e16 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -5,8 +5,9 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*HD44780Driver)(nil) @@ -60,23 +61,23 @@ func TestHD44780Driver(t *testing.T) { func TestHD44780DriverHalt(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestHD44780DriverDefaultName(t *testing.T) { d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "HD44780Driver"), true) + assert.True(t, strings.HasPrefix(d.Name(), "HD44780Driver")) } func TestHD44780DriverSetName(t *testing.T) { d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() d.SetName("my driver") - gobottest.Assert(t, d.Name(), "my driver") + assert.Equal(t, "my driver", d.Name()) } func TestHD44780DriverStart(t *testing.T) { d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestHD44780DriverStartError(t *testing.T) { @@ -92,7 +93,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_4BITMODE, "13", "15", pins) - gobottest.Assert(t, d.Start(), errors.New("Initialization error")) + assert.Errorf(t, d.Start(), "Initialization error") pins = HD44780DataPin{ D0: "31", @@ -105,7 +106,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_8BITMODE, "13", "15", pins) - gobottest.Assert(t, d.Start(), errors.New("Initialization error")) + assert.Errorf(t, d.Start(), "Initialization error") } func TestHD44780DriverWrite(t *testing.T) { @@ -113,11 +114,11 @@ func TestHD44780DriverWrite(t *testing.T) { d, _ = initTestHD44780Driver4BitModeWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Write("hello gobot"), nil) + assert.Nil(t, d.Write("hello gobot")) d, _ = initTestHD44780Driver8BitModeWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Write("hello gobot"), nil) + assert.Nil(t, d.Write("hello gobot")) } func TestHD44780DriverWriteError(t *testing.T) { @@ -129,107 +130,108 @@ func TestHD44780DriverWriteError(t *testing.T) { return errors.New("write error") } _ = d.Start() - gobottest.Assert(t, d.Write("hello gobot"), errors.New("write error")) + assert.Errorf(t, d.Write("hello gobot"), "write error") d, a = initTestHD44780Driver8BitModeWithStubbedAdaptor() a.testAdaptorDigitalWrite = func(string, byte) (err error) { return errors.New("write error") } _ = d.Start() - gobottest.Assert(t, d.Write("hello gobot"), errors.New("write error")) + assert.Errorf(t, d.Write("hello gobot"), "write error") } func TestHD44780DriverClear(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Clear(), nil) + assert.Nil(t, d.Clear()) } func TestHD44780DriverHome(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Home(), nil) + assert.Nil(t, d.Home()) } func TestHD44780DriverSetCursor(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.SetCursor(0, 3), nil) + assert.Nil(t, d.SetCursor(0, 3)) } func TestHD44780DriverSetCursorInvalid(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.SetCursor(-1, 3), errors.New("Invalid position value (-1, 3), range (1, 15)")) - gobottest.Assert(t, d.SetCursor(2, 3), errors.New("Invalid position value (2, 3), range (1, 15)")) - gobottest.Assert(t, d.SetCursor(0, -1), errors.New("Invalid position value (0, -1), range (1, 15)")) - gobottest.Assert(t, d.SetCursor(0, 16), errors.New("Invalid position value (0, 16), range (1, 15)")) + + assert.Errorf(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") + assert.Errorf(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") + assert.Errorf(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") + assert.Errorf(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") } func TestHD44780DriverDisplayOn(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Display(true), nil) + assert.Nil(t, d.Display(true)) } func TestHD44780DriverDisplayOff(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Display(false), nil) + assert.Nil(t, d.Display(false)) } func TestHD44780DriverCursorOn(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Cursor(true), nil) + assert.Nil(t, d.Cursor(true)) } func TestHD44780DriverCursorOff(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Cursor(false), nil) + assert.Nil(t, d.Cursor(false)) } func TestHD44780DriverBlinkOn(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Blink(true), nil) + assert.Nil(t, d.Blink(true)) } func TestHD44780DriverBlinkOff(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.Blink(false), nil) + assert.Nil(t, d.Blink(false)) } func TestHD44780DriverScrollLeft(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.ScrollLeft(), nil) + assert.Nil(t, d.ScrollLeft()) } func TestHD44780DriverScrollRight(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.ScrollRight(), nil) + assert.Nil(t, d.ScrollRight()) } func TestHD44780DriverLeftToRight(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.LeftToRight(), nil) + assert.Nil(t, d.LeftToRight()) } func TestHD44780DriverRightToLeft(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.RightToLeft(), nil) + assert.Nil(t, d.RightToLeft()) } func TestHD44780DriverSendCommand(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.SendCommand(0x33), nil) + assert.Nil(t, d.SendCommand(0x33)) } func TestHD44780DriverWriteChar(t *testing.T) { d := initTestHD44780Driver() - gobottest.Assert(t, d.WriteChar(0x41), nil) + assert.Nil(t, d.WriteChar(0x41)) } func TestHD44780DriverCreateChar(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - gobottest.Assert(t, d.CreateChar(0, charMap), nil) + assert.Nil(t, d.CreateChar(0, charMap)) } func TestHD44780DriverCreateCharError(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - gobottest.Assert(t, d.CreateChar(8, charMap), errors.New("can't set a custom character at a position greater than 7")) + assert.Errorf(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") } diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index cd6fc57f0..9e02e5a9b 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*LedDriver)(nil) @@ -27,8 +27,8 @@ func TestLedDriver(t *testing.T) { a := newGpioTestAdaptor() d := NewLedDriver(a, "1") - gobottest.Assert(t, d.Pin(), "1") - gobottest.Refute(t, d.Connection(), nil) + assert.Equal(t, "1", d.Pin()) + assert.NotNil(t, d.Connection()) a.testAdaptorDigitalWrite = func(string, byte) (err error) { return errors.New("write error") @@ -38,36 +38,36 @@ func TestLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - gobottest.Assert(t, err.(error), errors.New("write error")) + assert.Errorf(t, err.(error), "write error") err = d.Command("On")(nil) - gobottest.Assert(t, err.(error), errors.New("write error")) + assert.Errorf(t, err.(error), "write error") err = d.Command("Off")(nil) - gobottest.Assert(t, err.(error), errors.New("write error")) + assert.Errorf(t, err.(error), "write error") err = d.Command("Brightness")(map[string]interface{}{"level": 100.0}) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") } func TestLedDriverStart(t *testing.T) { d := initTestLedDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestLedDriverHalt(t *testing.T) { d := initTestLedDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestLedDriverToggle(t *testing.T) { d := initTestLedDriver() _ = d.Off() _ = d.Toggle() - gobottest.Assert(t, d.State(), true) + assert.True(t, d.State()) _ = d.Toggle() - gobottest.Assert(t, d.State(), false) + assert.False(t, d.State()) } func TestLedDriverBrightness(t *testing.T) { @@ -77,18 +77,18 @@ func TestLedDriverBrightness(t *testing.T) { err = errors.New("pwm error") return } - gobottest.Assert(t, d.Brightness(150), errors.New("pwm error")) + assert.Errorf(t, d.Brightness(150), "pwm error") } func TestLEDDriverDefaultName(t *testing.T) { a := newGpioTestAdaptor() d := NewLedDriver(a, "1") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "LED"), true) + assert.True(t, strings.HasPrefix(d.Name(), "LED")) } func TestLEDDriverSetName(t *testing.T) { a := newGpioTestAdaptor() d := NewLedDriver(a, "1") d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/gpio/makey_button_driver_test.go b/drivers/gpio/makey_button_driver_test.go index 0fb54c144..c810f767b 100644 --- a/drivers/gpio/makey_button_driver_test.go +++ b/drivers/gpio/makey_button_driver_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*MakeyButtonDriver)(nil) @@ -24,7 +24,7 @@ func TestMakeyButtonDriverHalt(t *testing.T) { <-d.halt close(done) }() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) select { case <-done: case <-time.After(makeyTestDelay * time.Millisecond): @@ -34,12 +34,12 @@ func TestMakeyButtonDriverHalt(t *testing.T) { func TestMakeyButtonDriver(t *testing.T) { d := initTestMakeyButtonDriver() - gobottest.Assert(t, d.Pin(), "1") - gobottest.Refute(t, d.Connection(), nil) - gobottest.Assert(t, d.interval, 10*time.Millisecond) + assert.Equal(t, "1", d.Pin()) + assert.NotNil(t, d.Connection()) + assert.Equal(t, 10*time.Millisecond, d.interval) d = NewMakeyButtonDriver(newGpioTestAdaptor(), "1", 30*time.Second) - gobottest.Assert(t, d.interval, 30*time.Second) + assert.Equal(t, 30*time.Second, d.interval) } func TestMakeyButtonDriverStart(t *testing.T) { @@ -47,10 +47,10 @@ func TestMakeyButtonDriverStart(t *testing.T) { a := newGpioTestAdaptor() d := NewMakeyButtonDriver(a, "1") - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) _ = d.Once(ButtonPush, func(data interface{}) { - gobottest.Assert(t, d.Active, true) + assert.True(t, d.Active) sem <- true }) @@ -66,7 +66,7 @@ func TestMakeyButtonDriverStart(t *testing.T) { } _ = d.Once(ButtonRelease, func(data interface{}) { - gobottest.Assert(t, d.Active, false) + assert.False(t, d.Active) sem <- true }) @@ -82,7 +82,7 @@ func TestMakeyButtonDriverStart(t *testing.T) { } _ = d.Once(Error, func(data interface{}) { - gobottest.Assert(t, data.(error).Error(), "digital read error") + assert.Equal(t, "digital read error", data.(error).Error()) sem <- true }) diff --git a/drivers/gpio/max7219_driver_test.go b/drivers/gpio/max7219_driver_test.go index dda37438b..22e92efbb 100644 --- a/drivers/gpio/max7219_driver_test.go +++ b/drivers/gpio/max7219_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*MAX7219Driver)(nil) @@ -32,21 +32,21 @@ func TestMAX7219Driver(t *testing.T) { func TestMAX7219DriverStart(t *testing.T) { d := initTestMAX7219Driver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestMAX7219DriverHalt(t *testing.T) { d := initTestMAX7219Driver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestMAX7219DriverDefaultName(t *testing.T) { d := initTestMAX7219Driver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "MAX7219Driver"), true) + assert.True(t, strings.HasPrefix(d.Name(), "MAX7219Driver")) } func TestMAX7219DriverSetName(t *testing.T) { d := initTestMAX7219Driver() d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/gpio/motor_driver_test.go b/drivers/gpio/motor_driver_test.go index aa382fec3..b81ad5742 100644 --- a/drivers/gpio/motor_driver_test.go +++ b/drivers/gpio/motor_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*MotorDriver)(nil) @@ -16,64 +16,64 @@ func initTestMotorDriver() *MotorDriver { func TestMotorDriver(t *testing.T) { d := NewMotorDriver(newGpioTestAdaptor(), "1") - gobottest.Refute(t, d.Connection(), nil) + assert.NotNil(t, d.Connection()) } func TestMotorDriverStart(t *testing.T) { d := initTestMotorDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestMotorDriverHalt(t *testing.T) { d := initTestMotorDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestMotorDriverIsOn(t *testing.T) { d := initTestMotorDriver() d.CurrentMode = "digital" d.CurrentState = 1 - gobottest.Assert(t, d.IsOn(), true) + assert.True(t, d.IsOn()) d.CurrentMode = "analog" d.CurrentSpeed = 100 - gobottest.Assert(t, d.IsOn(), true) + assert.True(t, d.IsOn()) } func TestMotorDriverIsOff(t *testing.T) { d := initTestMotorDriver() _ = d.Off() - gobottest.Assert(t, d.IsOff(), true) + assert.True(t, d.IsOff()) } func TestMotorDriverOn(t *testing.T) { d := initTestMotorDriver() d.CurrentMode = "digital" _ = d.On() - gobottest.Assert(t, d.CurrentState, uint8(1)) + assert.Equal(t, uint8(1), d.CurrentState) d.CurrentMode = "analog" d.CurrentSpeed = 0 _ = d.On() - gobottest.Assert(t, d.CurrentSpeed, uint8(255)) + assert.Equal(t, uint8(255), d.CurrentSpeed) } func TestMotorDriverOff(t *testing.T) { d := initTestMotorDriver() d.CurrentMode = "digital" _ = d.Off() - gobottest.Assert(t, d.CurrentState, uint8(0)) + assert.Equal(t, uint8(0), d.CurrentState) d.CurrentMode = "analog" d.CurrentSpeed = 100 _ = d.Off() - gobottest.Assert(t, d.CurrentSpeed, uint8(0)) + assert.Equal(t, uint8(0), d.CurrentSpeed) } func TestMotorDriverToggle(t *testing.T) { d := initTestMotorDriver() _ = d.Off() _ = d.Toggle() - gobottest.Assert(t, d.IsOn(), true) + assert.True(t, d.IsOn()) _ = d.Toggle() - gobottest.Assert(t, d.IsOn(), false) + assert.False(t, d.IsOn()) } func TestMotorDriverMin(t *testing.T) { @@ -94,15 +94,15 @@ func TestMotorDriverSpeed(t *testing.T) { func TestMotorDriverForward(t *testing.T) { d := initTestMotorDriver() _ = d.Forward(100) - gobottest.Assert(t, d.CurrentSpeed, uint8(100)) - gobottest.Assert(t, d.CurrentDirection, "forward") + assert.Equal(t, uint8(100), d.CurrentSpeed) + assert.Equal(t, "forward", d.CurrentDirection) } func TestMotorDriverBackward(t *testing.T) { d := initTestMotorDriver() _ = d.Backward(100) - gobottest.Assert(t, d.CurrentSpeed, uint8(100)) - gobottest.Assert(t, d.CurrentDirection, "backward") + assert.Equal(t, uint8(100), d.CurrentSpeed) + assert.Equal(t, "backward", d.CurrentDirection) } func TestMotorDriverDirection(t *testing.T) { @@ -121,18 +121,18 @@ func TestMotorDriverDigital(t *testing.T) { d.BackwardPin = "3" _ = d.On() - gobottest.Assert(t, d.CurrentState, uint8(1)) + assert.Equal(t, uint8(1), d.CurrentState) _ = d.Off() - gobottest.Assert(t, d.CurrentState, uint8(0)) + assert.Equal(t, uint8(0), d.CurrentState) } func TestMotorDriverDefaultName(t *testing.T) { d := initTestMotorDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Motor"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Motor")) } func TestMotorDriverSetName(t *testing.T) { d := initTestMotorDriver() d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/gpio/pir_motion_driver_test.go b/drivers/gpio/pir_motion_driver_test.go index 6cfc755b1..b7a7e87bc 100644 --- a/drivers/gpio/pir_motion_driver_test.go +++ b/drivers/gpio/pir_motion_driver_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*PIRMotionDriver)(nil) @@ -23,15 +23,15 @@ func TestPIRMotionDriverHalt(t *testing.T) { go func() { <-d.halt }() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestPIRMotionDriver(t *testing.T) { d := NewPIRMotionDriver(newGpioTestAdaptor(), "1") - gobottest.Refute(t, d.Connection(), nil) + assert.NotNil(t, d.Connection()) d = NewPIRMotionDriver(newGpioTestAdaptor(), "1", 30*time.Second) - gobottest.Assert(t, d.interval, 30*time.Second) + assert.Equal(t, 30*time.Second, d.interval) } func TestPIRMotionDriverStart(t *testing.T) { @@ -39,10 +39,10 @@ func TestPIRMotionDriverStart(t *testing.T) { a := newGpioTestAdaptor() d := NewPIRMotionDriver(a, "1") - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) _ = d.Once(MotionDetected, func(data interface{}) { - gobottest.Assert(t, d.Active, true) + assert.True(t, d.Active) sem <- true }) @@ -58,7 +58,7 @@ func TestPIRMotionDriverStart(t *testing.T) { } _ = d.Once(MotionStopped, func(data interface{}) { - gobottest.Assert(t, d.Active, false) + assert.False(t, d.Active) sem <- true }) @@ -91,11 +91,11 @@ func TestPIRMotionDriverStart(t *testing.T) { func TestPIRDriverDefaultName(t *testing.T) { d := initTestPIRMotionDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "PIR"), true) + assert.True(t, strings.HasPrefix(d.Name(), "PIR")) } func TestPIRDriverSetName(t *testing.T) { d := initTestPIRMotionDriver() d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/gpio/relay_driver_test.go b/drivers/gpio/relay_driver_test.go index 12160357a..c920871f0 100644 --- a/drivers/gpio/relay_driver_test.go +++ b/drivers/gpio/relay_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*RelayDriver)(nil) @@ -26,24 +26,24 @@ func initTestRelayDriver() (*RelayDriver, *gpioTestAdaptor) { func TestRelayDriverDefaultName(t *testing.T) { g, _ := initTestRelayDriver() - gobottest.Refute(t, g.Connection(), nil) - gobottest.Assert(t, strings.HasPrefix(g.Name(), "Relay"), true) + assert.NotNil(t, g.Connection()) + assert.True(t, strings.HasPrefix(g.Name(), "Relay")) } func TestRelayDriverSetName(t *testing.T) { g, _ := initTestRelayDriver() g.SetName("mybot") - gobottest.Assert(t, g.Name(), "mybot") + assert.Equal(t, "mybot", g.Name()) } func TestRelayDriverStart(t *testing.T) { d, _ := initTestRelayDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestRelayDriverHalt(t *testing.T) { d, _ := initTestRelayDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestRelayDriverToggle(t *testing.T) { @@ -55,14 +55,14 @@ func TestRelayDriverToggle(t *testing.T) { }) _ = d.Off() - gobottest.Assert(t, d.State(), false) - gobottest.Assert(t, lastVal, byte(0)) + assert.False(t, d.State()) + assert.Equal(t, byte(0), lastVal) _ = d.Toggle() - gobottest.Assert(t, d.State(), true) - gobottest.Assert(t, lastVal, byte(1)) + assert.True(t, d.State()) + assert.Equal(t, byte(1), lastVal) _ = d.Toggle() - gobottest.Assert(t, d.State(), false) - gobottest.Assert(t, lastVal, byte(0)) + assert.False(t, d.State()) + assert.Equal(t, byte(0), lastVal) } func TestRelayDriverToggleInverted(t *testing.T) { @@ -75,14 +75,14 @@ func TestRelayDriverToggleInverted(t *testing.T) { d.Inverted = true _ = d.Off() - gobottest.Assert(t, d.State(), false) - gobottest.Assert(t, lastVal, byte(1)) + assert.False(t, d.State()) + assert.Equal(t, byte(1), lastVal) _ = d.Toggle() - gobottest.Assert(t, d.State(), true) - gobottest.Assert(t, lastVal, byte(0)) + assert.True(t, d.State()) + assert.Equal(t, byte(0), lastVal) _ = d.Toggle() - gobottest.Assert(t, d.State(), false) - gobottest.Assert(t, lastVal, byte(1)) + assert.False(t, d.State()) + assert.Equal(t, byte(1), lastVal) } func TestRelayDriverCommands(t *testing.T) { @@ -93,17 +93,17 @@ func TestRelayDriverCommands(t *testing.T) { return nil }) - gobottest.Assert(t, d.Command("Off")(nil), nil) - gobottest.Assert(t, d.State(), false) - gobottest.Assert(t, lastVal, byte(0)) + assert.Nil(t, d.Command("Off")(nil)) + assert.False(t, d.State()) + assert.Equal(t, byte(0), lastVal) - gobottest.Assert(t, d.Command("On")(nil), nil) - gobottest.Assert(t, d.State(), true) - gobottest.Assert(t, lastVal, byte(1)) + assert.Nil(t, d.Command("On")(nil)) + assert.True(t, d.State()) + assert.Equal(t, byte(1), lastVal) - gobottest.Assert(t, d.Command("Toggle")(nil), nil) - gobottest.Assert(t, d.State(), false) - gobottest.Assert(t, lastVal, byte(0)) + assert.Nil(t, d.Command("Toggle")(nil)) + assert.False(t, d.State()) + assert.Equal(t, byte(0), lastVal) } func TestRelayDriverCommandsInverted(t *testing.T) { @@ -115,18 +115,18 @@ func TestRelayDriverCommandsInverted(t *testing.T) { }) d.Inverted = true - gobottest.Assert(t, d.Command("Off")(nil), nil) - gobottest.Assert(t, d.High(), true) - gobottest.Assert(t, d.State(), false) - gobottest.Assert(t, lastVal, byte(1)) + assert.Nil(t, d.Command("Off")(nil)) + assert.True(t, d.High()) + assert.False(t, d.State()) + assert.Equal(t, byte(1), lastVal) - gobottest.Assert(t, d.Command("On")(nil), nil) - gobottest.Assert(t, d.High(), false) - gobottest.Assert(t, d.State(), true) - gobottest.Assert(t, lastVal, byte(0)) + assert.Nil(t, d.Command("On")(nil)) + assert.False(t, d.High()) + assert.True(t, d.State()) + assert.Equal(t, byte(0), lastVal) - gobottest.Assert(t, d.Command("Toggle")(nil), nil) - gobottest.Assert(t, d.High(), true) - gobottest.Assert(t, d.State(), false) - gobottest.Assert(t, lastVal, byte(1)) + assert.Nil(t, d.Command("Toggle")(nil)) + assert.True(t, d.High()) + assert.False(t, d.State()) + assert.Equal(t, byte(1), lastVal) } diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index 2e9ffc9ca..5173b02ee 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*RgbLedDriver)(nil) @@ -28,11 +28,11 @@ func TestRgbLedDriver(t *testing.T) { a := newGpioTestAdaptor() d := NewRgbLedDriver(a, "1", "2", "3") - gobottest.Assert(t, d.Pin(), "r=1, g=2, b=3") - gobottest.Assert(t, d.RedPin(), "1") - gobottest.Assert(t, d.GreenPin(), "2") - gobottest.Assert(t, d.BluePin(), "3") - gobottest.Refute(t, d.Connection(), nil) + assert.Equal(t, "r=1, g=2, b=3", d.Pin()) + assert.Equal(t, "1", d.RedPin()) + assert.Equal(t, "2", d.GreenPin()) + assert.Equal(t, "3", d.BluePin()) + assert.NotNil(t, d.Connection()) a.testAdaptorDigitalWrite = func(string, byte) (err error) { return errors.New("write error") @@ -42,59 +42,59 @@ func TestRgbLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") err = d.Command("On")(nil) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") err = d.Command("Off")(nil) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") err = d.Command("SetRGB")(map[string]interface{}{"r": 0xff, "g": 0xff, "b": 0xff}) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") } func TestRgbLedDriverStart(t *testing.T) { d := initTestRgbLedDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestRgbLedDriverHalt(t *testing.T) { d := initTestRgbLedDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestRgbLedDriverToggle(t *testing.T) { d := initTestRgbLedDriver() _ = d.Off() _ = d.Toggle() - gobottest.Assert(t, d.State(), true) + assert.True(t, d.State()) _ = d.Toggle() - gobottest.Assert(t, d.State(), false) + assert.False(t, d.State()) } func TestRgbLedDriverSetLevel(t *testing.T) { a := newGpioTestAdaptor() d := NewRgbLedDriver(a, "1", "2", "3") - gobottest.Assert(t, d.SetLevel("1", 150), nil) + assert.Nil(t, d.SetLevel("1", 150)) d = NewRgbLedDriver(a, "1", "2", "3") a.testAdaptorPwmWrite = func(string, byte) (err error) { err = errors.New("pwm error") return } - gobottest.Assert(t, d.SetLevel("1", 150), errors.New("pwm error")) + assert.Errorf(t, d.SetLevel("1", 150), "pwm error") } func TestRgbLedDriverDefaultName(t *testing.T) { a := newGpioTestAdaptor() d := NewRgbLedDriver(a, "1", "2", "3") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "RGB"), true) + assert.True(t, strings.HasPrefix(d.Name(), "RGB")) } func TestRgbLedDriverSetName(t *testing.T) { a := newGpioTestAdaptor() d := NewRgbLedDriver(a, "1", "2", "3") d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index d34094d4b..0d3058b66 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*ServoDriver)(nil) @@ -21,69 +21,69 @@ func TestServoDriver(t *testing.T) { a := newGpioTestAdaptor() d := NewServoDriver(a, "1") - gobottest.Assert(t, d.Pin(), "1") - gobottest.Refute(t, d.Connection(), nil) + assert.Equal(t, "1", d.Pin()) + assert.NotNil(t, d.Connection()) a.testAdaptorServoWrite = func(string, byte) (err error) { return errors.New("pwm error") } err = d.Command("Min")(nil) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") err = d.Command("Center")(nil) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") err = d.Command("Max")(nil) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") err = d.Command("Move")(map[string]interface{}{"angle": 100.0}) - gobottest.Assert(t, err.(error), errors.New("pwm error")) + assert.Errorf(t, err.(error), "pwm error") } func TestServoDriverStart(t *testing.T) { d := initTestServoDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestServoDriverHalt(t *testing.T) { d := initTestServoDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestServoDriverMove(t *testing.T) { d := initTestServoDriver() _ = d.Move(100) - gobottest.Assert(t, d.CurrentAngle, uint8(100)) + assert.Equal(t, uint8(100), d.CurrentAngle) err := d.Move(200) - gobottest.Assert(t, err, ErrServoOutOfRange) + assert.Equal(t, ErrServoOutOfRange, err) } func TestServoDriverMin(t *testing.T) { d := initTestServoDriver() _ = d.Min() - gobottest.Assert(t, d.CurrentAngle, uint8(0)) + assert.Equal(t, uint8(0), d.CurrentAngle) } func TestServoDriverMax(t *testing.T) { d := initTestServoDriver() _ = d.Max() - gobottest.Assert(t, d.CurrentAngle, uint8(180)) + assert.Equal(t, uint8(180), d.CurrentAngle) } func TestServoDriverCenter(t *testing.T) { d := initTestServoDriver() _ = d.Center() - gobottest.Assert(t, d.CurrentAngle, uint8(90)) + assert.Equal(t, uint8(90), d.CurrentAngle) } func TestServoDriverDefaultName(t *testing.T) { d := initTestServoDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Servo"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Servo")) } func TestServoDriverSetName(t *testing.T) { d := initTestServoDriver() d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } diff --git a/drivers/gpio/stepper_driver_test.go b/drivers/gpio/stepper_driver_test.go index d41449c30..9e88dd693 100644 --- a/drivers/gpio/stepper_driver_test.go +++ b/drivers/gpio/stepper_driver_test.go @@ -1,12 +1,11 @@ package gpio import ( - "errors" "strings" "testing" "time" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) const ( @@ -20,7 +19,7 @@ func initStepperMotorDriver() *StepperDriver { func TestStepperDriverRun(t *testing.T) { d := initStepperMotorDriver() _ = d.Run() - gobottest.Assert(t, d.IsMoving(), true) + assert.True(t, d.IsMoving()) } func TestStepperDriverHalt(t *testing.T) { @@ -28,61 +27,61 @@ func TestStepperDriverHalt(t *testing.T) { _ = d.Run() time.Sleep(200 * time.Millisecond) _ = d.Halt() - gobottest.Assert(t, d.IsMoving(), false) + assert.False(t, d.IsMoving()) } func TestStepperDriverDefaultName(t *testing.T) { d := initStepperMotorDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Stepper"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Stepper")) } func TestStepperDriverSetName(t *testing.T) { name := "SomeStepperSriver" d := initStepperMotorDriver() d.SetName(name) - gobottest.Assert(t, d.Name(), name) + assert.Equal(t, name, d.Name()) } func TestStepperDriverSetDirection(t *testing.T) { dir := "backward" d := initStepperMotorDriver() _ = d.SetDirection(dir) - gobottest.Assert(t, d.direction, dir) + assert.Equal(t, dir, d.direction) } func TestStepperDriverDefaultDirection(t *testing.T) { d := initStepperMotorDriver() - gobottest.Assert(t, d.direction, "forward") + assert.Equal(t, "forward", d.direction) } func TestStepperDriverInvalidDirection(t *testing.T) { d := initStepperMotorDriver() err := d.SetDirection("reverse") - gobottest.Assert(t, err, errors.New("Invalid direction. Value should be forward or backward")) + assert.Errorf(t, err, "Invalid direction. Value should be forward or backward") } func TestStepperDriverMoveForward(t *testing.T) { d := initStepperMotorDriver() _ = d.Move(1) - gobottest.Assert(t, d.GetCurrentStep(), 1) + assert.Equal(t, 1, d.GetCurrentStep()) _ = d.Move(10) - gobottest.Assert(t, d.GetCurrentStep(), 11) + assert.Equal(t, 11, d.GetCurrentStep()) } func TestStepperDriverMoveBackward(t *testing.T) { d := initStepperMotorDriver() _ = d.Move(-1) - gobottest.Assert(t, d.GetCurrentStep(), stepsInRev-1) + assert.Equal(t, stepsInRev-1, d.GetCurrentStep()) _ = d.Move(-10) - gobottest.Assert(t, d.GetCurrentStep(), stepsInRev-11) + assert.Equal(t, stepsInRev-11, d.GetCurrentStep()) } func TestStepperDriverMoveFullRotation(t *testing.T) { d := initStepperMotorDriver() _ = d.Move(stepsInRev) - gobottest.Assert(t, d.GetCurrentStep(), 0) + assert.Equal(t, 0, d.GetCurrentStep()) } func TestStepperDriverMotorSetSpeedMoreThanMax(t *testing.T) { @@ -90,7 +89,7 @@ func TestStepperDriverMotorSetSpeedMoreThanMax(t *testing.T) { m := d.GetMaxSpeed() _ = d.SetSpeed(m + 1) - gobottest.Assert(t, m, d.speed) + assert.Equal(t, d.speed, m) } func TestStepperDriverMotorSetSpeedLessOrEqualMax(t *testing.T) { @@ -98,8 +97,8 @@ func TestStepperDriverMotorSetSpeedLessOrEqualMax(t *testing.T) { m := d.GetMaxSpeed() _ = d.SetSpeed(m - 1) - gobottest.Assert(t, m-1, d.speed) + assert.Equal(t, d.speed, m-1) _ = d.SetSpeed(m) - gobottest.Assert(t, m, d.speed) + assert.Equal(t, d.speed, m) } diff --git a/drivers/gpio/tm1638_driver_test.go b/drivers/gpio/tm1638_driver_test.go index ccff9152e..e7e5b7682 100644 --- a/drivers/gpio/tm1638_driver_test.go +++ b/drivers/gpio/tm1638_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*TM1638Driver)(nil) @@ -32,41 +32,41 @@ func TestTM1638Driver(t *testing.T) { func TestTM1638DriverStart(t *testing.T) { d := initTestTM1638Driver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestTM1638DriverHalt(t *testing.T) { d := initTestTM1638Driver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestTM1638DriverDefaultName(t *testing.T) { d := initTestTM1638Driver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "TM1638"), true) + assert.True(t, strings.HasPrefix(d.Name(), "TM1638")) } func TestTM1638DriverSetName(t *testing.T) { d := initTestTM1638Driver() d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } func TestTM1638DriverFromStringToByteArray(t *testing.T) { d := initTestTM1638Driver() data := d.fromStringToByteArray("Hello World") - gobottest.Assert(t, []byte{0x76, 0x7B, 0x30, 0x30, 0x5C, 0x00, 0x1D, 0x5C, 0x50, 0x30, 0x5E}, data) + assert.Equal(t, data, []byte{0x76, 0x7B, 0x30, 0x30, 0x5C, 0x00, 0x1D, 0x5C, 0x50, 0x30, 0x5E}) } func TestTM1638DriverAddFonts(t *testing.T) { d := initTestTM1638Driver() d.AddFonts(map[string]byte{"µ": 0x1C, "ß": 0x7F}) data := d.fromStringToByteArray("µß") - gobottest.Assert(t, []byte{0x1C, 0x7F}, data) + assert.Equal(t, data, []byte{0x1C, 0x7F}) } func TestTM1638DriverClearFonts(t *testing.T) { d := initTestTM1638Driver() d.ClearFonts() data := d.fromStringToByteArray("Hello World") - gobottest.Assert(t, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, data) + assert.Equal(t, data, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) } diff --git a/drivers/i2c/adafruit1109_driver_test.go b/drivers/i2c/adafruit1109_driver_test.go index 8fcb5a94d..f2c901374 100644 --- a/drivers/i2c/adafruit1109_driver_test.go +++ b/drivers/i2c/adafruit1109_driver_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Adafruit1109Driver)(nil) @@ -23,49 +23,49 @@ func TestNewAdafruit1109Driver(t *testing.T) { if !ok { t.Errorf("NewAdafruit1109Driver() should have returned a *Adafruit1109Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Refute(t, d.Connection(), nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Adafruit1109"), true) - gobottest.Assert(t, strings.Contains(d.Name(), "MCP23017"), true) - gobottest.Assert(t, strings.Contains(d.Name(), "HD44780"), true) - gobottest.Refute(t, d.MCP23017Driver, nil) - gobottest.Refute(t, d.HD44780Driver, nil) - gobottest.Refute(t, d.redPin, nil) - gobottest.Refute(t, d.greenPin, nil) - gobottest.Refute(t, d.bluePin, nil) - gobottest.Refute(t, d.selectPin, nil) - gobottest.Refute(t, d.upPin, nil) - gobottest.Refute(t, d.downPin, nil) - gobottest.Refute(t, d.leftPin, nil) - gobottest.Refute(t, d.rightPin, nil) - gobottest.Refute(t, d.rwPin, nil) - gobottest.Refute(t, d.rsPin, nil) - gobottest.Refute(t, d.enPin, nil) - gobottest.Refute(t, d.dataPinD4, nil) - gobottest.Refute(t, d.dataPinD5, nil) - gobottest.Refute(t, d.dataPinD6, nil) - gobottest.Refute(t, d.dataPinD7, nil) + assert.NotNil(t, d.Driver) + assert.NotNil(t, d.Connection()) + assert.True(t, strings.HasPrefix(d.Name(), "Adafruit1109")) + assert.Contains(t, d.Name(), "MCP23017") + assert.Contains(t, d.Name(), "HD44780") + assert.NotNil(t, d.MCP23017Driver) + assert.NotNil(t, d.HD44780Driver) + assert.NotNil(t, d.redPin) + assert.NotNil(t, d.greenPin) + assert.NotNil(t, d.bluePin) + assert.NotNil(t, d.selectPin) + assert.NotNil(t, d.upPin) + assert.NotNil(t, d.downPin) + assert.NotNil(t, d.leftPin) + assert.NotNil(t, d.rightPin) + assert.NotNil(t, d.rwPin) + assert.NotNil(t, d.rsPin) + assert.NotNil(t, d.enPin) + assert.NotNil(t, d.dataPinD4) + assert.NotNil(t, d.dataPinD5) + assert.NotNil(t, d.dataPinD6) + assert.NotNil(t, d.dataPinD7) } func TestAdafruit1109Connect(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - gobottest.Assert(t, d.Connect(), nil) + assert.Nil(t, d.Connect()) } func TestAdafruit1109Finalize(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - gobottest.Assert(t, d.Finalize(), nil) + assert.Nil(t, d.Finalize()) } func TestAdafruit1109SetName(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() d.SetName("foo") - gobottest.Assert(t, d.name, "foo") + assert.Equal(t, "foo", d.name) } func TestAdafruit1109Start(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestAdafruit1109StartWriteErr(t *testing.T) { @@ -73,7 +73,7 @@ func TestAdafruit1109StartWriteErr(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.Start(), errors.New("write error")) + assert.Errorf(t, d.Start(), "write error") } func TestAdafruit1109StartReadErr(t *testing.T) { @@ -81,13 +81,13 @@ func TestAdafruit1109StartReadErr(t *testing.T) { adaptor.i2cReadImpl = func([]byte) (int, error) { return 0, errors.New("read error") } - gobottest.Assert(t, d.Start(), errors.New("MCP write-read: MCP write-ReadByteData(reg=0): read error")) + assert.Errorf(t, d.Start(), "MCP write-read: MCP write-ReadByteData(reg=0): read error") } func TestAdafruit1109Halt(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestAdafruit1109DigitalRead(t *testing.T) { @@ -128,11 +128,11 @@ func TestAdafruit1109DigitalRead(t *testing.T) { // act got, err := d.DigitalRead(name) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], tc.wantReg) - gobottest.Assert(t, got, 1) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, tc.wantReg, a.written[0]) + assert.Equal(t, 1, got) }) } } @@ -160,9 +160,9 @@ func TestAdafruit1109SelectButton(t *testing.T) { // act got, err := d.SelectButton() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, got, tc.want) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, tc.want, got) }) } } @@ -190,9 +190,9 @@ func TestAdafruit1109UpButton(t *testing.T) { // act got, err := d.UpButton() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, got, tc.want) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, tc.want, got) }) } } @@ -220,9 +220,9 @@ func TestAdafruit1109DownButton(t *testing.T) { // act got, err := d.DownButton() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, got, tc.want) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, tc.want, got) }) } } @@ -250,9 +250,9 @@ func TestAdafruit1109LeftButton(t *testing.T) { // act got, err := d.LeftButton() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, got, tc.want) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, tc.want, got) }) } } @@ -280,9 +280,9 @@ func TestAdafruit1109RightButton(t *testing.T) { // act got, err := d.RightButton() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, got, tc.want) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, tc.want, got) }) } } @@ -297,7 +297,7 @@ func TestAdafruit1109_parseID(t *testing.T) { // act got := adafruit1109ParseID(id) // assert - gobottest.Assert(t, got, adafruit1109PortPin{port, pin}) + assert.Equal(t, adafruit1109PortPin{port, pin}, got) }) } } diff --git a/drivers/i2c/adafruit_driver_test.go b/drivers/i2c/adafruit_driver_test.go index 4f2bbd6b2..d100a73fe 100644 --- a/drivers/i2c/adafruit_driver_test.go +++ b/drivers/i2c/adafruit_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation implements the gobot.Driver interface @@ -30,14 +30,14 @@ func TestNewAdafruitMotorHatDriver(t *testing.T) { if !ok { t.Errorf("AdafruitMotorHatDriver() should have returned a *AdafruitMotorHatDriver") } - gobottest.Assert(t, strings.HasPrefix(d.Name(), "AdafruitMotorHat"), true) + assert.True(t, strings.HasPrefix(d.Name(), "AdafruitMotorHat")) } // Methods func TestAdafruitMotorHatDriverStart(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Refute(t, ada.Connection(), nil) - gobottest.Assert(t, ada.Start(), nil) + assert.NotNil(t, ada.Connection()) + assert.Nil(t, ada.Start()) } func TestAdafruitMotorHatDriverStartWriteError(t *testing.T) { @@ -45,7 +45,7 @@ func TestAdafruitMotorHatDriverStartWriteError(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.Start(), errors.New("write error")) + assert.Errorf(t, d.Start(), "write error") } func TestAdafruitMotorHatDriverStartReadError(t *testing.T) { @@ -53,19 +53,19 @@ func TestAdafruitMotorHatDriverStartReadError(t *testing.T) { adaptor.i2cReadImpl = func([]byte) (int, error) { return 0, errors.New("read error") } - gobottest.Assert(t, d.Start(), errors.New("read error")) + assert.Errorf(t, d.Start(), "read error") } func TestAdafruitMotorHatDriverStartConnectError(t *testing.T) { d, adaptor := initTestAdafruitMotorHatDriverWithStubbedAdaptor() adaptor.Testi2cConnectErr(true) - gobottest.Assert(t, d.Start(), errors.New("Invalid i2c connection")) + assert.Errorf(t, d.Start(), "Invalid i2c connection") } func TestAdafruitMotorHatDriverHalt(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Halt(), nil) + assert.Nil(t, ada.Halt()) } func TestSetHatAddresses(t *testing.T) { @@ -73,48 +73,48 @@ func TestSetHatAddresses(t *testing.T) { motorHatAddr := 0x61 servoHatAddr := 0x41 - gobottest.Assert(t, ada.SetMotorHatAddress(motorHatAddr), nil) - gobottest.Assert(t, ada.SetServoHatAddress(servoHatAddr), nil) + assert.Nil(t, ada.SetMotorHatAddress(motorHatAddr)) + assert.Nil(t, ada.SetServoHatAddress(servoHatAddr)) } func TestAdafruitMotorHatDriverSetServoMotorFreq(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) freq := 60.0 err := ada.SetServoMotorFreq(freq) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestAdafruitMotorHatDriverSetServoMotorFreqError(t *testing.T) { ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } freq := 60.0 - gobottest.Assert(t, ada.SetServoMotorFreq(freq), errors.New("write error")) + assert.Errorf(t, ada.SetServoMotorFreq(freq), "write error") } func TestAdafruitMotorHatDriverSetServoMotorPulse(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) var channel byte = 7 var on int32 = 1234 var off int32 = 4321 err := ada.SetServoMotorPulse(channel, on, off) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestAdafruitMotorHatDriverSetServoMotorPulseError(t *testing.T) { ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } @@ -122,124 +122,124 @@ func TestAdafruitMotorHatDriverSetServoMotorPulseError(t *testing.T) { var channel byte = 7 var on int32 = 1234 var off int32 = 4321 - gobottest.Assert(t, ada.SetServoMotorPulse(channel, on, off), errors.New("write error")) + assert.Errorf(t, ada.SetServoMotorPulse(channel, on, off), "write error") } func TestAdafruitMotorHatDriverSetDCMotorSpeed(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) dcMotor := 1 var speed int32 = 255 err := ada.SetDCMotorSpeed(dcMotor, speed) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestAdafruitMotorHatDriverSetDCMotorSpeedError(t *testing.T) { ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, ada.SetDCMotorSpeed(1, 255), errors.New("write error")) + assert.Errorf(t, ada.SetDCMotorSpeed(1, 255), "write error") } func TestAdafruitMotorHatDriverRunDCMotor(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) dcMotor := 1 - gobottest.Assert(t, ada.RunDCMotor(dcMotor, AdafruitForward), nil) - gobottest.Assert(t, ada.RunDCMotor(dcMotor, AdafruitBackward), nil) - gobottest.Assert(t, ada.RunDCMotor(dcMotor, AdafruitRelease), nil) + assert.Nil(t, ada.RunDCMotor(dcMotor, AdafruitForward)) + assert.Nil(t, ada.RunDCMotor(dcMotor, AdafruitBackward)) + assert.Nil(t, ada.RunDCMotor(dcMotor, AdafruitRelease)) } func TestAdafruitMotorHatDriverRunDCMotorError(t *testing.T) { ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } dcMotor := 1 - gobottest.Assert(t, ada.RunDCMotor(dcMotor, AdafruitForward), errors.New("write error")) - gobottest.Assert(t, ada.RunDCMotor(dcMotor, AdafruitBackward), errors.New("write error")) - gobottest.Assert(t, ada.RunDCMotor(dcMotor, AdafruitRelease), errors.New("write error")) + assert.Errorf(t, ada.RunDCMotor(dcMotor, AdafruitForward), "write error") + assert.Errorf(t, ada.RunDCMotor(dcMotor, AdafruitBackward), "write error") + assert.Errorf(t, ada.RunDCMotor(dcMotor, AdafruitRelease), "write error") } func TestAdafruitMotorHatDriverSetStepperMotorSpeed(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) stepperMotor := 1 rpm := 30 - gobottest.Assert(t, ada.SetStepperMotorSpeed(stepperMotor, rpm), nil) + assert.Nil(t, ada.SetStepperMotorSpeed(stepperMotor, rpm)) } func TestAdafruitMotorHatDriverStepperMicroStep(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) // NOTE: not using the direction and style constants to prevent importing // the i2c package stepperMotor := 0 steps := 50 err := ada.Step(stepperMotor, steps, 1, 3) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestAdafruitMotorHatDriverStepperSingleStep(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) // NOTE: not using the direction and style constants to prevent importing // the i2c package stepperMotor := 0 steps := 50 err := ada.Step(stepperMotor, steps, 1, 0) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestAdafruitMotorHatDriverStepperDoubleStep(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) // NOTE: not using the direction and style constants to prevent importing // the i2c package stepperMotor := 0 steps := 50 err := ada.Step(stepperMotor, steps, 1, 1) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestAdafruitMotorHatDriverStepperInterleaveStep(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - gobottest.Assert(t, ada.Start(), nil) + assert.Nil(t, ada.Start()) // NOTE: not using the direction and style constants to prevent importing // the i2c package stepperMotor := 0 steps := 50 err := ada.Step(stepperMotor, steps, 1, 2) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestAdafruitMotorHatDriverSetName(t *testing.T) { d := initTestAdafruitMotorHatDriver() d.SetName("TESTME") - gobottest.Assert(t, d.Name(), "TESTME") + assert.Equal(t, "TESTME", d.Name()) } func TestAdafruitMotorHatDriverOptions(t *testing.T) { d := NewAdafruitMotorHatDriver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } diff --git a/drivers/i2c/ads1x15_driver_1015_test.go b/drivers/i2c/ads1x15_driver_1015_test.go index 8e009bcd6..ef882fa39 100644 --- a/drivers/i2c/ads1x15_driver_1015_test.go +++ b/drivers/i2c/ads1x15_driver_1015_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func initTestADS1015DriverWithStubbedAdaptor() (*ADS1x15Driver, *i2cTestAdaptor) { @@ -23,11 +23,11 @@ func TestNewADS1015Driver(t *testing.T) { if !ok { t.Errorf("NewADS1015Driver() should have returned a *ADS1x15Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "ADS1015"), true) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "ADS1015")) for i := 0; i <= 3; i++ { - gobottest.Assert(t, d.channelCfgs[i].gain, 1) - gobottest.Assert(t, d.channelCfgs[i].dataRate, 1600) + assert.Equal(t, 1, d.channelCfgs[i].gain) + assert.Equal(t, 1600, d.channelCfgs[i].dataRate) } } @@ -35,10 +35,10 @@ func TestADS1015Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewADS1015Driver(newI2cTestAdaptor(), WithBus(2), WithADS1x15Gain(2), WithADS1x15DataRate(920)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) for i := 0; i <= 3; i++ { - gobottest.Assert(t, d.channelCfgs[i].gain, 2) - gobottest.Assert(t, d.channelCfgs[i].dataRate, 920) + assert.Equal(t, 2, d.channelCfgs[i].gain) + assert.Equal(t, 920, d.channelCfgs[i].dataRate) } } @@ -46,7 +46,7 @@ func TestADS1015WithADS1x15BestGainForVoltage(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() WithADS1x15BestGainForVoltage(1.01)(d) for i := 0; i <= 3; i++ { - gobottest.Assert(t, d.channelCfgs[i].gain, 3) + assert.Equal(t, 3, d.channelCfgs[i].gain) } } @@ -56,10 +56,10 @@ func TestADS1015WithADS1x15ChannelBestGainForVoltage(t *testing.T) { WithADS1x15ChannelBestGainForVoltage(1, 2.5)(d) WithADS1x15ChannelBestGainForVoltage(2, 3.3)(d) WithADS1x15ChannelBestGainForVoltage(3, 5.0)(d) - gobottest.Assert(t, d.channelCfgs[0].gain, 3) - gobottest.Assert(t, d.channelCfgs[1].gain, 1) - gobottest.Assert(t, d.channelCfgs[2].gain, 1) - gobottest.Assert(t, d.channelCfgs[3].gain, 0) + assert.Equal(t, 3, d.channelCfgs[0].gain) + assert.Equal(t, 1, d.channelCfgs[1].gain) + assert.Equal(t, 1, d.channelCfgs[2].gain) + assert.Equal(t, 0, d.channelCfgs[3].gain) } func TestADS1015AnalogRead(t *testing.T) { @@ -72,39 +72,39 @@ func TestADS1015AnalogRead(t *testing.T) { } val, err := d.AnalogRead("0") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("1") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("2") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("3") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("0-1") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("0-3") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("1-3") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("2-3") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) _, err = d.AnalogRead("3-2") - gobottest.Refute(t, err.Error(), nil) + assert.NotNil(t, err.Error()) } func TestADS1x15AnalogReadError(t *testing.T) { @@ -115,14 +115,14 @@ func TestADS1x15AnalogReadError(t *testing.T) { } _, err := d.AnalogRead("0") - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestADS1x15AnalogReadInvalidPin(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.AnalogRead("99") - gobottest.Assert(t, err, errors.New("Invalid channel (99), must be between 0 and 3")) + assert.Errorf(t, err, "Invalid channel (99), must be between 0 and 3") } func TestADS1x15AnalogReadWriteError(t *testing.T) { @@ -133,41 +133,41 @@ func TestADS1x15AnalogReadWriteError(t *testing.T) { } _, err := d.AnalogRead("0") - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") _, err = d.AnalogRead("0-1") - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") _, err = d.AnalogRead("2-3") - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } func TestADS1x15ReadInvalidChannel(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(9, 1, 1600) - gobottest.Assert(t, err, errors.New("Invalid channel (9), must be between 0 and 3")) + assert.Errorf(t, err, "Invalid channel (9), must be between 0 and 3") } func TestADS1x15ReadInvalidGain(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(0, 8, 1600) - gobottest.Assert(t, err, errors.New("Gain (8) must be one of: [0 1 2 3 4 5 6 7]")) + assert.Errorf(t, err, "Gain (8) must be one of: [0 1 2 3 4 5 6 7]") } func TestADS1x15ReadInvalidDataRate(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(0, 1, 321) - gobottest.Assert(t, err, errors.New("Invalid data rate (321). Accepted values: [128 250 490 920 1600 2400 3300]")) + assert.Errorf(t, err, "Invalid data rate (321). Accepted values: [128 250 490 920 1600 2400 3300]") } func TestADS1x15ReadDifferenceInvalidChannel(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.ReadDifference(9, 1, 1600) - gobottest.Assert(t, err, errors.New("Invalid channel (9), must be between 0 and 3")) + assert.Errorf(t, err, "Invalid channel (9), must be between 0 and 3") } func TestADS1015_rawRead(t *testing.T) { @@ -269,16 +269,16 @@ func TestADS1015_rawRead(t *testing.T) { // act got, err := d.rawRead(channel, channelOffset, tt.gain, tt.dataRate) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, tt.want) - gobottest.Assert(t, numCallsRead, 3) - gobottest.Assert(t, len(a.written), 6) - gobottest.Assert(t, a.written[0], uint8(ads1x15PointerConfig)) - gobottest.Assert(t, a.written[1], tt.wantConfig[0]) // MSByte: OS, MUX, PGA, MODE - gobottest.Assert(t, a.written[2], tt.wantConfig[1]) // LSByte: DR, COMP_* - gobottest.Assert(t, a.written[3], uint8(ads1x15PointerConfig)) // first check for no conversion - gobottest.Assert(t, a.written[4], uint8(ads1x15PointerConfig)) // second check for no conversion - gobottest.Assert(t, a.written[5], uint8(ads1x15PointerConversion)) + assert.Nil(t, err) + assert.Equal(t, tt.want, got) + assert.Equal(t, 3, numCallsRead) + assert.Equal(t, 6, len(a.written)) + assert.Equal(t, uint8(ads1x15PointerConfig), a.written[0]) + assert.Equal(t, tt.wantConfig[0], a.written[1]) // MSByte: OS, MUX, PGA, MODE + assert.Equal(t, tt.wantConfig[1], a.written[2]) // LSByte: DR, COMP_* + assert.Equal(t, uint8(ads1x15PointerConfig), a.written[3]) // first check for no conversion + assert.Equal(t, uint8(ads1x15PointerConfig), a.written[4]) // second check for no conversion + assert.Equal(t, uint8(ads1x15PointerConversion), a.written[5]) }) } } diff --git a/drivers/i2c/ads1x15_driver_1115_test.go b/drivers/i2c/ads1x15_driver_1115_test.go index 617d39fa7..5b3e5559c 100644 --- a/drivers/i2c/ads1x15_driver_1115_test.go +++ b/drivers/i2c/ads1x15_driver_1115_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func initTestADS1115DriverWithStubbedAdaptor() (*ADS1x15Driver, *i2cTestAdaptor) { @@ -23,11 +23,11 @@ func TestNewADS1115Driver(t *testing.T) { if !ok { t.Errorf("NewADS1115Driver() should have returned a *ADS1x15Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "ADS1115"), true) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "ADS1115")) for i := 0; i <= 3; i++ { - gobottest.Assert(t, d.channelCfgs[i].gain, 1) - gobottest.Assert(t, d.channelCfgs[i].dataRate, 128) + assert.Equal(t, 1, d.channelCfgs[i].gain) + assert.Equal(t, 128, d.channelCfgs[i].dataRate) } } @@ -35,10 +35,10 @@ func TestADS1115Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewADS1115Driver(newI2cTestAdaptor(), WithBus(2), WithADS1x15Gain(2), WithADS1x15DataRate(860)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) for i := 0; i <= 3; i++ { - gobottest.Assert(t, d.channelCfgs[i].gain, 2) - gobottest.Assert(t, d.channelCfgs[i].dataRate, 860) + assert.Equal(t, 2, d.channelCfgs[i].gain) + assert.Equal(t, 860, d.channelCfgs[i].dataRate) } } @@ -46,7 +46,7 @@ func TestADS1115WithADS1x15BestGainForVoltage(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() WithADS1x15BestGainForVoltage(1.01)(d) for i := 0; i <= 3; i++ { - gobottest.Assert(t, d.channelCfgs[i].gain, 3) + assert.Equal(t, 3, d.channelCfgs[i].gain) } } @@ -56,10 +56,10 @@ func TestADS1115WithADS1x15ChannelBestGainForVoltage(t *testing.T) { WithADS1x15ChannelBestGainForVoltage(1, 2.5)(d) WithADS1x15ChannelBestGainForVoltage(2, 3.3)(d) WithADS1x15ChannelBestGainForVoltage(3, 5.0)(d) - gobottest.Assert(t, d.channelCfgs[0].gain, 3) - gobottest.Assert(t, d.channelCfgs[1].gain, 1) - gobottest.Assert(t, d.channelCfgs[2].gain, 1) - gobottest.Assert(t, d.channelCfgs[3].gain, 0) + assert.Equal(t, 3, d.channelCfgs[0].gain) + assert.Equal(t, 1, d.channelCfgs[1].gain) + assert.Equal(t, 1, d.channelCfgs[2].gain) + assert.Equal(t, 0, d.channelCfgs[3].gain) } func TestADS1115AnalogRead(t *testing.T) { @@ -72,39 +72,39 @@ func TestADS1115AnalogRead(t *testing.T) { } val, err := d.AnalogRead("0") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("1") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("2") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("3") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("0-1") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("0-3") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("1-3") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) val, err = d.AnalogRead("2-3") - gobottest.Assert(t, val, 32767) - gobottest.Assert(t, err, nil) + assert.Equal(t, 32767, val) + assert.Nil(t, err) _, err = d.AnalogRead("3-2") - gobottest.Refute(t, err.Error(), nil) + assert.NotNil(t, err.Error()) } func TestADS1115AnalogReadError(t *testing.T) { @@ -115,14 +115,14 @@ func TestADS1115AnalogReadError(t *testing.T) { } _, err := d.AnalogRead("0") - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestADS1115AnalogReadInvalidPin(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.AnalogRead("98") - gobottest.Assert(t, err, errors.New("Invalid channel (98), must be between 0 and 3")) + assert.Errorf(t, err, "Invalid channel (98), must be between 0 and 3") } func TestADS1115AnalogReadWriteError(t *testing.T) { @@ -133,41 +133,41 @@ func TestADS1115AnalogReadWriteError(t *testing.T) { } _, err := d.AnalogRead("0") - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") _, err = d.AnalogRead("0-1") - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") _, err = d.AnalogRead("2-3") - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } func TestADS1115ReadInvalidChannel(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(7, 1, 1600) - gobottest.Assert(t, err, errors.New("Invalid channel (7), must be between 0 and 3")) + assert.Errorf(t, err, "Invalid channel (7), must be between 0 and 3") } func TestADS1115ReadInvalidGain(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(0, 21, 1600) - gobottest.Assert(t, err, errors.New("Gain (21) must be one of: [0 1 2 3 4 5 6 7]")) + assert.Errorf(t, err, "Gain (21) must be one of: [0 1 2 3 4 5 6 7]") } func TestADS1115ReadInvalidDataRate(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(0, 1, 678) - gobottest.Assert(t, err, errors.New("Invalid data rate (678). Accepted values: [8 16 32 64 128 250 475 860]")) + assert.Errorf(t, err, "Invalid data rate (678). Accepted values: [8 16 32 64 128 250 475 860]") } func TestADS1115ReadDifferenceInvalidChannel(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.ReadDifference(5, 1, 1600) - gobottest.Assert(t, err, errors.New("Invalid channel (5), must be between 0 and 3")) + assert.Errorf(t, err, "Invalid channel (5), must be between 0 and 3") } func TestADS1115_rawRead(t *testing.T) { @@ -269,16 +269,16 @@ func TestADS1115_rawRead(t *testing.T) { // act got, err := d.rawRead(channel, channelOffset, tt.gain, tt.dataRate) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, tt.want) - gobottest.Assert(t, numCallsRead, 3) - gobottest.Assert(t, len(a.written), 6) - gobottest.Assert(t, a.written[0], uint8(ads1x15PointerConfig)) - gobottest.Assert(t, a.written[1], tt.wantConfig[0]) // MSByte: OS, MUX, PGA, MODE - gobottest.Assert(t, a.written[2], tt.wantConfig[1]) // LSByte: DR, COMP_* - gobottest.Assert(t, a.written[3], uint8(ads1x15PointerConfig)) // first check for no conversion - gobottest.Assert(t, a.written[4], uint8(ads1x15PointerConfig)) // second check for no conversion - gobottest.Assert(t, a.written[5], uint8(ads1x15PointerConversion)) + assert.Nil(t, err) + assert.Equal(t, tt.want, got) + assert.Equal(t, 3, numCallsRead) + assert.Equal(t, 6, len(a.written)) + assert.Equal(t, uint8(ads1x15PointerConfig), a.written[0]) + assert.Equal(t, tt.wantConfig[0], a.written[1]) // MSByte: OS, MUX, PGA, MODE + assert.Equal(t, tt.wantConfig[1], a.written[2]) // LSByte: DR, COMP_* + assert.Equal(t, uint8(ads1x15PointerConfig), a.written[3]) // first check for no conversion + assert.Equal(t, uint8(ads1x15PointerConfig), a.written[4]) // second check for no conversion + assert.Equal(t, uint8(ads1x15PointerConversion), a.written[5]) }) } } diff --git a/drivers/i2c/ads1x15_driver_test.go b/drivers/i2c/ads1x15_driver_test.go index 948a36597..d842367f9 100644 --- a/drivers/i2c/ads1x15_driver_test.go +++ b/drivers/i2c/ads1x15_driver_test.go @@ -1,12 +1,11 @@ package i2c import ( - "errors" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -48,8 +47,8 @@ func TestADS1x15CommandsReadDifferenceWithDefaults(t *testing.T) { // act result := d.Command("ReadDifferenceWithDefaults")(ads1x15TestChannel) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) - gobottest.Assert(t, result.(map[string]interface{})["val"], -4.096) + assert.Nil(t, result.(map[string]interface{})["err"]) + assert.Equal(t, -4.096, result.(map[string]interface{})["val"]) } func TestADS1x15CommandsReadDifference(t *testing.T) { @@ -58,8 +57,8 @@ func TestADS1x15CommandsReadDifference(t *testing.T) { // act result := d.Command("ReadDifference")(ads1x15TestChannelGainDataRate) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) - gobottest.Assert(t, result.(map[string]interface{})["val"], -2.048) + assert.Nil(t, result.(map[string]interface{})["err"]) + assert.Equal(t, -2.048, result.(map[string]interface{})["val"]) } func TestADS1x15CommandsReadWithDefaults(t *testing.T) { @@ -68,8 +67,8 @@ func TestADS1x15CommandsReadWithDefaults(t *testing.T) { // act result := d.Command("ReadWithDefaults")(ads1x15TestChannel) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) - gobottest.Assert(t, result.(map[string]interface{})["val"], -4.096) + assert.Nil(t, result.(map[string]interface{})["err"]) + assert.Equal(t, -4.096, result.(map[string]interface{})["val"]) } func TestADS1x15CommandsRead(t *testing.T) { @@ -78,8 +77,8 @@ func TestADS1x15CommandsRead(t *testing.T) { // act result := d.Command("Read")(ads1x15TestChannelGainDataRate) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) - gobottest.Assert(t, result.(map[string]interface{})["val"], -2.048) + assert.Nil(t, result.(map[string]interface{})["err"]) + assert.Equal(t, -2.048, result.(map[string]interface{})["val"]) } func TestADS1x15CommandsAnalogRead(t *testing.T) { @@ -91,14 +90,14 @@ func TestADS1x15CommandsAnalogRead(t *testing.T) { // act result := d.Command("AnalogRead")(ads1x15TestPin) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) - gobottest.Assert(t, result.(map[string]interface{})["val"], -32768) + assert.Nil(t, result.(map[string]interface{})["err"]) + assert.Equal(t, -32768, result.(map[string]interface{})["val"]) } func TestADS1x15_ads1x15BestGainForVoltage(t *testing.T) { g, _ := ads1x15BestGainForVoltage(1.5) - gobottest.Assert(t, g, 2) + assert.Equal(t, 2, g) _, err := ads1x15BestGainForVoltage(20.0) - gobottest.Assert(t, err, errors.New("The maximum voltage which can be read is 6.144000")) + assert.Errorf(t, err, "The maximum voltage which can be read is 6.144000") } diff --git a/drivers/i2c/adxl345_driver_test.go b/drivers/i2c/adxl345_driver_test.go index d2f98f88c..c74f8104e 100644 --- a/drivers/i2c/adxl345_driver_test.go +++ b/drivers/i2c/adxl345_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -25,21 +25,21 @@ func TestNewADXL345Driver(t *testing.T) { if !ok { t.Errorf("NewADXL345Driver() should have returned a *ADXL345Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "ADXL345"), true) - gobottest.Assert(t, d.defaultAddress, 0x53) - gobottest.Assert(t, d.powerCtl.measure, uint8(1)) - gobottest.Assert(t, d.dataFormat.fullScaleRange, ADXL345FsRangeConfig(0x00)) - gobottest.Assert(t, d.bwRate.rate, ADXL345RateConfig(0x0A)) - gobottest.Assert(t, d.bwRate.lowPower, true) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "ADXL345")) + assert.Equal(t, 0x53, d.defaultAddress) + assert.Equal(t, uint8(1), d.powerCtl.measure) + assert.Equal(t, ADXL345FsRangeConfig(0x00), d.dataFormat.fullScaleRange) + assert.Equal(t, ADXL345RateConfig(0x0A), d.bwRate.rate) + assert.True(t, d.bwRate.lowPower) } func TestADXL345Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewADXL345Driver(newI2cTestAdaptor(), WithBus(2), WithADXL345LowPowerMode(false)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.bwRate.lowPower, false) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.False(t, d.bwRate.lowPower) } func TestADXL345WithADXL345DataOutputRate(t *testing.T) { @@ -52,8 +52,8 @@ func TestADXL345WithADXL345DataOutputRate(t *testing.T) { // act WithADXL345DataOutputRate(setVal)(d) // assert - gobottest.Assert(t, d.bwRate.rate, setVal) - gobottest.Assert(t, len(a.written), 0) + assert.Equal(t, setVal, d.bwRate.rate) + assert.Equal(t, 0, len(a.written)) } func TestADXL345WithADXL345FullScaleRange(t *testing.T) { @@ -66,8 +66,8 @@ func TestADXL345WithADXL345FullScaleRange(t *testing.T) { // act WithADXL345FullScaleRange(setVal)(d) // assert - gobottest.Assert(t, d.dataFormat.fullScaleRange, setVal) - gobottest.Assert(t, len(a.written), 0) + assert.Equal(t, setVal, d.dataFormat.fullScaleRange) + assert.Equal(t, 0, len(a.written)) } func TestADXL345UseLowPower(t *testing.T) { @@ -85,11 +85,11 @@ func TestADXL345UseLowPower(t *testing.T) { // act err := d.UseLowPower(setVal) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, d.bwRate.lowPower, setVal) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, a.written[1], wantVal) + assert.Nil(t, err) + assert.Equal(t, setVal, d.bwRate.lowPower) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, wantVal, a.written[1]) } func TestADXL345SetRate(t *testing.T) { @@ -107,11 +107,11 @@ func TestADXL345SetRate(t *testing.T) { // act err := d.SetRate(setVal) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, d.bwRate.rate, setVal) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, a.written[1], wantVal) + assert.Nil(t, err) + assert.Equal(t, setVal, d.bwRate.rate) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, wantVal, a.written[1]) } func TestADXL345SetRange(t *testing.T) { @@ -129,11 +129,11 @@ func TestADXL345SetRange(t *testing.T) { // act err := d.SetRange(setVal) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, d.dataFormat.fullScaleRange, setVal) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, a.written[1], wantVal) + assert.Nil(t, err) + assert.Equal(t, setVal, d.dataFormat.fullScaleRange) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, wantVal, a.written[1]) } func TestADXL345RawXYZ(t *testing.T) { @@ -184,13 +184,13 @@ func TestADXL345RawXYZ(t *testing.T) { // act gotX, gotY, gotZ, err := d.RawXYZ() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, gotX, tc.wantX) - gobottest.Assert(t, gotY, tc.wantY) - gobottest.Assert(t, gotZ, tc.wantZ) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(0x32)) + assert.Nil(t, err) + assert.Equal(t, tc.wantX, gotX) + assert.Equal(t, tc.wantY, gotY) + assert.Equal(t, tc.wantZ, gotZ) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(0x32), a.written[0]) }) } } @@ -205,7 +205,7 @@ func TestADXL345RawXYZError(t *testing.T) { // act _, _, _, err := d.RawXYZ() // assert - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestADXL345XYZ(t *testing.T) { @@ -252,9 +252,9 @@ func TestADXL345XYZ(t *testing.T) { // act x, y, z, _ := d.XYZ() // assert - gobottest.Assert(t, x, tc.wantX) - gobottest.Assert(t, y, tc.wantY) - gobottest.Assert(t, z, tc.wantZ) + assert.Equal(t, tc.wantX, x) + assert.Equal(t, tc.wantY, y) + assert.Equal(t, tc.wantZ, z) }) } } @@ -269,7 +269,7 @@ func TestADXL345XYZError(t *testing.T) { // act _, _, _, err := d.XYZ() // assert - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestADXL345_initialize(t *testing.T) { @@ -292,14 +292,14 @@ func TestADXL345_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 6) - gobottest.Assert(t, a.written[0], wantRateReg) - gobottest.Assert(t, a.written[1], wantRateRegVal) - gobottest.Assert(t, a.written[2], wantPwrReg) - gobottest.Assert(t, a.written[3], wantPwrRegVal) - gobottest.Assert(t, a.written[4], wantFormatReg) - gobottest.Assert(t, a.written[5], wantFormatRegVal) + assert.Nil(t, err) + assert.Equal(t, 6, len(a.written)) + assert.Equal(t, wantRateReg, a.written[0]) + assert.Equal(t, wantRateRegVal, a.written[1]) + assert.Equal(t, wantPwrReg, a.written[2]) + assert.Equal(t, wantPwrRegVal, a.written[3]) + assert.Equal(t, wantFormatReg, a.written[4]) + assert.Equal(t, wantFormatRegVal, a.written[5]) } func TestADXL345_shutdown(t *testing.T) { @@ -316,8 +316,8 @@ func TestADXL345_shutdown(t *testing.T) { // act, assert - shutdown() must be called on Halt() err := d.Halt() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, a.written[1], wantVal) + assert.Nil(t, err) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, wantVal, a.written[1]) } diff --git a/drivers/i2c/bh1750_driver_test.go b/drivers/i2c/bh1750_driver_test.go index 9d8fc94a1..a914d4407 100644 --- a/drivers/i2c/bh1750_driver_test.go +++ b/drivers/i2c/bh1750_driver_test.go @@ -7,8 +7,8 @@ import ( "bytes" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -30,32 +30,32 @@ func TestNewBH1750Driver(t *testing.T) { if !ok { t.Errorf("NewBH1750Driver() should have returned a *BH1750Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "BH1750"), true) - gobottest.Assert(t, d.defaultAddress, 0x23) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "BH1750")) + assert.Equal(t, 0x23, d.defaultAddress) } func TestBH1750Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewBH1750Driver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestBH1750Start(t *testing.T) { d := NewBH1750Driver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestBH1750Halt(t *testing.T) { d, _ := initTestBH1750DriverWithStubbedAdaptor() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestBH1750NullLux(t *testing.T) { d, _ := initTestBH1750DriverWithStubbedAdaptor() lux, _ := d.Lux() - gobottest.Assert(t, lux, 0) + assert.Equal(t, 0, lux) } func TestBH1750Lux(t *testing.T) { @@ -68,13 +68,13 @@ func TestBH1750Lux(t *testing.T) { } lux, _ := d.Lux() - gobottest.Assert(t, lux, 1213) + assert.Equal(t, 1213, lux) } func TestBH1750NullRawSensorData(t *testing.T) { d, _ := initTestBH1750DriverWithStubbedAdaptor() level, _ := d.RawSensorData() - gobottest.Assert(t, level, 0) + assert.Equal(t, 0, level) } func TestBH1750RawSensorData(t *testing.T) { @@ -87,7 +87,7 @@ func TestBH1750RawSensorData(t *testing.T) { } level, _ := d.RawSensorData() - gobottest.Assert(t, level, 1456) + assert.Equal(t, 1456, level) } func TestBH1750LuxError(t *testing.T) { @@ -97,7 +97,7 @@ func TestBH1750LuxError(t *testing.T) { } _, err := d.Lux() - gobottest.Assert(t, err, errors.New("wrong number of bytes read")) + assert.Errorf(t, err, "wrong number of bytes read") } func TestBH1750RawSensorDataError(t *testing.T) { @@ -107,5 +107,5 @@ func TestBH1750RawSensorDataError(t *testing.T) { } _, err := d.RawSensorData() - gobottest.Assert(t, err, errors.New("wrong number of bytes read")) + assert.Errorf(t, err, "wrong number of bytes read") } diff --git a/drivers/i2c/blinkm_driver_test.go b/drivers/i2c/blinkm_driver_test.go index 2093b2b3f..519931a25 100644 --- a/drivers/i2c/blinkm_driver_test.go +++ b/drivers/i2c/blinkm_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -28,26 +28,26 @@ func TestNewBlinkMDriver(t *testing.T) { if !ok { t.Errorf("NewBlinkMDriver() should have returned a *BlinkMDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "BlinkM"), true) - gobottest.Assert(t, d.defaultAddress, 0x09) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "BlinkM")) + assert.Equal(t, 0x09, d.defaultAddress) } func TestBlinkMOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewBlinkMDriver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestBlinkMStart(t *testing.T) { d := NewBlinkMDriver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestBlinkMHalt(t *testing.T) { d, _ := initTestBlinkMDriverWithStubbedAdaptor() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } // Commands @@ -55,14 +55,14 @@ func TestNewBlinkMDriverCommands_Rgb(t *testing.T) { d, _ := initTestBlinkMDriverWithStubbedAdaptor() result := d.Command("Rgb")(rgb) - gobottest.Assert(t, result, nil) + assert.Nil(t, result) } func TestNewBlinkMDriverCommands_Fade(t *testing.T) { d, _ := initTestBlinkMDriverWithStubbedAdaptor() result := d.Command("Fade")(rgb) - gobottest.Assert(t, result, nil) + assert.Nil(t, result) } func TestNewBlinkMDriverCommands_FirmwareVersion(t *testing.T) { @@ -77,7 +77,7 @@ func TestNewBlinkMDriverCommands_FirmwareVersion(t *testing.T) { result := d.Command("FirmwareVersion")(param) version, _ := d.FirmwareVersion() - gobottest.Assert(t, result.(map[string]interface{})["version"].(string), version) + assert.Equal(t, version, result.(map[string]interface{})["version"].(string)) // When len(data) is not 2 a.i2cReadImpl = func(b []byte) (int, error) { @@ -87,7 +87,7 @@ func TestNewBlinkMDriverCommands_FirmwareVersion(t *testing.T) { result = d.Command("FirmwareVersion")(param) version, _ = d.FirmwareVersion() - gobottest.Assert(t, result.(map[string]interface{})["version"].(string), version) + assert.Equal(t, version, result.(map[string]interface{})["version"].(string)) } func TestNewBlinkMDriverCommands_Color(t *testing.T) { @@ -97,7 +97,7 @@ func TestNewBlinkMDriverCommands_Color(t *testing.T) { result := d.Command("Color")(param) color, _ := d.Color() - gobottest.Assert(t, result.(map[string]interface{})["color"].([]byte), color) + assert.Equal(t, color, result.(map[string]interface{})["color"].([]byte)) } func TestBlinkMFirmwareVersion(t *testing.T) { @@ -109,7 +109,7 @@ func TestBlinkMFirmwareVersion(t *testing.T) { } version, _ := d.FirmwareVersion() - gobottest.Assert(t, version, "99.1") + assert.Equal(t, "99.1", version) // when len(data) is not 2 a.i2cReadImpl = func(b []byte) (int, error) { @@ -118,14 +118,14 @@ func TestBlinkMFirmwareVersion(t *testing.T) { } version, _ = d.FirmwareVersion() - gobottest.Assert(t, version, "") + assert.Equal(t, "", version) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } _, err := d.FirmwareVersion() - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } func TestBlinkMColor(t *testing.T) { @@ -137,7 +137,7 @@ func TestBlinkMColor(t *testing.T) { } color, _ := d.Color() - gobottest.Assert(t, color, []byte{99, 1, 2}) + assert.Equal(t, []byte{99, 1, 2}, color) // when len(data) is not 3 a.i2cReadImpl = func(b []byte) (int, error) { @@ -146,14 +146,14 @@ func TestBlinkMColor(t *testing.T) { } color, _ = d.Color() - gobottest.Assert(t, color, []byte{}) + assert.Equal(t, []byte{}, color) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } _, err := d.Color() - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } @@ -164,7 +164,7 @@ func TestBlinkMFade(t *testing.T) { } err := d.Fade(100, 100, 100) - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } @@ -175,6 +175,6 @@ func TestBlinkMRGB(t *testing.T) { } err := d.Rgb(100, 100, 100) - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } diff --git a/drivers/i2c/bme280_driver_test.go b/drivers/i2c/bme280_driver_test.go index 80635ac87..9ffc61313 100644 --- a/drivers/i2c/bme280_driver_test.go +++ b/drivers/i2c/bme280_driver_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -25,15 +25,15 @@ func TestNewBME280Driver(t *testing.T) { if !ok { t.Errorf("NewBME280Driver() should have returned a *BME280Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "BMP280"), true) - gobottest.Assert(t, d.defaultAddress, 0x77) - gobottest.Assert(t, d.ctrlPwrMode, uint8(0x03)) - gobottest.Assert(t, d.ctrlPressOversamp, BMP280PressureOversampling(0x05)) - gobottest.Assert(t, d.ctrlTempOversamp, BMP280TemperatureOversampling(0x01)) - gobottest.Assert(t, d.ctrlHumOversamp, BME280HumidityOversampling(0x05)) - gobottest.Assert(t, d.confFilter, BMP280IIRFilter(0x00)) - gobottest.Refute(t, d.calCoeffs, nil) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "BMP280")) + assert.Equal(t, 0x77, d.defaultAddress) + assert.Equal(t, uint8(0x03), d.ctrlPwrMode) + assert.Equal(t, BMP280PressureOversampling(0x05), d.ctrlPressOversamp) + assert.Equal(t, BMP280TemperatureOversampling(0x01), d.ctrlTempOversamp) + assert.Equal(t, BME280HumidityOversampling(0x05), d.ctrlHumOversamp) + assert.Equal(t, BMP280IIRFilter(0x00), d.confFilter) + assert.NotNil(t, d.calCoeffs) } func TestBME280Options(t *testing.T) { @@ -44,11 +44,11 @@ func TestBME280Options(t *testing.T) { WithBME280TemperatureOversampling(0x02), WithBME280IIRFilter(0x03), WithBME280HumidityOversampling(0x04)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.ctrlPressOversamp, BMP280PressureOversampling(0x01)) - gobottest.Assert(t, d.ctrlTempOversamp, BMP280TemperatureOversampling(0x02)) - gobottest.Assert(t, d.confFilter, BMP280IIRFilter(0x03)) - gobottest.Assert(t, d.ctrlHumOversamp, BME280HumidityOversampling(0x04)) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, BMP280PressureOversampling(0x01), d.ctrlPressOversamp) + assert.Equal(t, BMP280TemperatureOversampling(0x02), d.ctrlTempOversamp) + assert.Equal(t, BMP280IIRFilter(0x03), d.confFilter) + assert.Equal(t, BME280HumidityOversampling(0x04), d.ctrlHumOversamp) } func TestBME280Measurements(t *testing.T) { @@ -72,8 +72,8 @@ func TestBME280Measurements(t *testing.T) { } _ = bme280.Start() hum, err := bme280.Humidity() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, hum, float32(51.20179)) + assert.Nil(t, err) + assert.Equal(t, float32(51.20179), hum) } func TestBME280InitH1Error(t *testing.T) { @@ -92,7 +92,7 @@ func TestBME280InitH1Error(t *testing.T) { return buf.Len(), nil } - gobottest.Assert(t, bme280.Start(), errors.New("h1 read error")) + assert.Errorf(t, bme280.Start(), "h1 read error") } func TestBME280InitH2Error(t *testing.T) { @@ -111,7 +111,7 @@ func TestBME280InitH2Error(t *testing.T) { return buf.Len(), nil } - gobottest.Assert(t, bme280.Start(), errors.New("h2 read error")) + assert.Errorf(t, bme280.Start(), "h2 read error") } func TestBME280HumidityWriteError(t *testing.T) { @@ -122,8 +122,8 @@ func TestBME280HumidityWriteError(t *testing.T) { return 0, errors.New("write error") } hum, err := bme280.Humidity() - gobottest.Assert(t, err, errors.New("write error")) - gobottest.Assert(t, hum, float32(0.0)) + assert.Errorf(t, err, "write error") + assert.Equal(t, float32(0.0), hum) } func TestBME280HumidityReadError(t *testing.T) { @@ -134,8 +134,8 @@ func TestBME280HumidityReadError(t *testing.T) { return 0, errors.New("read error") } hum, err := bme280.Humidity() - gobottest.Assert(t, err, errors.New("read error")) - gobottest.Assert(t, hum, float32(0.0)) + assert.Errorf(t, err, "read error") + assert.Equal(t, float32(0.0), hum) } func TestBME280HumidityNotEnabled(t *testing.T) { @@ -159,8 +159,8 @@ func TestBME280HumidityNotEnabled(t *testing.T) { } _ = bme280.Start() hum, err := bme280.Humidity() - gobottest.Assert(t, err, errors.New("Humidity disabled")) - gobottest.Assert(t, hum, float32(0.0)) + assert.Errorf(t, err, "Humidity disabled") + assert.Equal(t, float32(0.0), hum) } func TestBME280_initializationBME280(t *testing.T) { @@ -186,5 +186,5 @@ func TestBME280_initializationBME280(t *testing.T) { } return 0, nil } - gobottest.Assert(t, bme280.Start(), nil) + assert.Nil(t, bme280.Start()) } diff --git a/drivers/i2c/bmp180_driver_test.go b/drivers/i2c/bmp180_driver_test.go index 87dfcfca6..35056977b 100644 --- a/drivers/i2c/bmp180_driver_test.go +++ b/drivers/i2c/bmp180_driver_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -28,19 +28,19 @@ func TestNewBMP180Driver(t *testing.T) { if !ok { t.Errorf("NewBMP180Driver() should have returned a *BMP180Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "BMP180"), true) - gobottest.Assert(t, d.defaultAddress, 0x77) - gobottest.Assert(t, d.oversampling, BMP180OversamplingMode(0x00)) - gobottest.Refute(t, d.calCoeffs, nil) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "BMP180")) + assert.Equal(t, 0x77, d.defaultAddress) + assert.Equal(t, BMP180OversamplingMode(0x00), d.oversampling) + assert.NotNil(t, d.calCoeffs) } func TestBMP180Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewBMP180Driver(newI2cTestAdaptor(), WithBus(2), WithBMP180OversamplingMode(0x01)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.oversampling, BMP180OversamplingMode(0x01)) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, BMP180OversamplingMode(0x01), d.oversampling) } func TestBMP180Measurements(t *testing.T) { @@ -72,11 +72,11 @@ func TestBMP180Measurements(t *testing.T) { } _ = bmp180.Start() temp, err := bmp180.Temperature() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, temp, float32(15.0)) + assert.Nil(t, err) + assert.Equal(t, float32(15.0), temp) pressure, err := bmp180.Pressure() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, pressure, float32(69964)) + assert.Nil(t, err) + assert.Equal(t, float32(69964), pressure) } func TestBMP180TemperatureError(t *testing.T) { @@ -108,7 +108,7 @@ func TestBMP180TemperatureError(t *testing.T) { } _ = bmp180.Start() _, err := bmp180.Temperature() - gobottest.Assert(t, err, errors.New("temp error")) + assert.Errorf(t, err, "temp error") } func TestBMP180PressureError(t *testing.T) { @@ -138,7 +138,7 @@ func TestBMP180PressureError(t *testing.T) { } _ = bmp180.Start() _, err := bmp180.Pressure() - gobottest.Assert(t, err, errors.New("press error")) + assert.Errorf(t, err, "press error") } func TestBMP180PressureWriteError(t *testing.T) { @@ -150,7 +150,7 @@ func TestBMP180PressureWriteError(t *testing.T) { } _, err := bmp180.Pressure() - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } func TestBMP180_initialization(t *testing.T) { @@ -183,26 +183,26 @@ func TestBMP180_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(0xAA)) - gobottest.Assert(t, d.calCoeffs.ac1, int16(408)) - gobottest.Assert(t, d.calCoeffs.ac2, int16(-72)) - gobottest.Assert(t, d.calCoeffs.ac3, int16(-14383)) - gobottest.Assert(t, d.calCoeffs.ac4, uint16(32741)) - gobottest.Assert(t, d.calCoeffs.ac5, uint16(32757)) - gobottest.Assert(t, d.calCoeffs.ac6, uint16(23153)) - gobottest.Assert(t, d.calCoeffs.b1, int16(6190)) - gobottest.Assert(t, d.calCoeffs.b2, int16(4)) - gobottest.Assert(t, d.calCoeffs.mb, int16(-32768)) - gobottest.Assert(t, d.calCoeffs.mc, int16(-8711)) - gobottest.Assert(t, d.calCoeffs.md, int16(2868)) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(0xAA), a.written[0]) + assert.Equal(t, int16(408), d.calCoeffs.ac1) + assert.Equal(t, int16(-72), d.calCoeffs.ac2) + assert.Equal(t, int16(-14383), d.calCoeffs.ac3) + assert.Equal(t, uint16(32741), d.calCoeffs.ac4) + assert.Equal(t, uint16(32757), d.calCoeffs.ac5) + assert.Equal(t, uint16(23153), d.calCoeffs.ac6) + assert.Equal(t, int16(6190), d.calCoeffs.b1) + assert.Equal(t, int16(4), d.calCoeffs.b2) + assert.Equal(t, int16(-32768), d.calCoeffs.mb) + assert.Equal(t, int16(-8711), d.calCoeffs.mc) + assert.Equal(t, int16(2868), d.calCoeffs.md) } func TestBMP180_bmp180PauseForReading(t *testing.T) { - gobottest.Assert(t, bmp180PauseForReading(BMP180UltraLowPower), time.Duration(5*time.Millisecond)) - gobottest.Assert(t, bmp180PauseForReading(BMP180Standard), time.Duration(8*time.Millisecond)) - gobottest.Assert(t, bmp180PauseForReading(BMP180HighResolution), time.Duration(14*time.Millisecond)) - gobottest.Assert(t, bmp180PauseForReading(BMP180UltraHighResolution), time.Duration(26*time.Millisecond)) + assert.Equal(t, time.Duration(5*time.Millisecond), bmp180PauseForReading(BMP180UltraLowPower)) + assert.Equal(t, time.Duration(8*time.Millisecond), bmp180PauseForReading(BMP180Standard)) + assert.Equal(t, time.Duration(14*time.Millisecond), bmp180PauseForReading(BMP180HighResolution)) + assert.Equal(t, time.Duration(26*time.Millisecond), bmp180PauseForReading(BMP180UltraHighResolution)) } diff --git a/drivers/i2c/bmp280_driver_test.go b/drivers/i2c/bmp280_driver_test.go index bbbe13c8c..6f769e09f 100644 --- a/drivers/i2c/bmp280_driver_test.go +++ b/drivers/i2c/bmp280_driver_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -25,22 +25,22 @@ func TestNewBMP280Driver(t *testing.T) { if !ok { t.Errorf("NewBMP280Driver() should have returned a *BMP280Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "BMP280"), true) - gobottest.Assert(t, d.defaultAddress, 0x77) - gobottest.Assert(t, d.ctrlPwrMode, uint8(0x03)) - gobottest.Assert(t, d.ctrlPressOversamp, BMP280PressureOversampling(0x05)) - gobottest.Assert(t, d.ctrlTempOversamp, BMP280TemperatureOversampling(0x01)) - gobottest.Assert(t, d.confFilter, BMP280IIRFilter(0x00)) - gobottest.Refute(t, d.calCoeffs, nil) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "BMP280")) + assert.Equal(t, 0x77, d.defaultAddress) + assert.Equal(t, uint8(0x03), d.ctrlPwrMode) + assert.Equal(t, BMP280PressureOversampling(0x05), d.ctrlPressOversamp) + assert.Equal(t, BMP280TemperatureOversampling(0x01), d.ctrlTempOversamp) + assert.Equal(t, BMP280IIRFilter(0x00), d.confFilter) + assert.NotNil(t, d.calCoeffs) } func TestBMP280Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewBMP280Driver(newI2cTestAdaptor(), WithBus(2), WithBMP280PressureOversampling(0x04)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.ctrlPressOversamp, BMP280PressureOversampling(0x04)) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, BMP280PressureOversampling(0x04), d.ctrlPressOversamp) } func TestWithBMP280TemperatureOversampling(t *testing.T) { @@ -53,8 +53,8 @@ func TestWithBMP280TemperatureOversampling(t *testing.T) { // act WithBMP280TemperatureOversampling(setVal)(d) // assert - gobottest.Assert(t, d.ctrlTempOversamp, setVal) - gobottest.Assert(t, len(a.written), 0) + assert.Equal(t, setVal, d.ctrlTempOversamp) + assert.Equal(t, 0, len(a.written)) } func TestWithBMP280IIRFilter(t *testing.T) { @@ -67,8 +67,8 @@ func TestWithBMP280IIRFilter(t *testing.T) { // act WithBMP280IIRFilter(setVal)(d) // assert - gobottest.Assert(t, d.confFilter, setVal) - gobottest.Assert(t, len(a.written), 0) + assert.Equal(t, setVal, d.confFilter) + assert.Equal(t, 0, len(a.written)) } func TestBMP280Measurements(t *testing.T) { @@ -88,14 +88,14 @@ func TestBMP280Measurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, temp, float32(25.014637)) + assert.Nil(t, err) + assert.Equal(t, float32(25.014637), temp) pressure, err := d.Pressure() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, pressure, float32(99545.414)) + assert.Nil(t, err) + assert.Equal(t, float32(99545.414), pressure) alt, err := d.Altitude() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, alt, float32(149.22713)) + assert.Nil(t, err) + assert.Equal(t, float32(149.22713), alt) } func TestBMP280TemperatureWriteError(t *testing.T) { @@ -106,8 +106,8 @@ func TestBMP280TemperatureWriteError(t *testing.T) { return 0, errors.New("write error") } temp, err := d.Temperature() - gobottest.Assert(t, err, errors.New("write error")) - gobottest.Assert(t, temp, float32(0.0)) + assert.Errorf(t, err, "write error") + assert.Equal(t, float32(0.0), temp) } func TestBMP280TemperatureReadError(t *testing.T) { @@ -118,8 +118,8 @@ func TestBMP280TemperatureReadError(t *testing.T) { return 0, errors.New("read error") } temp, err := d.Temperature() - gobottest.Assert(t, err, errors.New("read error")) - gobottest.Assert(t, temp, float32(0.0)) + assert.Errorf(t, err, "read error") + assert.Equal(t, float32(0.0), temp) } func TestBMP280PressureWriteError(t *testing.T) { @@ -130,8 +130,8 @@ func TestBMP280PressureWriteError(t *testing.T) { return 0, errors.New("write error") } press, err := d.Pressure() - gobottest.Assert(t, err, errors.New("write error")) - gobottest.Assert(t, press, float32(0.0)) + assert.Errorf(t, err, "write error") + assert.Equal(t, float32(0.0), press) } func TestBMP280PressureReadError(t *testing.T) { @@ -142,8 +142,8 @@ func TestBMP280PressureReadError(t *testing.T) { return 0, errors.New("read error") } press, err := d.Pressure() - gobottest.Assert(t, err, errors.New("read error")) - gobottest.Assert(t, press, float32(0.0)) + assert.Errorf(t, err, "read error") + assert.Equal(t, float32(0.0), press) } func TestBMP280_initialization(t *testing.T) { @@ -188,24 +188,24 @@ func TestBMP280_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 5) - gobottest.Assert(t, a.written[0], wantCalibReg) - gobottest.Assert(t, a.written[1], wantCtrlReg) - gobottest.Assert(t, a.written[2], wantCtrlRegVal) - gobottest.Assert(t, a.written[3], wantConfReg) - gobottest.Assert(t, a.written[4], wantConfRegVal) - gobottest.Assert(t, d.calCoeffs.t1, uint16(27504)) - gobottest.Assert(t, d.calCoeffs.t2, int16(26435)) - gobottest.Assert(t, d.calCoeffs.t3, int16(-1000)) - gobottest.Assert(t, d.calCoeffs.p1, uint16(36477)) - gobottest.Assert(t, d.calCoeffs.p2, int16(-10685)) - gobottest.Assert(t, d.calCoeffs.p3, int16(3024)) - gobottest.Assert(t, d.calCoeffs.p4, int16(2855)) - gobottest.Assert(t, d.calCoeffs.p5, int16(140)) - gobottest.Assert(t, d.calCoeffs.p6, int16(-7)) - gobottest.Assert(t, d.calCoeffs.p7, int16(15500)) - gobottest.Assert(t, d.calCoeffs.p8, int16(-14600)) - gobottest.Assert(t, d.calCoeffs.p9, int16(6000)) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 5, len(a.written)) + assert.Equal(t, wantCalibReg, a.written[0]) + assert.Equal(t, wantCtrlReg, a.written[1]) + assert.Equal(t, wantCtrlRegVal, a.written[2]) + assert.Equal(t, wantConfReg, a.written[3]) + assert.Equal(t, wantConfRegVal, a.written[4]) + assert.Equal(t, uint16(27504), d.calCoeffs.t1) + assert.Equal(t, int16(26435), d.calCoeffs.t2) + assert.Equal(t, int16(-1000), d.calCoeffs.t3) + assert.Equal(t, uint16(36477), d.calCoeffs.p1) + assert.Equal(t, int16(-10685), d.calCoeffs.p2) + assert.Equal(t, int16(3024), d.calCoeffs.p3) + assert.Equal(t, int16(2855), d.calCoeffs.p4) + assert.Equal(t, int16(140), d.calCoeffs.p5) + assert.Equal(t, int16(-7), d.calCoeffs.p6) + assert.Equal(t, int16(15500), d.calCoeffs.p7) + assert.Equal(t, int16(-14600), d.calCoeffs.p8) + assert.Equal(t, int16(6000), d.calCoeffs.p9) } diff --git a/drivers/i2c/bmp388_driver_test.go b/drivers/i2c/bmp388_driver_test.go index fb0ce1b59..7f54414f5 100644 --- a/drivers/i2c/bmp388_driver_test.go +++ b/drivers/i2c/bmp388_driver_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -44,20 +44,20 @@ func TestNewBMP388Driver(t *testing.T) { if !ok { t.Errorf("NewBMP388Driver() should have returned a *BMP388Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "BMP388"), true) - gobottest.Assert(t, d.defaultAddress, 0x77) - gobottest.Assert(t, d.ctrlPwrMode, uint8(0x01)) // forced mode - gobottest.Assert(t, d.confFilter, BMP388IIRFilter(0x00)) // filter off - gobottest.Refute(t, d.calCoeffs, nil) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "BMP388")) + assert.Equal(t, 0x77, d.defaultAddress) + assert.Equal(t, uint8(0x01), d.ctrlPwrMode) // forced mode + assert.Equal(t, BMP388IIRFilter(0x00), d.confFilter) // filter off + assert.NotNil(t, d.calCoeffs) } func TestBMP388Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewBMP388Driver(newI2cTestAdaptor(), WithBus(2), WithBMP388IIRFilter(BMP388IIRFilter(0x03))) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.confFilter, BMP388IIRFilter(0x03)) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, BMP388IIRFilter(0x03), d.confFilter) } func TestBMP388Measurements(t *testing.T) { @@ -84,14 +84,14 @@ func TestBMP388Measurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature(2) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, temp, float32(22.906143)) + assert.Nil(t, err) + assert.Equal(t, float32(22.906143), temp) pressure, err := d.Pressure(2) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, pressure, float32(98874.85)) + assert.Nil(t, err) + assert.Equal(t, float32(98874.85), pressure) alt, err := d.Altitude(2) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, alt, float32(205.89395)) + assert.Nil(t, err) + assert.Equal(t, float32(205.89395), alt) } func TestBMP388TemperatureWriteError(t *testing.T) { @@ -102,8 +102,8 @@ func TestBMP388TemperatureWriteError(t *testing.T) { return 0, errors.New("write error") } temp, err := d.Temperature(2) - gobottest.Assert(t, err, errors.New("write error")) - gobottest.Assert(t, temp, float32(0.0)) + assert.Errorf(t, err, "write error") + assert.Equal(t, float32(0.0), temp) } func TestBMP388TemperatureReadError(t *testing.T) { @@ -114,8 +114,8 @@ func TestBMP388TemperatureReadError(t *testing.T) { return 0, errors.New("read error") } temp, err := d.Temperature(2) - gobottest.Assert(t, err, errors.New("read error")) - gobottest.Assert(t, temp, float32(0.0)) + assert.Errorf(t, err, "read error") + assert.Equal(t, float32(0.0), temp) } func TestBMP388PressureWriteError(t *testing.T) { @@ -126,8 +126,8 @@ func TestBMP388PressureWriteError(t *testing.T) { return 0, errors.New("write error") } press, err := d.Pressure(2) - gobottest.Assert(t, err, errors.New("write error")) - gobottest.Assert(t, press, float32(0.0)) + assert.Errorf(t, err, "write error") + assert.Equal(t, float32(0.0), press) } func TestBMP388PressureReadError(t *testing.T) { @@ -138,8 +138,8 @@ func TestBMP388PressureReadError(t *testing.T) { return 0, errors.New("read error") } press, err := d.Pressure(2) - gobottest.Assert(t, err, errors.New("read error")) - gobottest.Assert(t, press, float32(0.0)) + assert.Errorf(t, err, "read error") + assert.Equal(t, float32(0.0), press) } func TestBMP388_initialization(t *testing.T) { @@ -176,25 +176,25 @@ func TestBMP388_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, len(a.written), 6) - gobottest.Assert(t, a.written[0], wantChipIDReg) - gobottest.Assert(t, a.written[1], wantCalibReg) - gobottest.Assert(t, a.written[2], wantCommandReg) - gobottest.Assert(t, a.written[3], wantCommandRegVal) - gobottest.Assert(t, a.written[4], wantConfReg) - gobottest.Assert(t, a.written[5], wantConfRegVal) - gobottest.Assert(t, d.calCoeffs.t1, float32(7.021568e+06)) - gobottest.Assert(t, d.calCoeffs.t2, float32(1.7549843e-05)) - gobottest.Assert(t, d.calCoeffs.t3, float32(-3.5527137e-14)) - gobottest.Assert(t, d.calCoeffs.p1, float32(-0.015769958)) - gobottest.Assert(t, d.calCoeffs.p2, float32(-3.5410747e-05)) - gobottest.Assert(t, d.calCoeffs.p3, float32(8.1490725e-09)) - gobottest.Assert(t, d.calCoeffs.p4, float32(0)) - gobottest.Assert(t, d.calCoeffs.p5, float32(208056)) - gobottest.Assert(t, d.calCoeffs.p6, float32(490.875)) - gobottest.Assert(t, d.calCoeffs.p7, float32(-0.05078125)) - gobottest.Assert(t, d.calCoeffs.p8, float32(-0.00030517578)) - gobottest.Assert(t, d.calCoeffs.p9, float32(5.8957283e-11)) + assert.Nil(t, err) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, 6, len(a.written)) + assert.Equal(t, wantChipIDReg, a.written[0]) + assert.Equal(t, wantCalibReg, a.written[1]) + assert.Equal(t, wantCommandReg, a.written[2]) + assert.Equal(t, wantCommandRegVal, a.written[3]) + assert.Equal(t, wantConfReg, a.written[4]) + assert.Equal(t, wantConfRegVal, a.written[5]) + assert.Equal(t, float32(7.021568e+06), d.calCoeffs.t1) + assert.Equal(t, float32(1.7549843e-05), d.calCoeffs.t2) + assert.Equal(t, float32(-3.5527137e-14), d.calCoeffs.t3) + assert.Equal(t, float32(-0.015769958), d.calCoeffs.p1) + assert.Equal(t, float32(-3.5410747e-05), d.calCoeffs.p2) + assert.Equal(t, float32(8.1490725e-09), d.calCoeffs.p3) + assert.Equal(t, float32(0), d.calCoeffs.p4) + assert.Equal(t, float32(208056), d.calCoeffs.p5) + assert.Equal(t, float32(490.875), d.calCoeffs.p6) + assert.Equal(t, float32(-0.05078125), d.calCoeffs.p7) + assert.Equal(t, float32(-0.00030517578), d.calCoeffs.p8) + assert.Equal(t, float32(5.8957283e-11), d.calCoeffs.p9) } diff --git a/drivers/i2c/ccs811_driver_test.go b/drivers/i2c/ccs811_driver_test.go index 56f01cfe6..956821443 100644 --- a/drivers/i2c/ccs811_driver_test.go +++ b/drivers/i2c/ccs811_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -24,25 +24,25 @@ func TestNewCCS811Driver(t *testing.T) { if !ok { t.Errorf("NewCCS811Driver() should have returned a *CCS811Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "CCS811"), true) - gobottest.Assert(t, d.defaultAddress, 0x5A) - gobottest.Refute(t, d.measMode, nil) - gobottest.Assert(t, d.ntcResistanceValue, uint32(100000)) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "CCS811")) + assert.Equal(t, 0x5A, d.defaultAddress) + assert.NotNil(t, d.measMode) + assert.Equal(t, uint32(100000), d.ntcResistanceValue) } func TestCCS811Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewCCS811Driver(newI2cTestAdaptor(), WithBus(2), WithAddress(0xFF), WithCCS811NTCResistance(0xFF)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.GetAddressOrDefault(0x5a), 0xFF) - gobottest.Assert(t, d.ntcResistanceValue, uint32(0xFF)) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, 0xFF, d.GetAddressOrDefault(0x5a)) + assert.Equal(t, uint32(0xFF), d.ntcResistanceValue) } func TestCCS811WithCCS811MeasMode(t *testing.T) { d := NewCCS811Driver(newI2cTestAdaptor(), WithCCS811MeasMode(CCS811DriveMode10Sec)) - gobottest.Assert(t, d.measMode.driveMode, CCS811DriveMode(CCS811DriveMode10Sec)) + assert.Equal(t, CCS811DriveMode(CCS811DriveMode10Sec), d.measMode.driveMode) } func TestCCS811GetGasData(t *testing.T) { @@ -91,9 +91,9 @@ func TestCCS811GetGasData(t *testing.T) { // act eco2, tvoc, err := d.GetGasData() // assert - gobottest.Assert(t, eco2, tc.eco2) - gobottest.Assert(t, tvoc, tc.tvoc) - gobottest.Assert(t, err, tc.err) + assert.Equal(t, tc.eco2, eco2) + assert.Equal(t, tc.tvoc, tvoc) + assert.Equal(t, tc.err, err) }) } } @@ -148,8 +148,8 @@ func TestCCS811GetTemperature(t *testing.T) { // act temp, err := d.GetTemperature() // assert - gobottest.Assert(t, temp, tc.temp) - gobottest.Assert(t, err, tc.err) + assert.Equal(t, tc.temp, temp) + assert.Equal(t, tc.err, err) }) } } @@ -212,8 +212,8 @@ func TestCCS811HasData(t *testing.T) { // act result, err := d.HasData() // assert - gobottest.Assert(t, result, tc.result) - gobottest.Assert(t, err, tc.err) + assert.Equal(t, tc.result, result) + assert.Equal(t, tc.err, err) }) } } @@ -255,13 +255,13 @@ func TestCCS811_initialize(t *testing.T) { // arrange, act - initialize() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 9) - gobottest.Assert(t, a.written[0], wantChipIDReg) - gobottest.Assert(t, a.written[1], wantResetReg) - gobottest.Assert(t, a.written[2:6], wantResetRegSequence) - gobottest.Assert(t, a.written[6], wantAppStartReg) - gobottest.Assert(t, a.written[7], wantMeasReg) - gobottest.Assert(t, a.written[8], wantMeasRegVal) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 9, len(a.written)) + assert.Equal(t, wantChipIDReg, a.written[0]) + assert.Equal(t, wantResetReg, a.written[1]) + assert.Equal(t, wantResetRegSequence, a.written[2:6]) + assert.Equal(t, wantAppStartReg, a.written[6]) + assert.Equal(t, wantMeasReg, a.written[7]) + assert.Equal(t, wantMeasRegVal, a.written[8]) } diff --git a/drivers/i2c/drv2605l_driver_test.go b/drivers/i2c/drv2605l_driver_test.go index 7fd988847..125a0f9c5 100644 --- a/drivers/i2c/drv2605l_driver_test.go +++ b/drivers/i2c/drv2605l_driver_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -37,21 +37,21 @@ func TestNewDRV2605LDriver(t *testing.T) { if !ok { t.Errorf("NewDRV2605LDriver() should have returned a *DRV2605LDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "DRV2605L"), true) - gobottest.Assert(t, d.defaultAddress, 0x5a) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "DRV2605L")) + assert.Equal(t, 0x5a, d.defaultAddress) } func TestDRV2605LOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewDRV2605LDriver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestDRV2605LStart(t *testing.T) { d := NewDRV2605LDriver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestDRV2605LHalt(t *testing.T) { @@ -62,33 +62,33 @@ func TestDRV2605LHalt(t *testing.T) { writeNewStandbyModeData := []byte{drv2605RegMode, 42 | drv2605Standby} d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - gobottest.Assert(t, d.Halt(), nil) - gobottest.Assert(t, a.written, append(append(writeStopPlaybackData, readCurrentStandbyModeData), writeNewStandbyModeData...)) + assert.Nil(t, d.Halt()) + assert.Equal(t, append(append(writeStopPlaybackData, readCurrentStandbyModeData), writeNewStandbyModeData...), a.written) } func TestDRV2605LGetPause(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - gobottest.Assert(t, d.GetPauseWaveform(0), uint8(0x80)) - gobottest.Assert(t, d.GetPauseWaveform(1), uint8(0x81)) - gobottest.Assert(t, d.GetPauseWaveform(128), d.GetPauseWaveform(127)) + assert.Equal(t, uint8(0x80), d.GetPauseWaveform(0)) + assert.Equal(t, uint8(0x81), d.GetPauseWaveform(1)) + assert.Equal(t, d.GetPauseWaveform(127), d.GetPauseWaveform(128)) } func TestDRV2605LSequenceTermination(t *testing.T) { d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - gobottest.Assert(t, d.SetSequence([]byte{1, 2}), nil) - gobottest.Assert(t, a.written, []byte{ + assert.Nil(t, d.SetSequence([]byte{1, 2})) + assert.Equal(t, []byte{ drv2605RegWaveSeq1, 1, drv2605RegWaveSeq2, 2, drv2605RegWaveSeq3, 0, - }) + }, a.written) } func TestDRV2605LSequenceTruncation(t *testing.T) { d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - gobottest.Assert(t, d.SetSequence([]byte{1, 2, 3, 4, 5, 6, 7, 8, 99, 100}), nil) - gobottest.Assert(t, a.written, []byte{ + assert.Nil(t, d.SetSequence([]byte{1, 2, 3, 4, 5, 6, 7, 8, 99, 100})) + assert.Equal(t, []byte{ drv2605RegWaveSeq1, 1, drv2605RegWaveSeq2, 2, drv2605RegWaveSeq3, 3, @@ -97,12 +97,12 @@ func TestDRV2605LSequenceTruncation(t *testing.T) { drv2605RegWaveSeq6, 6, drv2605RegWaveSeq7, 7, drv2605RegWaveSeq8, 8, - }) + }, a.written) } func TestDRV2605LSetMode(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - gobottest.Assert(t, d.SetMode(DRV2605ModeIntTrig), nil) + assert.Nil(t, d.SetMode(DRV2605ModeIntTrig)) } func TestDRV2605LSetModeReadError(t *testing.T) { @@ -110,12 +110,12 @@ func TestDRV2605LSetModeReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - gobottest.Assert(t, d.SetMode(DRV2605ModeIntTrig), errors.New("read error")) + assert.Errorf(t, d.SetMode(DRV2605ModeIntTrig), "read error") } func TestDRV2605LSetStandbyMode(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - gobottest.Assert(t, d.SetStandbyMode(true), nil) + assert.Nil(t, d.SetStandbyMode(true)) } func TestDRV2605LSetStandbyModeReadError(t *testing.T) { @@ -123,15 +123,15 @@ func TestDRV2605LSetStandbyModeReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - gobottest.Assert(t, d.SetStandbyMode(true), errors.New("read error")) + assert.Errorf(t, d.SetStandbyMode(true), "read error") } func TestDRV2605LSelectLibrary(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - gobottest.Assert(t, d.SelectLibrary(1), nil) + assert.Nil(t, d.SelectLibrary(1)) } func TestDRV2605LGo(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - gobottest.Assert(t, d.Go(), nil) + assert.Nil(t, d.Go()) } diff --git a/drivers/i2c/generic_driver_test.go b/drivers/i2c/generic_driver_test.go index 44d6d94d6..fdb490e69 100644 --- a/drivers/i2c/generic_driver_test.go +++ b/drivers/i2c/generic_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*GenericDriver)(nil) @@ -20,6 +20,6 @@ func TestNewGenericDriver(t *testing.T) { if !ok { t.Errorf("NewGenericDriver() should have returned a *GenericDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "GenericI2C"), true) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "GenericI2C")) } diff --git a/drivers/i2c/grove_drivers_test.go b/drivers/i2c/grove_drivers_test.go index 2d94f7711..eff163972 100644 --- a/drivers/i2c/grove_drivers_test.go +++ b/drivers/i2c/grove_drivers_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*GroveLcdDriver)(nil) @@ -33,24 +33,24 @@ func initGroveAccelerometerDriverWithStubbedAdaptor() (*GroveAccelerometerDriver func TestGroveLcdDriverName(t *testing.T) { g := initTestGroveLcdDriver() - gobottest.Refute(t, g.Connection(), nil) - gobottest.Assert(t, strings.HasPrefix(g.Name(), "JHD1313M1"), true) + assert.NotNil(t, g.Connection()) + assert.True(t, strings.HasPrefix(g.Name(), "JHD1313M1")) } func TestLcdDriverWithAddress(t *testing.T) { adaptor := newI2cTestAdaptor() g := NewGroveLcdDriver(adaptor, WithAddress(0x66)) - gobottest.Assert(t, g.GetAddressOrDefault(0x33), 0x66) + assert.Equal(t, 0x66, g.GetAddressOrDefault(0x33)) } func TestGroveAccelerometerDriverName(t *testing.T) { g := initTestGroveAccelerometerDriver() - gobottest.Refute(t, g.Connection(), nil) - gobottest.Assert(t, strings.HasPrefix(g.Name(), "MMA7660"), true) + assert.NotNil(t, g.Connection()) + assert.True(t, strings.HasPrefix(g.Name(), "MMA7660")) } func TestGroveAccelerometerDriverWithAddress(t *testing.T) { adaptor := newI2cTestAdaptor() g := NewGroveAccelerometerDriver(adaptor, WithAddress(0x66)) - gobottest.Assert(t, g.GetAddressOrDefault(0x33), 0x66) + assert.Equal(t, 0x66, g.GetAddressOrDefault(0x33)) } diff --git a/drivers/i2c/grovepi_driver_test.go b/drivers/i2c/grovepi_driver_test.go index dad364537..23b16db5f 100644 --- a/drivers/i2c/grovepi_driver_test.go +++ b/drivers/i2c/grovepi_driver_test.go @@ -5,10 +5,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -41,17 +41,17 @@ func TestNewGrovePiDriver(t *testing.T) { if !ok { t.Errorf("NewGrovePiDriver() should have returned a *GrovePiDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "GrovePi"), true) - gobottest.Assert(t, d.defaultAddress, 0x04) - gobottest.Refute(t, d.pins, nil) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "GrovePi")) + assert.Equal(t, 0x04, d.defaultAddress) + assert.NotNil(t, d.pins) } func TestGrovePiOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewGrovePiDriver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestGrovePiSomeRead(t *testing.T) { @@ -166,13 +166,13 @@ func TestGrovePiSomeRead(t *testing.T) { return } // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, a.written, tc.wantWritten) - gobottest.Assert(t, numCallsRead, len(tc.simResponse)) - gobottest.Assert(t, got, tc.wantResult) - gobottest.Assert(t, gotF1, tc.wantResultF1) - gobottest.Assert(t, gotF2, tc.wantResultF2) - gobottest.Assert(t, gotString, tc.wantResultString) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantWritten, a.written) + assert.Equal(t, len(tc.simResponse), numCallsRead) + assert.Equal(t, tc.wantResult, got) + assert.Equal(t, tc.wantResultF1, gotF1) + assert.Equal(t, tc.wantResultF2, gotF2) + assert.Equal(t, tc.wantResultString, gotString) }) } } @@ -219,16 +219,16 @@ func TestGrovePiSomeWrite(t *testing.T) { return } // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, a.written, tc.wantWritten) + assert.Nil(t, err) + assert.Equal(t, tc.wantWritten, a.written) }) } } func TestGrovePi_getPin(t *testing.T) { - gobottest.Assert(t, getPin("a1"), "1") - gobottest.Assert(t, getPin("A16"), "16") - gobottest.Assert(t, getPin("D3"), "3") - gobottest.Assert(t, getPin("d22"), "22") - gobottest.Assert(t, getPin("22"), "22") + assert.Equal(t, "1", getPin("a1")) + assert.Equal(t, "16", getPin("A16")) + assert.Equal(t, "3", getPin("D3")) + assert.Equal(t, "22", getPin("d22")) + assert.Equal(t, "22", getPin("22")) } diff --git a/drivers/i2c/hmc5883l_driver_test.go b/drivers/i2c/hmc5883l_driver_test.go index a7a88d9b0..c7b9b2dff 100644 --- a/drivers/i2c/hmc5883l_driver_test.go +++ b/drivers/i2c/hmc5883l_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -23,40 +23,40 @@ func TestNewHMC5883LDriver(t *testing.T) { if !ok { t.Errorf("NewHMC5883LDriver() should have returned a *HMC5883LDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.name, "HMC5883L"), true) - gobottest.Assert(t, d.defaultAddress, 0x1E) - gobottest.Assert(t, d.samplesAvg, uint8(8)) - gobottest.Assert(t, d.outputRate, uint32(15000)) - gobottest.Assert(t, d.applyBias, int8(0)) - gobottest.Assert(t, d.measurementMode, 0) - gobottest.Assert(t, d.gain, 390.0) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.name, "HMC5883L")) + assert.Equal(t, 0x1E, d.defaultAddress) + assert.Equal(t, uint8(8), d.samplesAvg) + assert.Equal(t, uint32(15000), d.outputRate) + assert.Equal(t, int8(0), d.applyBias) + assert.Equal(t, 0, d.measurementMode) + assert.Equal(t, 390.0, d.gain) } func TestHMC5883LOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewHMC5883LDriver(newI2cTestAdaptor(), WithBus(2), WithHMC5883LSamplesAveraged(4)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.samplesAvg, uint8(4)) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, uint8(4), d.samplesAvg) } func TestHMC5883LWithHMC5883LDataOutputRate(t *testing.T) { d := NewHMC5883LDriver(newI2cTestAdaptor()) WithHMC5883LDataOutputRate(7500)(d) - gobottest.Assert(t, d.outputRate, uint32(7500)) + assert.Equal(t, uint32(7500), d.outputRate) } func TestHMC5883LWithHMC5883LApplyBias(t *testing.T) { d := NewHMC5883LDriver(newI2cTestAdaptor()) WithHMC5883LApplyBias(-1)(d) - gobottest.Assert(t, d.applyBias, int8(-1)) + assert.Equal(t, int8(-1), d.applyBias) } func TestHMC5883LWithHMC5883LGain(t *testing.T) { d := NewHMC5883LDriver(newI2cTestAdaptor()) WithHMC5883LGain(230)(d) - gobottest.Assert(t, d.gain, 230.0) + assert.Equal(t, 230.0, d.gain) } func TestHMC5883LRead(t *testing.T) { @@ -121,10 +121,10 @@ func TestHMC5883LRead(t *testing.T) { // act gotX, gotY, gotZ, err := d.Read() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, gotX, tc.wantX) - gobottest.Assert(t, gotY, tc.wantY) - gobottest.Assert(t, gotZ, tc.wantZ) + assert.Nil(t, err) + assert.Equal(t, tc.wantX, gotX) + assert.Equal(t, tc.wantY, gotY) + assert.Equal(t, tc.wantZ, gotZ) }) } } @@ -177,13 +177,13 @@ func TestHMC5883L_readRawData(t *testing.T) { // act gotX, gotY, gotZ, err := d.readRawData() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, gotX, tc.wantX) - gobottest.Assert(t, gotY, tc.wantY) - gobottest.Assert(t, gotZ, tc.wantZ) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(hmc5883lAxisX)) + assert.Nil(t, err) + assert.Equal(t, tc.wantX, gotX) + assert.Equal(t, tc.wantY, gotY) + assert.Equal(t, tc.wantZ, gotZ) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(hmc5883lAxisX), a.written[0]) }) } } @@ -203,12 +203,12 @@ func TestHMC5883L_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 6) - gobottest.Assert(t, a.written[0], uint8(hmc5883lRegA)) - gobottest.Assert(t, a.written[1], wantRegA) - gobottest.Assert(t, a.written[2], uint8(hmc5883lRegB)) - gobottest.Assert(t, a.written[3], wantRegB) - gobottest.Assert(t, a.written[4], uint8(hmc5883lRegMode)) - gobottest.Assert(t, a.written[5], wantRegM) + assert.Nil(t, err) + assert.Equal(t, 6, len(a.written)) + assert.Equal(t, uint8(hmc5883lRegA), a.written[0]) + assert.Equal(t, wantRegA, a.written[1]) + assert.Equal(t, uint8(hmc5883lRegB), a.written[2]) + assert.Equal(t, wantRegB, a.written[3]) + assert.Equal(t, uint8(hmc5883lRegMode), a.written[4]) + assert.Equal(t, wantRegM, a.written[5]) } diff --git a/drivers/i2c/hmc6352_driver_test.go b/drivers/i2c/hmc6352_driver_test.go index fa2e01c0f..81fcd14df 100644 --- a/drivers/i2c/hmc6352_driver_test.go +++ b/drivers/i2c/hmc6352_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -28,26 +28,26 @@ func TestNewHMC6352Driver(t *testing.T) { if !ok { t.Errorf("NewHMC6352Driver() should have returned a *HMC6352Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "HMC6352"), true) - gobottest.Assert(t, d.defaultAddress, 0x21) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "HMC6352")) + assert.Equal(t, 0x21, d.defaultAddress) } func TestHMC6352Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewHMC6352Driver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestHMC6352Start(t *testing.T) { d := NewHMC6352Driver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestHMC6352Halt(t *testing.T) { d, _ := initTestHMC6352DriverWithStubbedAdaptor() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestHMC6352Heading(t *testing.T) { @@ -59,7 +59,7 @@ func TestHMC6352Heading(t *testing.T) { } heading, _ := d.Heading() - gobottest.Assert(t, heading, uint16(2534)) + assert.Equal(t, uint16(2534), heading) // when len(data) is not 2 d, a = initTestHMC6352DriverWithStubbedAdaptor() @@ -69,8 +69,8 @@ func TestHMC6352Heading(t *testing.T) { } heading, err := d.Heading() - gobottest.Assert(t, heading, uint16(0)) - gobottest.Assert(t, err, ErrNotEnoughBytes) + assert.Equal(t, uint16(0), heading) + assert.Equal(t, ErrNotEnoughBytes, err) // when read error d, a = initTestHMC6352DriverWithStubbedAdaptor() @@ -79,8 +79,8 @@ func TestHMC6352Heading(t *testing.T) { } heading, err = d.Heading() - gobottest.Assert(t, heading, uint16(0)) - gobottest.Assert(t, err, errors.New("read error")) + assert.Equal(t, uint16(0), heading) + assert.Errorf(t, err, "read error") // when write error d, a = initTestHMC6352DriverWithStubbedAdaptor() @@ -89,6 +89,6 @@ func TestHMC6352Heading(t *testing.T) { } heading, err = d.Heading() - gobottest.Assert(t, heading, uint16(0)) - gobottest.Assert(t, err, errors.New("write error")) + assert.Equal(t, uint16(0), heading) + assert.Errorf(t, err, "write error") } diff --git a/drivers/i2c/i2c_config_test.go b/drivers/i2c/i2c_config_test.go index fac9087ae..522e506bb 100644 --- a/drivers/i2c/i2c_config_test.go +++ b/drivers/i2c/i2c_config_test.go @@ -3,7 +3,7 @@ package i2c import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestNewConfig(t *testing.T) { @@ -14,8 +14,8 @@ func TestNewConfig(t *testing.T) { if !ok { t.Errorf("NewConfig() should have returned a *i2cConfig") } - gobottest.Assert(t, c.bus, BusNotInitialized) - gobottest.Assert(t, c.address, AddressNotInitialized) + assert.Equal(t, BusNotInitialized, c.bus) + assert.Equal(t, AddressNotInitialized, c.address) } func TestWithBus(t *testing.T) { @@ -24,7 +24,7 @@ func TestWithBus(t *testing.T) { // act c.SetBus(0x23) // assert - gobottest.Assert(t, c.(*i2cConfig).bus, 0x23) + assert.Equal(t, 0x23, c.(*i2cConfig).bus) } func TestWithAddress(t *testing.T) { @@ -33,7 +33,7 @@ func TestWithAddress(t *testing.T) { // act c.SetAddress(0x24) // assert - gobottest.Assert(t, c.(*i2cConfig).address, 0x24) + assert.Equal(t, 0x24, c.(*i2cConfig).address) } func TestGetBusOrDefaultWithBusOption(t *testing.T) { @@ -53,7 +53,7 @@ func TestGetBusOrDefaultWithBusOption(t *testing.T) { WithBus(tc.init)(c) got := c.GetBusOrDefault(tc.bus) // assert - gobottest.Assert(t, got, tc.want) + assert.Equal(t, tc.want, got) }) } } @@ -75,7 +75,7 @@ func TestGetAddressOrDefaultWithAddressOption(t *testing.T) { WithAddress(tc.init)(c) got := c.GetAddressOrDefault(tc.address) // assert - gobottest.Assert(t, got, tc.want) + assert.Equal(t, tc.want, got) }) } } diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index 7e7600742..a243dd013 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -4,13 +4,12 @@ package i2c import ( - "errors" "testing" "unsafe" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -72,130 +71,130 @@ func initI2CDeviceAddressError() gobot.I2cSystemDevicer { func TestI2CAddress(t *testing.T) { c := NewConnection(initI2CDevice(), 0x66) - gobottest.Assert(t, c.address, 0x66) + assert.Equal(t, 0x66, c.address) } func TestI2CClose(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) - gobottest.Assert(t, c.Close(), nil) + assert.Nil(t, c.Close()) } func TestI2CRead(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) i, _ := c.Read([]byte{}) - gobottest.Assert(t, i, 0) + assert.Equal(t, 0, i) } func TestI2CReadAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.Read([]byte{}) - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWrite(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) i, _ := c.Write([]byte{0x01}) - gobottest.Assert(t, i, 1) + assert.Equal(t, 1, i) } func TestI2CWriteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.Write([]byte{0x01}) - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadByte(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) v, _ := c.ReadByte() - gobottest.Assert(t, v, uint8(0xFC)) + assert.Equal(t, uint8(0xFC), v) } func TestI2CReadByteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadByte() - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadByteData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) v, _ := c.ReadByteData(0x01) - gobottest.Assert(t, v, uint8(0xFD)) + assert.Equal(t, uint8(0xFD), v) } func TestI2CReadByteDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadByteData(0x01) - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadWordData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) v, _ := c.ReadWordData(0x01) - gobottest.Assert(t, v, uint16(0xFFFE)) + assert.Equal(t, uint16(0xFFFE), v) } func TestI2CReadWordDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadWordData(0x01) - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteByte(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteByte(0x01) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestI2CWriteByteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteByte(0x01) - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteByteData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteByteData(0x01, 0x01) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestI2CWriteByteDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteByteData(0x01, 0x01) - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteWordData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteWordData(0x01, 0x01) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestI2CWriteWordDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteWordData(0x01, 0x01) - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteBlockData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteBlockData(0x01, []byte{0x01, 0x02}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestI2CWriteBlockDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteBlockData(0x01, []byte{0x01, 0x02}) - gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted")) + assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") } func Test_setBit(t *testing.T) { var expectedVal uint8 = 129 actualVal := setBit(1, 7) - gobottest.Assert(t, expectedVal, actualVal) + assert.Equal(t, actualVal, expectedVal) } func Test_clearBit(t *testing.T) { var expectedVal uint8 actualVal := clearBit(128, 7) - gobottest.Assert(t, expectedVal, actualVal) + assert.Equal(t, actualVal, expectedVal) } diff --git a/drivers/i2c/i2c_driver_test.go b/drivers/i2c/i2c_driver_test.go index 3fed2a785..51bc13e57 100644 --- a/drivers/i2c/i2c_driver_test.go +++ b/drivers/i2c/i2c_driver_test.go @@ -1,12 +1,10 @@ package i2c import ( - "errors" - "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -32,15 +30,15 @@ func TestNewDriver(t *testing.T) { if !ok { t.Errorf("NewDriver() should have returned a *Driver") } - gobottest.Assert(t, strings.Contains(d.name, "I2C_BASIC"), true) - gobottest.Assert(t, d.defaultAddress, 0x15) - gobottest.Assert(t, d.connector, a) - gobottest.Assert(t, d.connection, nil) - gobottest.Assert(t, d.afterStart(), nil) - gobottest.Assert(t, d.beforeHalt(), nil) - gobottest.Refute(t, d.Config, nil) - gobottest.Refute(t, d.Commander, nil) - gobottest.Refute(t, d.mutex, nil) + assert.Contains(t, d.name, "I2C_BASIC") + assert.Equal(t, 0x15, d.defaultAddress) + assert.Equal(t, a, d.connector) + assert.Nil(t, d.connection) + assert.Nil(t, d.afterStart()) + assert.Nil(t, d.beforeHalt()) + assert.NotNil(t, d.Config) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) } func TestSetName(t *testing.T) { @@ -49,22 +47,22 @@ func TestSetName(t *testing.T) { // act d.SetName("TESTME") // assert - gobottest.Assert(t, d.Name(), "TESTME") + assert.Equal(t, "TESTME", d.Name()) } func TestConnection(t *testing.T) { // arrange d := initTestDriver() // act, assert - gobottest.Refute(t, d.Connection(), nil) + assert.NotNil(t, d.Connection()) } func TestStart(t *testing.T) { // arrange d, a := initDriverWithStubbedAdaptor() // act, assert - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, 0x15, a.address) + assert.Nil(t, d.Start()) + assert.Equal(t, a.address, 0x15) } func TestStartConnectError(t *testing.T) { @@ -72,14 +70,14 @@ func TestStartConnectError(t *testing.T) { d, a := initDriverWithStubbedAdaptor() a.Testi2cConnectErr(true) // act, assert - gobottest.Assert(t, d.Start(), errors.New("Invalid i2c connection")) + assert.Errorf(t, d.Start(), "Invalid i2c connection") } func TestHalt(t *testing.T) { // arrange d := initTestDriver() // act, assert - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestWrite(t *testing.T) { @@ -100,10 +98,10 @@ func TestWrite(t *testing.T) { // act err := d.Write(address, value) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsWrite, 1) - gobottest.Assert(t, a.written[0], wantAddress) - gobottest.Assert(t, a.written[1], uint8(value)) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsWrite) + assert.Equal(t, wantAddress, a.written[0]) + assert.Equal(t, uint8(value), a.written[1]) } func TestRead(t *testing.T) { @@ -131,9 +129,9 @@ func TestRead(t *testing.T) { // act val, err := d.Read(address) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, val, int(want)) - gobottest.Assert(t, numCallsWrite, 1) - gobottest.Assert(t, a.written[0], wantAddress) - gobottest.Assert(t, numCallsRead, 1) + assert.Nil(t, err) + assert.Equal(t, int(want), val) + assert.Equal(t, 1, numCallsWrite) + assert.Equal(t, wantAddress, a.written[0]) + assert.Equal(t, 1, numCallsRead) } diff --git a/drivers/i2c/ina3221_driver_test.go b/drivers/i2c/ina3221_driver_test.go index 3564fd824..2e490830e 100644 --- a/drivers/i2c/ina3221_driver_test.go +++ b/drivers/i2c/ina3221_driver_test.go @@ -7,8 +7,8 @@ import ( "strings" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -30,26 +30,26 @@ func TestNewINA3221Driver(t *testing.T) { if !ok { t.Error("NewINA3221Driver() should return a *INA3221Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "INA3221"), true) - gobottest.Assert(t, d.defaultAddress, 0x40) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "INA3221")) + assert.Equal(t, 0x40, d.defaultAddress) } func TestINA3221Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewINA3221Driver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestINA3221Start(t *testing.T) { d := NewINA3221Driver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestINA3221Halt(t *testing.T) { d, _ := initTestINA3221DriverWithStubbedAdaptor() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestINA3221GetBusVoltage(t *testing.T) { @@ -61,8 +61,8 @@ func TestINA3221GetBusVoltage(t *testing.T) { } v, err := d.GetBusVoltage(INA3221Channel1) - gobottest.Assert(t, v, float64(13.928)) - gobottest.Assert(t, err, nil) + assert.Equal(t, float64(13.928), v) + assert.Nil(t, err) } func TestINA3221GetBusVoltageReadError(t *testing.T) { @@ -72,7 +72,7 @@ func TestINA3221GetBusVoltageReadError(t *testing.T) { } _, err := d.GetBusVoltage(INA3221Channel1) - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestINA3221GetShuntVoltage(t *testing.T) { @@ -84,8 +84,8 @@ func TestINA3221GetShuntVoltage(t *testing.T) { } v, err := d.GetShuntVoltage(INA3221Channel1) - gobottest.Assert(t, v, float64(7.48)) - gobottest.Assert(t, err, nil) + assert.Equal(t, float64(7.48), v) + assert.Nil(t, err) } func TestINA3221GetShuntVoltageReadError(t *testing.T) { @@ -95,7 +95,7 @@ func TestINA3221GetShuntVoltageReadError(t *testing.T) { } _, err := d.GetShuntVoltage(INA3221Channel1) - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestINA3221GetCurrent(t *testing.T) { @@ -107,8 +107,8 @@ func TestINA3221GetCurrent(t *testing.T) { } v, err := d.GetCurrent(INA3221Channel1) - gobottest.Assert(t, v, float64(74.8)) - gobottest.Assert(t, err, nil) + assert.Equal(t, float64(74.8), v) + assert.Nil(t, err) } func TestINA3221CurrentReadError(t *testing.T) { @@ -118,7 +118,7 @@ func TestINA3221CurrentReadError(t *testing.T) { } _, err := d.GetCurrent(INA3221Channel1) - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestINA3221GetLoadVoltage(t *testing.T) { @@ -132,8 +132,8 @@ func TestINA3221GetLoadVoltage(t *testing.T) { } v, err := d.GetLoadVoltage(INA3221Channel2) - gobottest.Assert(t, v, float64(13.935480)) - gobottest.Assert(t, err, nil) + assert.Equal(t, float64(13.935480), v) + assert.Nil(t, err) } func TestINA3221GetLoadVoltageReadError(t *testing.T) { @@ -143,5 +143,5 @@ func TestINA3221GetLoadVoltageReadError(t *testing.T) { } _, err := d.GetLoadVoltage(INA3221Channel2) - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } diff --git a/drivers/i2c/jhd1313m1_driver_test.go b/drivers/i2c/jhd1313m1_driver_test.go index 1c0c99fc9..858689dd6 100644 --- a/drivers/i2c/jhd1313m1_driver_test.go +++ b/drivers/i2c/jhd1313m1_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*JHD1313M1Driver)(nil) @@ -37,30 +37,30 @@ func TestNewJHD1313M1Driver(t *testing.T) { func TestJHD1313M1Driver(t *testing.T) { jhd := initTestJHD1313M1Driver() - gobottest.Refute(t, jhd.Connection(), nil) - gobottest.Assert(t, strings.HasPrefix(jhd.Name(), "JHD1313M1"), true) + assert.NotNil(t, jhd.Connection()) + assert.True(t, strings.HasPrefix(jhd.Name(), "JHD1313M1")) } func TestJHD1313MDriverSetName(t *testing.T) { d := initTestJHD1313M1Driver() d.SetName("TESTME") - gobottest.Assert(t, d.Name(), "TESTME") + assert.Equal(t, "TESTME", d.Name()) } func TestJHD1313MDriverOptions(t *testing.T) { d := NewJHD1313M1Driver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestJHD1313MDriverStart(t *testing.T) { d := initTestJHD1313M1Driver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestJHD1313MStartConnectError(t *testing.T) { d, adaptor := initTestJHD1313M1DriverWithStubbedAdaptor() adaptor.Testi2cConnectErr(true) - gobottest.Assert(t, d.Start(), errors.New("Invalid i2c connection")) + assert.Errorf(t, d.Start(), "Invalid i2c connection") } func TestJHD1313MDriverStartWriteError(t *testing.T) { @@ -68,19 +68,19 @@ func TestJHD1313MDriverStartWriteError(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.Start(), errors.New("write error")) + assert.Errorf(t, d.Start(), "write error") } func TestJHD1313MDriverHalt(t *testing.T) { d := initTestJHD1313M1Driver() _ = d.Start() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestJHD1313MDriverSetRgb(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.SetRGB(0x00, 0x00, 0x00), nil) + assert.Nil(t, d.SetRGB(0x00, 0x00, 0x00)) } func TestJHD1313MDriverSetRgbError(t *testing.T) { @@ -90,13 +90,13 @@ func TestJHD1313MDriverSetRgbError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.SetRGB(0x00, 0x00, 0x00), errors.New("write error")) + assert.Errorf(t, d.SetRGB(0x00, 0x00, 0x00), "write error") } func TestJHD1313MDriverClear(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Clear(), nil) + assert.Nil(t, d.Clear()) } func TestJHD1313MDriverClearError(t *testing.T) { @@ -106,19 +106,19 @@ func TestJHD1313MDriverClearError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.Clear(), errors.New("write error")) + assert.Errorf(t, d.Clear(), "write error") } func TestJHD1313MDriverHome(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Home(), nil) + assert.Nil(t, d.Home()) } func TestJHD1313MDriverWrite(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Write("Hello"), nil) + assert.Nil(t, d.Write("Hello")) } func TestJHD1313MDriverWriteError(t *testing.T) { @@ -128,13 +128,13 @@ func TestJHD1313MDriverWriteError(t *testing.T) { return 0, errors.New("write error") } - gobottest.Assert(t, d.Write("Hello"), errors.New("write error")) + assert.Errorf(t, d.Write("Hello"), "write error") } func TestJHD1313MDriverWriteTwoLines(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Write("Hello\nthere"), nil) + assert.Nil(t, d.Write("Hello\nthere")) } func TestJHD1313MDriverWriteTwoLinesError(t *testing.T) { @@ -144,52 +144,52 @@ func TestJHD1313MDriverWriteTwoLinesError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.Write("Hello\nthere"), errors.New("write error")) + assert.Errorf(t, d.Write("Hello\nthere"), "write error") } func TestJHD1313MDriverSetPosition(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.SetPosition(2), nil) + assert.Nil(t, d.SetPosition(2)) } func TestJHD1313MDriverSetSecondLinePosition(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.SetPosition(18), nil) + assert.Nil(t, d.SetPosition(18)) } func TestJHD1313MDriverSetPositionInvalid(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.SetPosition(-1), jhd1313m1ErrInvalidPosition) - gobottest.Assert(t, d.SetPosition(32), jhd1313m1ErrInvalidPosition) + assert.Equal(t, jhd1313m1ErrInvalidPosition, d.SetPosition(-1)) + assert.Equal(t, jhd1313m1ErrInvalidPosition, d.SetPosition(32)) } func TestJHD1313MDriverScroll(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Scroll(true), nil) + assert.Nil(t, d.Scroll(true)) } func TestJHD1313MDriverReverseScroll(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - gobottest.Assert(t, d.Scroll(false), nil) + assert.Nil(t, d.Scroll(false)) } func TestJHD1313MDriverSetCustomChar(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} _ = d.Start() - gobottest.Assert(t, d.SetCustomChar(0, data), nil) + assert.Nil(t, d.SetCustomChar(0, data)) } func TestJHD1313MDriverSetCustomCharError(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} _ = d.Start() - gobottest.Assert(t, d.SetCustomChar(10, data), errors.New("can't set a custom character at a position greater than 7")) + assert.Errorf(t, d.SetCustomChar(10, data), "can't set a custom character at a position greater than 7") } func TestJHD1313MDriverSetCustomCharWriteError(t *testing.T) { @@ -200,7 +200,7 @@ func TestJHD1313MDriverSetCustomCharWriteError(t *testing.T) { return 0, errors.New("write error") } data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - gobottest.Assert(t, d.SetCustomChar(0, data), errors.New("write error")) + assert.Errorf(t, d.SetCustomChar(0, data), "write error") } func TestJHD1313MDriverCommands(t *testing.T) { @@ -208,20 +208,20 @@ func TestJHD1313MDriverCommands(t *testing.T) { _ = d.Start() err := d.Command("SetRGB")(map[string]interface{}{"r": "1", "g": "1", "b": "1"}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = d.Command("Clear")(map[string]interface{}{}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = d.Command("Home")(map[string]interface{}{}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = d.Command("Write")(map[string]interface{}{"msg": "Hello"}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = d.Command("SetPosition")(map[string]interface{}{"pos": "1"}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = d.Command("Scroll")(map[string]interface{}{"lr": "true"}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } diff --git a/drivers/i2c/l3gd20h_driver_test.go b/drivers/i2c/l3gd20h_driver_test.go index 892891698..01a3cf728 100644 --- a/drivers/i2c/l3gd20h_driver_test.go +++ b/drivers/i2c/l3gd20h_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -33,17 +33,17 @@ func TestNewL3GD20HDriver(t *testing.T) { if !ok { t.Errorf("NewL3GD20HDriver() should have returned a *L3GD20HDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "L3GD20H"), true) - gobottest.Assert(t, d.defaultAddress, 0x6b) - gobottest.Assert(t, d.Scale(), L3GD20HScale250dps) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "L3GD20H")) + assert.Equal(t, 0x6b, d.defaultAddress) + assert.Equal(t, L3GD20HScale250dps, d.Scale()) } func TestL3GD20HOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option. // Further tests for options can also be done by call of "WithOption(val)(d)". d := NewL3GD20HDriver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestL3GD20HWithL3GD20HFullScaleRange(t *testing.T) { @@ -75,7 +75,7 @@ func TestL3GD20HWithL3GD20HFullScaleRange(t *testing.T) { // act WithL3GD20HFullScaleRange(tc.scale)(d) // assert - gobottest.Assert(t, d.scale, L3GD20HScale(tc.want)) + assert.Equal(t, L3GD20HScale(tc.want), d.scale) }) } } @@ -109,7 +109,7 @@ func TestL3GD20HScale(t *testing.T) { // act d.SetScale(tc.scale) // assert - gobottest.Assert(t, d.scale, L3GD20HScale(tc.want)) + assert.Equal(t, L3GD20HScale(tc.want), d.scale) }) } } @@ -130,10 +130,10 @@ func TestL3GD20HFullScaleRange(t *testing.T) { // act got, err := d.FullScaleRange() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(0x23)) - gobottest.Assert(t, got, readValue) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(0x23), a.written[0]) + assert.Equal(t, readValue, got) } func TestL3GD20HMeasurement(t *testing.T) { @@ -196,12 +196,12 @@ func TestL3GD20HMeasurement(t *testing.T) { // act x, y, z, err := d.XYZ() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(0xA8)) - gobottest.Assert(t, x, tc.wantX) - gobottest.Assert(t, y, tc.wantY) - gobottest.Assert(t, z, tc.wantZ) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(0xA8), a.written[0]) + assert.Equal(t, tc.wantX, x) + assert.Equal(t, tc.wantY, y) + assert.Equal(t, tc.wantZ, z) }) } } @@ -214,7 +214,7 @@ func TestL3GD20HMeasurementError(t *testing.T) { _ = d.Start() _, _, _, err := d.XYZ() - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestL3GD20HMeasurementWriteError(t *testing.T) { @@ -223,7 +223,7 @@ func TestL3GD20HMeasurementWriteError(t *testing.T) { return 0, errors.New("write error") } _, _, _, err := d.XYZ() - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } func TestL3GD20H_initialize(t *testing.T) { @@ -250,11 +250,11 @@ func TestL3GD20H_initialize(t *testing.T) { // arrange, act - initialize() must be called on Start() _, a := initL3GD20HWithStubbedAdaptor() // assert - gobottest.Assert(t, len(a.written), 6) - gobottest.Assert(t, a.written[0], uint8(0x20)) - gobottest.Assert(t, a.written[1], uint8(0x00)) - gobottest.Assert(t, a.written[2], uint8(0x20)) - gobottest.Assert(t, a.written[3], uint8(0x0F)) - gobottest.Assert(t, a.written[4], uint8(0x23)) - gobottest.Assert(t, a.written[5], uint8(0x00)) + assert.Equal(t, 6, len(a.written)) + assert.Equal(t, uint8(0x20), a.written[0]) + assert.Equal(t, uint8(0x00), a.written[1]) + assert.Equal(t, uint8(0x20), a.written[2]) + assert.Equal(t, uint8(0x0F), a.written[3]) + assert.Equal(t, uint8(0x23), a.written[4]) + assert.Equal(t, uint8(0x00), a.written[5]) } diff --git a/drivers/i2c/lidarlite_driver_test.go b/drivers/i2c/lidarlite_driver_test.go index 9a570fb2c..d3311822f 100644 --- a/drivers/i2c/lidarlite_driver_test.go +++ b/drivers/i2c/lidarlite_driver_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -34,26 +34,26 @@ func TestNewLIDARLiteDriver(t *testing.T) { if !ok { t.Errorf("NewLIDARLiteDriver() should have returned a *LIDARLiteDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "LIDARLite"), true) - gobottest.Assert(t, d.defaultAddress, 0x62) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "LIDARLite")) + assert.Equal(t, 0x62, d.defaultAddress) } func TestLIDARLiteDriverOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewLIDARLiteDriver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestLIDARLiteDriverStart(t *testing.T) { d := NewLIDARLiteDriver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestLIDARLiteDriverHalt(t *testing.T) { d := initTestLIDARLiteDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestLIDARLiteDriverDistance(t *testing.T) { @@ -72,8 +72,8 @@ func TestLIDARLiteDriverDistance(t *testing.T) { distance, err := d.Distance() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, distance, int(25345)) + assert.Nil(t, err) + assert.Equal(t, int(25345), distance) // when insufficient bytes have been read d, a = initTestLIDARLiteDriverWithStubbedAdaptor() @@ -82,8 +82,8 @@ func TestLIDARLiteDriverDistance(t *testing.T) { } distance, err = d.Distance() - gobottest.Assert(t, distance, int(0)) - gobottest.Assert(t, err, ErrNotEnoughBytes) + assert.Equal(t, int(0), distance) + assert.Equal(t, ErrNotEnoughBytes, err) // when read error d, a = initTestLIDARLiteDriverWithStubbedAdaptor() @@ -92,8 +92,8 @@ func TestLIDARLiteDriverDistance(t *testing.T) { } distance, err = d.Distance() - gobottest.Assert(t, distance, int(0)) - gobottest.Assert(t, err, errors.New("read error")) + assert.Equal(t, int(0), distance) + assert.Errorf(t, err, "read error") } func TestLIDARLiteDriverDistanceError1(t *testing.T) { @@ -103,8 +103,8 @@ func TestLIDARLiteDriverDistanceError1(t *testing.T) { } distance, err := d.Distance() - gobottest.Assert(t, distance, int(0)) - gobottest.Assert(t, err, errors.New("write error")) + assert.Equal(t, int(0), distance) + assert.Errorf(t, err, "write error") } func TestLIDARLiteDriverDistanceError2(t *testing.T) { @@ -117,8 +117,8 @@ func TestLIDARLiteDriverDistanceError2(t *testing.T) { } distance, err := d.Distance() - gobottest.Assert(t, distance, int(0)) - gobottest.Assert(t, err, errors.New("write error")) + assert.Equal(t, int(0), distance) + assert.Errorf(t, err, "write error") } func TestLIDARLiteDriverDistanceError3(t *testing.T) { @@ -137,6 +137,6 @@ func TestLIDARLiteDriverDistanceError3(t *testing.T) { } distance, err := d.Distance() - gobottest.Assert(t, distance, int(0)) - gobottest.Assert(t, err, errors.New("write error")) + assert.Equal(t, int(0), distance) + assert.Errorf(t, err, "write error") } diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index a682c0caf..220df3272 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -45,56 +45,56 @@ func TestNewMCP23017Driver(t *testing.T) { if !ok { t.Errorf("NewMCP23017Driver() should have returned a *MCP23017Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "MCP23017"), true) - gobottest.Assert(t, d.defaultAddress, 0x20) - gobottest.Refute(t, d.mcpConf, nil) - gobottest.Refute(t, d.mcpBehav, nil) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "MCP23017")) + assert.Equal(t, 0x20, d.defaultAddress) + assert.NotNil(t, d.mcpConf) + assert.NotNil(t, d.mcpBehav) } func TestWithMCP23017Bank(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Bank(1)) - gobottest.Assert(t, b.mcpConf.bank, uint8(1)) + assert.Equal(t, uint8(1), b.mcpConf.bank) } func TestWithMCP23017Mirror(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Mirror(1)) - gobottest.Assert(t, b.mcpConf.mirror, uint8(1)) + assert.Equal(t, uint8(1), b.mcpConf.mirror) } func TestWithMCP23017Seqop(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Seqop(1)) - gobottest.Assert(t, b.mcpConf.seqop, uint8(1)) + assert.Equal(t, uint8(1), b.mcpConf.seqop) } func TestWithMCP23017Disslw(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Disslw(1)) - gobottest.Assert(t, b.mcpConf.disslw, uint8(1)) + assert.Equal(t, uint8(1), b.mcpConf.disslw) } func TestWithMCP23017Haen(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Haen(1)) - gobottest.Assert(t, b.mcpConf.haen, uint8(1)) + assert.Equal(t, uint8(1), b.mcpConf.haen) } func TestWithMCP23017Odr(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Odr(1)) - gobottest.Assert(t, b.mcpConf.odr, uint8(1)) + assert.Equal(t, uint8(1), b.mcpConf.odr) } func TestWithMCP23017Intpol(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Intpol(1)) - gobottest.Assert(t, b.mcpConf.intpol, uint8(1)) + assert.Equal(t, uint8(1), b.mcpConf.intpol) } func TestWithMCP23017ForceRefresh(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017ForceRefresh(1)) - gobottest.Assert(t, b.mcpBehav.forceRefresh, true) + assert.True(t, b.mcpBehav.forceRefresh) } func TestWithMCP23017AutoIODirOff(t *testing.T) { b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017AutoIODirOff(1)) - gobottest.Assert(t, b.mcpBehav.autoIODirOff, true) + assert.True(t, b.mcpBehav.autoIODirOff) } func TestMCP23017CommandsWriteGPIO(t *testing.T) { @@ -103,7 +103,7 @@ func TestMCP23017CommandsWriteGPIO(t *testing.T) { // act result := d.Command("WriteGPIO")(pinValPort) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestMCP23017CommandsReadGPIO(t *testing.T) { @@ -112,7 +112,7 @@ func TestMCP23017CommandsReadGPIO(t *testing.T) { // act result := d.Command("ReadGPIO")(pinPort) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestMCP23017WriteGPIO(t *testing.T) { @@ -147,15 +147,15 @@ func TestMCP23017WriteGPIO(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 6) - gobottest.Assert(t, a.written[0], wantReg1) - gobottest.Assert(t, a.written[1], wantReg1) - gobottest.Assert(t, a.written[2], wantReg1Val) - gobottest.Assert(t, a.written[3], wantReg2) - gobottest.Assert(t, a.written[4], wantReg2) - gobottest.Assert(t, a.written[5], wantReg2Val) - gobottest.Assert(t, numCallsRead, 2) + assert.Nil(t, err) + assert.Equal(t, 6, len(a.written)) + assert.Equal(t, wantReg1, a.written[0]) + assert.Equal(t, wantReg1, a.written[1]) + assert.Equal(t, wantReg1Val, a.written[2]) + assert.Equal(t, wantReg2, a.written[3]) + assert.Equal(t, wantReg2, a.written[4]) + assert.Equal(t, wantReg2Val, a.written[5]) + assert.Equal(t, 2, numCallsRead) } } @@ -186,11 +186,11 @@ func TestMCP23017WriteGPIONoRefresh(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], wantReg1) - gobottest.Assert(t, a.written[1], wantReg2) - gobottest.Assert(t, numCallsRead, 2) + assert.Nil(t, err) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, wantReg1, a.written[0]) + assert.Equal(t, wantReg2, a.written[1]) + assert.Equal(t, 2, numCallsRead) } } @@ -223,12 +223,12 @@ func TestMCP23017WriteGPIONoAutoDir(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 3) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, a.written[1], wantReg) - gobottest.Assert(t, a.written[2], wantRegVal) - gobottest.Assert(t, numCallsRead, 1) + assert.Nil(t, err) + assert.Equal(t, 3, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, wantReg, a.written[1]) + assert.Equal(t, wantRegVal, a.written[2]) + assert.Equal(t, 1, numCallsRead) } } @@ -241,7 +241,7 @@ func TestMCP23017CommandsWriteGPIOErrIODIR(t *testing.T) { // act err := d.WriteGPIO(7, "A", 0) // assert - gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=0): write error")) + assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") } func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { @@ -258,7 +258,7 @@ func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { // act err := d.WriteGPIO(7, "A", 0) // assert - gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=20): write error")) + assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=20): write error") } func TestMCP23017ReadGPIO(t *testing.T) { @@ -290,14 +290,14 @@ func TestMCP23017ReadGPIO(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, len(a.written), 4) - gobottest.Assert(t, a.written[0], wantReg1) - gobottest.Assert(t, a.written[1], wantReg1) - gobottest.Assert(t, a.written[2], wantReg1Val) - gobottest.Assert(t, a.written[3], wantReg2) - gobottest.Assert(t, val, uint8(bitState)) + assert.Nil(t, err) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, 4, len(a.written)) + assert.Equal(t, wantReg1, a.written[0]) + assert.Equal(t, wantReg1, a.written[1]) + assert.Equal(t, wantReg1Val, a.written[2]) + assert.Equal(t, wantReg2, a.written[3]) + assert.Equal(t, uint8(bitState), val) } } @@ -328,12 +328,12 @@ func TestMCP23017ReadGPIONoRefresh(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], wantReg1) - gobottest.Assert(t, a.written[1], wantReg2) - gobottest.Assert(t, val, uint8(bitState)) + assert.Nil(t, err) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, wantReg1, a.written[0]) + assert.Equal(t, wantReg2, a.written[1]) + assert.Equal(t, uint8(bitState), val) } } @@ -363,11 +363,11 @@ func TestMCP23017ReadGPIONoAutoDir(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], wantReg2) - gobottest.Assert(t, val, uint8(bitState)) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, wantReg2, a.written[0]) + assert.Equal(t, uint8(bitState), val) } } @@ -381,7 +381,7 @@ func TestMCP23017ReadGPIOErr(t *testing.T) { // act _, err := d.ReadGPIO(7, "A") // assert - gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=0): read error")) + assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): read error") } func TestMCP23017SetPinMode(t *testing.T) { @@ -413,12 +413,12 @@ func TestMCP23017SetPinMode(t *testing.T) { // act err := d.SetPinMode(testPin, testPort, uint8(bitState)) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 3) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, a.written[1], wantReg) - gobottest.Assert(t, a.written[2], wantRegVal) - gobottest.Assert(t, numCallsRead, 1) + assert.Nil(t, err) + assert.Equal(t, 3, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, wantReg, a.written[1]) + assert.Equal(t, wantRegVal, a.written[2]) + assert.Equal(t, 1, numCallsRead) } } @@ -431,7 +431,7 @@ func TestMCP23017SetPinModeErr(t *testing.T) { // act err := d.SetPinMode(7, "A", 0) // assert - gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=0): write error")) + assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") } func TestMCP23017SetPullUp(t *testing.T) { @@ -463,12 +463,12 @@ func TestMCP23017SetPullUp(t *testing.T) { // act err := d.SetPullUp(testPin, testPort, uint8(bitState)) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 3) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, a.written[1], wantReg) - gobottest.Assert(t, a.written[2], wantSetVal) - gobottest.Assert(t, numCallsRead, 1) + assert.Nil(t, err) + assert.Equal(t, 3, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, wantReg, a.written[1]) + assert.Equal(t, wantSetVal, a.written[2]) + assert.Equal(t, 1, numCallsRead) } } @@ -481,7 +481,7 @@ func TestMCP23017SetPullUpErr(t *testing.T) { // act err := d.SetPullUp(7, "A", 0) // assert - gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=12): write error")) + assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=12): write error") } func TestMCP23017SetGPIOPolarity(t *testing.T) { @@ -513,12 +513,12 @@ func TestMCP23017SetGPIOPolarity(t *testing.T) { // act err := d.SetGPIOPolarity(testPin, testPort, uint8(bitState)) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 3) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, a.written[1], wantReg) - gobottest.Assert(t, a.written[2], wantSetVal) - gobottest.Assert(t, numCallsRead, 1) + assert.Nil(t, err) + assert.Equal(t, 3, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, wantReg, a.written[1]) + assert.Equal(t, wantSetVal, a.written[2]) + assert.Equal(t, 1, numCallsRead) } } @@ -531,7 +531,7 @@ func TestMCP23017SetGPIOPolarityErr(t *testing.T) { // act err := d.SetGPIOPolarity(7, "A", 0) // assert - gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=2): write error")) + assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=2): write error") } func TestMCP23017_write(t *testing.T) { @@ -539,13 +539,13 @@ func TestMCP23017_write(t *testing.T) { d, _ := initTestMCP23017WithStubbedAdaptor(0) port := d.getPort("A") err := d.write(port.IODIR, uint8(7), 0) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) // set bit d, _ = initTestMCP23017WithStubbedAdaptor(0) port = d.getPort("B") err = d.write(port.IODIR, uint8(7), 1) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) // write error d, a := initTestMCP23017WithStubbedAdaptor(0) @@ -553,7 +553,7 @@ func TestMCP23017_write(t *testing.T) { return 0, errors.New("write error") } err = d.write(port.IODIR, uint8(7), 0) - gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=1): write error")) + assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): write error") // read error d, a = initTestMCP23017WithStubbedAdaptor(0) @@ -561,12 +561,12 @@ func TestMCP23017_write(t *testing.T) { return len(b), errors.New("read error") } err = d.write(port.IODIR, uint8(7), 0) - gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=1): read error")) + assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): read error") a.i2cReadImpl = func(b []byte) (int, error) { return len(b), nil } err = d.write(port.IODIR, uint8(7), 1) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestMCP23017_read(t *testing.T) { @@ -578,7 +578,7 @@ func TestMCP23017_read(t *testing.T) { return 1, nil } val, _ := d.read(port.IODIR) - gobottest.Assert(t, val, uint8(255)) + assert.Equal(t, uint8(255), val) // read error d, a = initTestMCP23017WithStubbedAdaptor(0) @@ -587,8 +587,8 @@ func TestMCP23017_read(t *testing.T) { } val, err := d.read(port.IODIR) - gobottest.Assert(t, val, uint8(0)) - gobottest.Assert(t, err, errors.New("MCP write-ReadByteData(reg=0): read error")) + assert.Equal(t, uint8(0), val) + assert.Errorf(t, err, "MCP write-ReadByteData(reg=0): read error") // read d, a = initTestMCP23017WithStubbedAdaptor(0) @@ -598,7 +598,7 @@ func TestMCP23017_read(t *testing.T) { return 1, nil } val, _ = d.read(port.IODIR) - gobottest.Assert(t, val, uint8(255)) + assert.Equal(t, uint8(255), val) } func TestMCP23017_getPort(t *testing.T) { @@ -606,23 +606,23 @@ func TestMCP23017_getPort(t *testing.T) { d := initTestMCP23017(0) expectedPort := mcp23017GetBank(0).portA actualPort := d.getPort("A") - gobottest.Assert(t, expectedPort, actualPort) + assert.Equal(t, actualPort, expectedPort) // port B d = initTestMCP23017(0) expectedPort = mcp23017GetBank(0).portB actualPort = d.getPort("B") - gobottest.Assert(t, expectedPort, actualPort) + assert.Equal(t, actualPort, expectedPort) // default d = initTestMCP23017(0) expectedPort = mcp23017GetBank(0).portA actualPort = d.getPort("") - gobottest.Assert(t, expectedPort, actualPort) + assert.Equal(t, actualPort, expectedPort) // port A bank 1 d = initTestMCP23017(1) expectedPort = mcp23017GetBank(1).portA actualPort = d.getPort("") - gobottest.Assert(t, expectedPort, actualPort) + assert.Equal(t, actualPort, expectedPort) } diff --git a/drivers/i2c/mma7660_driver_test.go b/drivers/i2c/mma7660_driver_test.go index d44d0fa87..44529c6b6 100644 --- a/drivers/i2c/mma7660_driver_test.go +++ b/drivers/i2c/mma7660_driver_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -29,43 +29,43 @@ func TestNewMMA7660Driver(t *testing.T) { if !ok { t.Errorf("NewMMA7660Driver() should have returned a *MMA7660Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "MMA7660"), true) - gobottest.Assert(t, d.defaultAddress, 0x4c) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "MMA7660")) + assert.Equal(t, 0x4c, d.defaultAddress) } func TestMMA7660Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewMMA7660Driver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestMMA7660Start(t *testing.T) { d := NewMMA7660Driver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestMMA7660Halt(t *testing.T) { d, _ := initTestMMA7660DriverWithStubbedAdaptor() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestMMA7660Acceleration(t *testing.T) { d, _ := initTestMMA7660DriverWithStubbedAdaptor() x, y, z := d.Acceleration(21.0, 21.0, 21.0) - gobottest.Assert(t, x, 1.0) - gobottest.Assert(t, y, 1.0) - gobottest.Assert(t, z, 1.0) + assert.Equal(t, 1.0, x) + assert.Equal(t, 1.0, y) + assert.Equal(t, 1.0, z) } func TestMMA7660NullXYZ(t *testing.T) { d, _ := initTestMMA7660DriverWithStubbedAdaptor() x, y, z, _ := d.XYZ() - gobottest.Assert(t, x, 0.0) - gobottest.Assert(t, y, 0.0) - gobottest.Assert(t, z, 0.0) + assert.Equal(t, 0.0, x) + assert.Equal(t, 0.0, y) + assert.Equal(t, 0.0, z) } func TestMMA7660XYZ(t *testing.T) { @@ -78,9 +78,9 @@ func TestMMA7660XYZ(t *testing.T) { } x, y, z, _ := d.XYZ() - gobottest.Assert(t, x, 17.0) - gobottest.Assert(t, y, 18.0) - gobottest.Assert(t, z, 19.0) + assert.Equal(t, 17.0, x) + assert.Equal(t, 18.0, y) + assert.Equal(t, 19.0, z) } func TestMMA7660XYZError(t *testing.T) { @@ -90,7 +90,7 @@ func TestMMA7660XYZError(t *testing.T) { } _, _, _, err := d.XYZ() - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestMMA7660XYZNotReady(t *testing.T) { @@ -103,5 +103,5 @@ func TestMMA7660XYZNotReady(t *testing.T) { } _, _, _, err := d.XYZ() - gobottest.Assert(t, err, ErrNotReady) + assert.Equal(t, ErrNotReady, err) } diff --git a/drivers/i2c/mpl115a2_driver_test.go b/drivers/i2c/mpl115a2_driver_test.go index 6891e9e47..14a4fb86a 100644 --- a/drivers/i2c/mpl115a2_driver_test.go +++ b/drivers/i2c/mpl115a2_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -24,16 +24,16 @@ func TestNewMPL115A2Driver(t *testing.T) { if !ok { t.Errorf("NewMPL115A2Driver() should have returned a *MPL115A2Driver") } - gobottest.Refute(t, d.Connection(), nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "MPL115A2"), true) - gobottest.Assert(t, d.defaultAddress, 0x60) + assert.NotNil(t, d.Connection()) + assert.True(t, strings.HasPrefix(d.Name(), "MPL115A2")) + assert.Equal(t, 0x60, d.defaultAddress) } func TestMPL115A2Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewMPL115A2Driver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestMPL115A2ReadData(t *testing.T) { @@ -78,18 +78,18 @@ func TestMPL115A2ReadData(t *testing.T) { press, errP := d.Pressure() temp, errT := d.Temperature() // assert - gobottest.Assert(t, errP, nil) - gobottest.Assert(t, errT, nil) - gobottest.Assert(t, readCallCounter, 2) - gobottest.Assert(t, len(a.written), 6) - gobottest.Assert(t, a.written[0], uint8(0x12)) - gobottest.Assert(t, a.written[1], uint8(0x00)) - gobottest.Assert(t, a.written[2], uint8(0x00)) - gobottest.Assert(t, a.written[3], uint8(0x12)) - gobottest.Assert(t, a.written[4], uint8(0x00)) - gobottest.Assert(t, a.written[5], uint8(0x00)) - gobottest.Assert(t, press, float32(96.585915)) - gobottest.Assert(t, temp, float32(23.317757)) + assert.Nil(t, errP) + assert.Nil(t, errT) + assert.Equal(t, 2, readCallCounter) + assert.Equal(t, 6, len(a.written)) + assert.Equal(t, uint8(0x12), a.written[0]) + assert.Equal(t, uint8(0x00), a.written[1]) + assert.Equal(t, uint8(0x00), a.written[2]) + 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.Equal(t, float32(96.585915), press) + assert.Equal(t, float32(23.317757), temp) } func TestMPL115A2ReadDataError(t *testing.T) { @@ -101,7 +101,7 @@ func TestMPL115A2ReadDataError(t *testing.T) { } _, err := d.Pressure() - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } func TestMPL115A2_initialization(t *testing.T) { @@ -124,12 +124,12 @@ func TestMPL115A2_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, readCallCounter, 1) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(0x04)) - gobottest.Assert(t, d.a0, float32(2009.75)) - gobottest.Assert(t, d.b1, float32(-2.3758545)) - gobottest.Assert(t, d.b2, float32(-0.9204712)) - gobottest.Assert(t, d.c12, float32(0.0007901192)) + assert.Nil(t, err) + assert.Equal(t, 1, readCallCounter) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(0x04), a.written[0]) + assert.Equal(t, float32(2009.75), d.a0) + assert.Equal(t, float32(-2.3758545), d.b1) + assert.Equal(t, float32(-0.9204712), d.b2) + assert.Equal(t, float32(0.0007901192), d.c12) } diff --git a/drivers/i2c/mpu6050_driver_test.go b/drivers/i2c/mpu6050_driver_test.go index ac9a3ec9a..905663829 100644 --- a/drivers/i2c/mpu6050_driver_test.go +++ b/drivers/i2c/mpu6050_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -28,48 +28,48 @@ func TestNewMPU6050Driver(t *testing.T) { if !ok { t.Errorf("NewMPU6050Driver() should have returned a *MPU6050Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.name, "MPU6050"), true) - gobottest.Assert(t, d.defaultAddress, 0x68) - gobottest.Assert(t, d.dlpf, MPU6050DlpfConfig(0x00)) - gobottest.Assert(t, d.frameSync, MPU6050FrameSyncConfig(0x00)) - gobottest.Assert(t, d.accelFs, MPU6050AccelFsConfig(0x00)) - gobottest.Assert(t, d.gyroFs, MPU6050GyroFsConfig(0x00)) - gobottest.Assert(t, d.clock, MPU6050Pwr1ClockConfig(0x01)) - gobottest.Assert(t, d.gravity, 9.80665) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.name, "MPU6050")) + assert.Equal(t, 0x68, d.defaultAddress) + assert.Equal(t, MPU6050DlpfConfig(0x00), d.dlpf) + assert.Equal(t, MPU6050FrameSyncConfig(0x00), d.frameSync) + assert.Equal(t, MPU6050AccelFsConfig(0x00), d.accelFs) + assert.Equal(t, MPU6050GyroFsConfig(0x00), d.gyroFs) + assert.Equal(t, MPU6050Pwr1ClockConfig(0x01), d.clock) + assert.Equal(t, 9.80665, d.gravity) } func TestMPU6050Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewMPU6050Driver(newI2cTestAdaptor(), WithBus(2), WithMPU6050DigitalFilter(0x06)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.dlpf, MPU6050DlpfConfig(0x06)) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, MPU6050DlpfConfig(0x06), d.dlpf) } func TestWithMPU6050FrameSync(t *testing.T) { d := NewMPU6050Driver(newI2cTestAdaptor(), WithMPU6050FrameSync(0x07)) - gobottest.Assert(t, d.frameSync, MPU6050FrameSyncConfig(0x07)) + assert.Equal(t, MPU6050FrameSyncConfig(0x07), d.frameSync) } func TestWithMPU6050AccelFullScaleRange(t *testing.T) { d := NewMPU6050Driver(newI2cTestAdaptor(), WithMPU6050AccelFullScaleRange(0x02)) - gobottest.Assert(t, d.accelFs, MPU6050AccelFsConfig(0x02)) + assert.Equal(t, MPU6050AccelFsConfig(0x02), d.accelFs) } func TestWithMPU6050GyroFullScaleRange(t *testing.T) { d := NewMPU6050Driver(newI2cTestAdaptor(), WithMPU6050GyroFullScaleRange(0x03)) - gobottest.Assert(t, d.gyroFs, MPU6050GyroFsConfig(0x03)) + assert.Equal(t, MPU6050GyroFsConfig(0x03), d.gyroFs) } func TestWithMPU6050ClockSource(t *testing.T) { d := NewMPU6050Driver(newI2cTestAdaptor(), WithMPU6050ClockSource(0x05)) - gobottest.Assert(t, d.clock, MPU6050Pwr1ClockConfig(0x05)) + assert.Equal(t, MPU6050Pwr1ClockConfig(0x05), d.clock) } func TestWithMPU6050Gravity(t *testing.T) { d := NewMPU6050Driver(newI2cTestAdaptor(), WithMPU6050Gravity(1.0)) - gobottest.Assert(t, d.gravity, 1.0) + assert.Equal(t, 1.0, d.gravity) } func TestMPU6050GetData(t *testing.T) { @@ -111,9 +111,9 @@ func TestMPU6050GetData(t *testing.T) { // act _ = d.GetData() // assert - gobottest.Assert(t, d.Accelerometer, wantAccel) - gobottest.Assert(t, d.Gyroscope, wantGyro) - gobottest.Assert(t, d.Temperature, wantTemp) + assert.Equal(t, wantAccel, d.Accelerometer) + assert.Equal(t, wantGyro, d.Gyroscope) + assert.Equal(t, wantTemp, d.Temperature) } func TestMPU6050GetDataReadError(t *testing.T) { @@ -124,7 +124,7 @@ func TestMPU6050GetDataReadError(t *testing.T) { return 0, errors.New("read error") } - gobottest.Assert(t, d.GetData(), errors.New("read error")) + assert.Errorf(t, d.GetData(), "read error") } func TestMPU6050GetDataWriteError(t *testing.T) { @@ -135,7 +135,7 @@ func TestMPU6050GetDataWriteError(t *testing.T) { return 0, errors.New("write error") } - gobottest.Assert(t, d.GetData(), errors.New("write error")) + assert.Errorf(t, d.GetData(), "write error") } func TestMPU6050_initialize(t *testing.T) { @@ -172,20 +172,20 @@ func TestMPU6050_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, readCallCounter, 1) - gobottest.Assert(t, len(a.written), 13) - gobottest.Assert(t, a.written[0], uint8(0x6B)) - gobottest.Assert(t, a.written[1], uint8(0x80)) - gobottest.Assert(t, a.written[2], uint8(0x6B)) - gobottest.Assert(t, a.written[3], uint8(0x68)) - gobottest.Assert(t, a.written[4], uint8(0x07)) - gobottest.Assert(t, a.written[5], uint8(0x1A)) - gobottest.Assert(t, a.written[6], uint8(0x00)) - gobottest.Assert(t, a.written[7], uint8(0x1B)) - gobottest.Assert(t, a.written[8], uint8(0x00)) - gobottest.Assert(t, a.written[9], uint8(0x1C)) - gobottest.Assert(t, a.written[10], uint8(0x00)) - gobottest.Assert(t, a.written[11], uint8(0x6B)) - gobottest.Assert(t, a.written[12], uint8(0x01)) + assert.Nil(t, err) + assert.Equal(t, 1, readCallCounter) + assert.Equal(t, 13, len(a.written)) + assert.Equal(t, uint8(0x6B), a.written[0]) + assert.Equal(t, uint8(0x80), a.written[1]) + assert.Equal(t, uint8(0x6B), a.written[2]) + assert.Equal(t, uint8(0x68), a.written[3]) + assert.Equal(t, uint8(0x07), a.written[4]) + assert.Equal(t, uint8(0x1A), a.written[5]) + assert.Equal(t, uint8(0x00), a.written[6]) + assert.Equal(t, uint8(0x1B), a.written[7]) + assert.Equal(t, uint8(0x00), a.written[8]) + assert.Equal(t, uint8(0x1C), a.written[9]) + assert.Equal(t, uint8(0x00), a.written[10]) + assert.Equal(t, uint8(0x6B), a.written[11]) + assert.Equal(t, uint8(0x01), a.written[12]) } diff --git a/drivers/i2c/pca9501_driver_test.go b/drivers/i2c/pca9501_driver_test.go index 8446e43eb..33ecb93d7 100644 --- a/drivers/i2c/pca9501_driver_test.go +++ b/drivers/i2c/pca9501_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -47,16 +47,16 @@ func TestNewPCA9501Driver(t *testing.T) { if !ok { t.Errorf("NewPCA9501Driver() should have returned a *PCA9501Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "PCA9501"), true) - gobottest.Assert(t, d.defaultAddress, 0x3f) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "PCA9501")) + assert.Equal(t, 0x3f, d.defaultAddress) } func TestPCA9501Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewPCA9501Driver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestPCA9501CommandsWriteGPIO(t *testing.T) { @@ -71,7 +71,7 @@ func TestPCA9501CommandsWriteGPIO(t *testing.T) { // act result := d.Command("WriteGPIO")(pinVal) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestPCA9501CommandsReadGPIO(t *testing.T) { @@ -83,7 +83,7 @@ func TestPCA9501CommandsReadGPIO(t *testing.T) { // act result := d.Command("ReadGPIO")(pin) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestPCA9501CommandsWriteEEPROM(t *testing.T) { @@ -95,7 +95,7 @@ func TestPCA9501CommandsWriteEEPROM(t *testing.T) { // act result := d.Command("WriteEEPROM")(addressVal) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestPCA9501CommandsReadEEPROM(t *testing.T) { @@ -110,7 +110,7 @@ func TestPCA9501CommandsReadEEPROM(t *testing.T) { // act result := d.Command("ReadEEPROM")(address) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestPCA9501WriteGPIO(t *testing.T) { @@ -160,11 +160,11 @@ func TestPCA9501WriteGPIO(t *testing.T) { // act err := d.WriteGPIO(tc.pin, tc.setVal) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], tc.wantPin) - gobottest.Assert(t, a.written[1], tc.wantState) + assert.Nil(t, err) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, tc.wantPin, a.written[0]) + assert.Equal(t, tc.wantState, a.written[1]) }) } } @@ -192,9 +192,9 @@ func TestPCA9501WriteGPIOErrorAtWriteDirection(t *testing.T) { // act err := d.WriteGPIO(7, 0) // assert - gobottest.Assert(t, err, wantErr) - gobottest.Assert(t, numCallsRead < 2, true) - gobottest.Assert(t, numCallsWrite, 1) + assert.Equal(t, wantErr, err) + assert.True(t, numCallsRead < 2) + assert.Equal(t, 1, numCallsWrite) } func TestPCA9501WriteGPIOErrorAtWriteValue(t *testing.T) { @@ -218,8 +218,8 @@ func TestPCA9501WriteGPIOErrorAtWriteValue(t *testing.T) { // act err := d.WriteGPIO(7, 0) // assert - gobottest.Assert(t, err, wantErr) - gobottest.Assert(t, numCallsWrite, 2) + assert.Equal(t, wantErr, err) + assert.Equal(t, 2, numCallsWrite) } func TestPCA9501ReadGPIO(t *testing.T) { @@ -254,11 +254,11 @@ func TestPCA9501ReadGPIO(t *testing.T) { // act got, err := d.ReadGPIO(pin) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], wantCtrlState) + assert.Nil(t, err) + assert.Equal(t, tc.want, got) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, wantCtrlState, a.written[0]) }) } } @@ -286,9 +286,9 @@ func TestPCA9501ReadGPIOErrorAtReadDirection(t *testing.T) { // act _, err := d.ReadGPIO(1) // assert - gobottest.Assert(t, err, wantErr) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, numCallsWrite, 0) + assert.Equal(t, wantErr, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 0, numCallsWrite) } func TestPCA9501ReadGPIOErrorAtReadValue(t *testing.T) { @@ -314,8 +314,8 @@ func TestPCA9501ReadGPIOErrorAtReadValue(t *testing.T) { // act _, err := d.ReadGPIO(2) // assert - gobottest.Assert(t, err, wantErr) - gobottest.Assert(t, numCallsWrite, 1) + assert.Equal(t, wantErr, err) + assert.Equal(t, 1, numCallsWrite) } func TestPCA9501WriteEEPROM(t *testing.T) { @@ -334,10 +334,10 @@ func TestPCA9501WriteEEPROM(t *testing.T) { // act err := d.WriteEEPROM(addressEEPROM, want) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsWrite, 1) - gobottest.Assert(t, a.written[0], addressEEPROM) - gobottest.Assert(t, a.written[1], want) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsWrite) + assert.Equal(t, addressEEPROM, a.written[0]) + assert.Equal(t, want, a.written[1]) } func TestPCA9501ReadEEPROM(t *testing.T) { @@ -363,11 +363,11 @@ func TestPCA9501ReadEEPROM(t *testing.T) { // act val, err := d.ReadEEPROM(addressEEPROM) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, val, want) - gobottest.Assert(t, numCallsWrite, 1) - gobottest.Assert(t, a.written[0], addressEEPROM) - gobottest.Assert(t, numCallsRead, 1) + assert.Nil(t, err) + assert.Equal(t, want, val) + assert.Equal(t, 1, numCallsWrite) + assert.Equal(t, addressEEPROM, a.written[0]) + assert.Equal(t, 1, numCallsRead) } func TestPCA9501ReadEEPROMErrorWhileWriteAddress(t *testing.T) { @@ -387,8 +387,8 @@ func TestPCA9501ReadEEPROMErrorWhileWriteAddress(t *testing.T) { // act _, err := d.ReadEEPROM(15) // assert - gobottest.Assert(t, err, wantErr) - gobottest.Assert(t, numCallsRead, 0) + assert.Equal(t, wantErr, err) + assert.Equal(t, 0, numCallsRead) } func TestPCA9501ReadEEPROMErrorWhileReadValue(t *testing.T) { @@ -408,8 +408,8 @@ func TestPCA9501ReadEEPROMErrorWhileReadValue(t *testing.T) { // act _, err := d.ReadEEPROM(15) // assert - gobottest.Assert(t, numCallsWrite, 1) - gobottest.Assert(t, err, wantErr) + assert.Equal(t, 1, numCallsWrite) + assert.Equal(t, wantErr, err) } func TestPCA9501_initialize(t *testing.T) { @@ -419,6 +419,6 @@ func TestPCA9501_initialize(t *testing.T) { // act err := d.initialize() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, a.address, want) + assert.Nil(t, err) + assert.Equal(t, want, a.address) } diff --git a/drivers/i2c/pca953x_driver_test.go b/drivers/i2c/pca953x_driver_test.go index 0dfd3aa64..20e944b78 100644 --- a/drivers/i2c/pca953x_driver_test.go +++ b/drivers/i2c/pca953x_driver_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -29,9 +29,9 @@ func TestNewPCA953xDriver(t *testing.T) { if !ok { t.Errorf("NewPCA953xDriver() should have returned a *PCA953xDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "PCA953x"), true) - gobottest.Assert(t, d.defaultAddress, 0x63) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "PCA953x")) + assert.Equal(t, 0x63, d.defaultAddress) } func TestPCA953xWriteGPIO(t *testing.T) { @@ -99,8 +99,8 @@ func TestPCA953xWriteGPIO(t *testing.T) { // act err := d.WriteGPIO(tc.idx, tc.val) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, a.written, tc.wantWritten) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantWritten, a.written) }) } } @@ -158,10 +158,10 @@ func TestPCA953xReadGPIO(t *testing.T) { // act got, err := d.ReadGPIO(tc.idx) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], wantReg) - gobottest.Assert(t, got, tc.want) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, wantReg, a.written[0]) + assert.Equal(t, tc.want, got) }) } } @@ -200,8 +200,8 @@ func TestPCA953xWritePeriod(t *testing.T) { // act err := d.WritePeriod(tc.idx, tc.val) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, a.written, tc.wantWritten) + assert.Nil(t, err) + assert.Equal(t, tc.wantWritten, a.written) }) } } @@ -250,9 +250,9 @@ func TestPCA953xReadPeriod(t *testing.T) { // act got, err := d.ReadPeriod(tc.idx) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, a.written, tc.wantWritten) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.want, got) + assert.Equal(t, tc.wantWritten, a.written) }) } } @@ -291,8 +291,8 @@ func TestPCA953xWriteFrequency(t *testing.T) { // act err := d.WriteFrequency(tc.idx, tc.val) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, a.written, tc.wantWritten) + assert.Nil(t, err) + assert.Equal(t, tc.wantWritten, a.written) }) } } @@ -341,9 +341,9 @@ func TestPCA953xReadFrequency(t *testing.T) { // act got, err := d.ReadFrequency(tc.idx) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, a.written, tc.wantWritten) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.want, got) + assert.Equal(t, tc.wantWritten, a.written) }) } } @@ -382,8 +382,8 @@ func TestPCA953xWriteDutyCyclePercent(t *testing.T) { // act err := d.WriteDutyCyclePercent(tc.idx, tc.val) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, a.written, tc.wantWritten) + assert.Nil(t, err) + assert.Equal(t, tc.wantWritten, a.written) }) } } @@ -432,9 +432,9 @@ func TestPCA953xReadDutyCyclePercent(t *testing.T) { // act got, err := d.ReadDutyCyclePercent(tc.idx) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, a.written, tc.wantWritten) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.want, got) + assert.Equal(t, tc.wantWritten, a.written) }) } } @@ -465,13 +465,13 @@ func TestPCA953x_readRegister(t *testing.T) { // act val, err := d.readRegister(wantRegAddress) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, numCallsWrite, 1) - gobottest.Assert(t, val, wantRegVal) - gobottest.Assert(t, readByteCount, wantReadByteCount) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(wantRegAddress)) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 1, numCallsWrite) + assert.Equal(t, wantRegVal, val) + assert.Equal(t, wantReadByteCount, readByteCount) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(wantRegAddress), a.written[0]) } func TestPCA953x_writeRegister(t *testing.T) { @@ -491,12 +491,12 @@ func TestPCA953x_writeRegister(t *testing.T) { // act err := d.writeRegister(wantRegAddress, wantRegVal) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsWrite, 1) - gobottest.Assert(t, numCallsWrite, 1) - gobottest.Assert(t, len(a.written), wantByteCount) - gobottest.Assert(t, a.written[0], uint8(wantRegAddress)) - gobottest.Assert(t, a.written[1], uint8(wantRegVal)) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsWrite) + assert.Equal(t, 1, numCallsWrite) + assert.Equal(t, wantByteCount, len(a.written)) + assert.Equal(t, uint8(wantRegAddress), a.written[0]) + assert.Equal(t, uint8(wantRegVal), a.written[1]) } func TestPCA953x_pca953xCalcPsc(t *testing.T) { @@ -517,8 +517,8 @@ func TestPCA953x_pca953xCalcPsc(t *testing.T) { // act val, err := pca953xCalcPsc(tc.period) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, val, tc.want) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.want, val) }) } } @@ -539,7 +539,7 @@ func TestPCA953x_pca953xCalcPeriod(t *testing.T) { // act val := pca953xCalcPeriod(tc.psc) // assert - gobottest.Assert(t, float32(math.Round(float64(val)*10000)/10000), tc.want) + assert.Equal(t, tc.want, float32(math.Round(float64(val)*10000)/10000)) }) } } @@ -563,8 +563,8 @@ func TestPCA953x_pca953xCalcPwm(t *testing.T) { // act val, err := pca953xCalcPwm(tc.percent) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, val, tc.want) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.want, val) }) } } @@ -585,7 +585,7 @@ func TestPCA953x_pca953xCalcDutyCyclePercent(t *testing.T) { // act val := pca953xCalcDutyCyclePercent(tc.pwm) // assert - gobottest.Assert(t, float32(math.Round(float64(val)*10)/10), tc.want) + assert.Equal(t, tc.want, float32(math.Round(float64(val)*10)/10)) }) } } diff --git a/drivers/i2c/pca9685_driver_test.go b/drivers/i2c/pca9685_driver_test.go index d77484449..ca448d447 100644 --- a/drivers/i2c/pca9685_driver_test.go +++ b/drivers/i2c/pca9685_driver_test.go @@ -5,9 +5,9 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -33,16 +33,16 @@ func TestNewPCA9685Driver(t *testing.T) { if !ok { t.Errorf("NewPCA9685Driver() should have returned a *PCA9685Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "PCA9685"), true) - gobottest.Assert(t, d.defaultAddress, 0x40) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "PCA9685")) + assert.Equal(t, 0x40, d.defaultAddress) } func TestPCA9685Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewPCA9685Driver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestPCA9685Start(t *testing.T) { @@ -52,7 +52,7 @@ func TestPCA9685Start(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestPCA9685Halt(t *testing.T) { @@ -61,8 +61,8 @@ func TestPCA9685Halt(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestPCA9685SetPWM(t *testing.T) { @@ -71,8 +71,8 @@ func TestPCA9685SetPWM(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.SetPWM(0, 0, 256), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.SetPWM(0, 0, 256)) } func TestPCA9685SetPWMError(t *testing.T) { @@ -81,11 +81,11 @@ func TestPCA9685SetPWMError(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.SetPWM(0, 0, 256), errors.New("write error")) + assert.Errorf(t, d.SetPWM(0, 0, 256), "write error") } func TestPCA9685SetPWMFreq(t *testing.T) { @@ -94,13 +94,13 @@ func TestPCA9685SetPWMFreq(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) a.i2cReadImpl = func(b []byte) (int, error) { copy(b, []byte{0x01}) return 1, nil } - gobottest.Assert(t, d.SetPWMFreq(60), nil) + assert.Nil(t, d.SetPWMFreq(60)) } func TestPCA9685SetPWMFreqReadError(t *testing.T) { @@ -109,12 +109,12 @@ func TestPCA9685SetPWMFreqReadError(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - gobottest.Assert(t, d.SetPWMFreq(60), errors.New("read error")) + assert.Errorf(t, d.SetPWMFreq(60), "read error") } func TestPCA9685SetPWMFreqWriteError(t *testing.T) { @@ -123,12 +123,12 @@ func TestPCA9685SetPWMFreqWriteError(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.SetPWMFreq(60), errors.New("write error")) + assert.Errorf(t, d.SetPWMFreq(60), "write error") } func TestPCA9685Commands(t *testing.T) { @@ -140,14 +140,14 @@ func TestPCA9685Commands(t *testing.T) { _ = d.Start() err := d.Command("PwmWrite")(map[string]interface{}{"pin": "1", "val": "1"}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = d.Command("ServoWrite")(map[string]interface{}{"pin": "1", "val": "1"}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = d.Command("SetPWM")(map[string]interface{}{"channel": "1", "on": "0", "off": "1024"}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = d.Command("SetPWMFreq")(map[string]interface{}{"freq": "60"}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } diff --git a/drivers/i2c/pcf8583_driver_test.go b/drivers/i2c/pcf8583_driver_test.go index c0a6db1d9..a772b1192 100644 --- a/drivers/i2c/pcf8583_driver_test.go +++ b/drivers/i2c/pcf8583_driver_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -26,20 +26,20 @@ func TestNewPCF8583Driver(t *testing.T) { if !ok { t.Errorf("NewPCF8583Driver() should have returned a *PCF8583Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.name, "PCF8583"), true) - gobottest.Assert(t, d.defaultAddress, 0x50) - gobottest.Assert(t, d.mode, PCF8583Control(0x00)) - gobottest.Assert(t, d.yearOffset, 0) - gobottest.Assert(t, d.ramOffset, uint8(0x10)) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.name, "PCF8583")) + assert.Equal(t, 0x50, d.defaultAddress) + assert.Equal(t, PCF8583Control(0x00), d.mode) + assert.Equal(t, 0, d.yearOffset) + assert.Equal(t, uint8(0x10), d.ramOffset) } func TestPCF8583Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewPCF8583Driver(newI2cTestAdaptor(), WithBus(2), WithPCF8583Mode(PCF8583CtrlModeClock50)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.mode, PCF8583CtrlModeClock50) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, PCF8583CtrlModeClock50, d.mode) } func TestPCF8583CommandsWriteTime(t *testing.T) { @@ -60,7 +60,7 @@ func TestPCF8583CommandsWriteTime(t *testing.T) { // act result := d.Command("WriteTime")(map[string]interface{}{"val": time.Now()}) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestPCF8583CommandsReadTime(t *testing.T) { @@ -94,8 +94,8 @@ func TestPCF8583CommandsReadTime(t *testing.T) { // act result := d.Command("ReadTime")(map[string]interface{}{}) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) - gobottest.Assert(t, result.(map[string]interface{})["val"], want) + assert.Nil(t, result.(map[string]interface{})["err"]) + assert.Equal(t, want, result.(map[string]interface{})["val"]) } func TestPCF8583CommandsWriteCounter(t *testing.T) { @@ -116,7 +116,7 @@ func TestPCF8583CommandsWriteCounter(t *testing.T) { // act result := d.Command("WriteCounter")(map[string]interface{}{"val": int32(123456)}) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestPCF8583CommandsReadCounter(t *testing.T) { @@ -145,8 +145,8 @@ func TestPCF8583CommandsReadCounter(t *testing.T) { // act result := d.Command("ReadCounter")(map[string]interface{}{}) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) - gobottest.Assert(t, result.(map[string]interface{})["val"], want) + assert.Nil(t, result.(map[string]interface{})["err"]) + assert.Equal(t, want, result.(map[string]interface{})["val"]) } func TestPCF8583CommandsWriteRAM(t *testing.T) { @@ -159,7 +159,7 @@ func TestPCF8583CommandsWriteRAM(t *testing.T) { // act result := d.Command("WriteRAM")(addressValue) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestPCF8583CommandsReadRAM(t *testing.T) { @@ -171,8 +171,8 @@ func TestPCF8583CommandsReadRAM(t *testing.T) { // act result := d.Command("ReadRAM")(address) // assert - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) - gobottest.Assert(t, result.(map[string]interface{})["val"], uint8(0)) + assert.Nil(t, result.(map[string]interface{})["err"]) + assert.Equal(t, uint8(0), result.(map[string]interface{})["val"]) } func TestPCF8583WriteTime(t *testing.T) { @@ -210,21 +210,21 @@ func TestPCF8583WriteTime(t *testing.T) { // act err := d.WriteTime(initDate) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, d.yearOffset, initDate.Year()) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 11) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, a.written[1], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, a.written[2], wantCtrlStop) - gobottest.Assert(t, a.written[3], wantReg1Val) - gobottest.Assert(t, a.written[4], wantReg2Val) - gobottest.Assert(t, a.written[5], wantReg3Val) - gobottest.Assert(t, a.written[6], wantReg4Val) - gobottest.Assert(t, a.written[7], wantReg5Val) - gobottest.Assert(t, a.written[8], wantReg6Val) - gobottest.Assert(t, a.written[9], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, a.written[10], wantCrtlStart) + assert.Nil(t, err) + assert.Equal(t, initDate.Year(), d.yearOffset) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 11, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[1]) + assert.Equal(t, wantCtrlStop, a.written[2]) + assert.Equal(t, wantReg1Val, a.written[3]) + assert.Equal(t, wantReg2Val, a.written[4]) + assert.Equal(t, wantReg3Val, a.written[5]) + assert.Equal(t, wantReg4Val, a.written[6]) + assert.Equal(t, wantReg5Val, a.written[7]) + assert.Equal(t, wantReg6Val, a.written[8]) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[9]) + assert.Equal(t, wantCrtlStart, a.written[10]) } func TestPCF8583WriteTimeNoTimeModeFails(t *testing.T) { @@ -246,11 +246,11 @@ func TestPCF8583WriteTimeNoTimeModeFails(t *testing.T) { // act err := d.WriteTime(time.Now()) // assert - gobottest.Refute(t, err, nil) - gobottest.Assert(t, strings.Contains(err.Error(), "wrong mode 0x30"), true) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, numCallsRead, 1) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "wrong mode 0x30") + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, 1, numCallsRead) } func TestPCF8583ReadTime(t *testing.T) { @@ -292,11 +292,11 @@ func TestPCF8583ReadTime(t *testing.T) { // act got, err := d.ReadTime() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, got, want) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, want, got) } func TestPCF8583ReadTimeNoTimeModeFails(t *testing.T) { @@ -318,12 +318,12 @@ func TestPCF8583ReadTimeNoTimeModeFails(t *testing.T) { // act got, err := d.ReadTime() // assert - gobottest.Refute(t, err, nil) - gobottest.Assert(t, strings.Contains(err.Error(), "wrong mode 0x20"), true) - gobottest.Assert(t, got, time.Time{}) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, numCallsRead, 1) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "wrong mode 0x20") + assert.Equal(t, time.Time{}, got) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, 1, numCallsRead) } func TestPCF8583WriteCounter(t *testing.T) { @@ -357,17 +357,17 @@ func TestPCF8583WriteCounter(t *testing.T) { // act err := d.WriteCounter(initCount) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 8) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, a.written[1], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, a.written[2], wantCtrlStop) - gobottest.Assert(t, a.written[3], wantReg1Val) - gobottest.Assert(t, a.written[4], wantReg2Val) - gobottest.Assert(t, a.written[5], wantReg3Val) - gobottest.Assert(t, a.written[6], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, a.written[7], wantCtrlStart) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 8, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[1]) + assert.Equal(t, wantCtrlStop, a.written[2]) + assert.Equal(t, wantReg1Val, a.written[3]) + assert.Equal(t, wantReg2Val, a.written[4]) + assert.Equal(t, wantReg3Val, a.written[5]) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[6]) + assert.Equal(t, wantCtrlStart, a.written[7]) } func TestPCF8583WriteCounterNoCounterModeFails(t *testing.T) { @@ -389,11 +389,11 @@ func TestPCF8583WriteCounterNoCounterModeFails(t *testing.T) { // act err := d.WriteCounter(123) // assert - gobottest.Refute(t, err, nil) - gobottest.Assert(t, strings.Contains(err.Error(), "wrong mode 0x10"), true) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, numCallsRead, 1) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "wrong mode 0x10") + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, 1, numCallsRead) } func TestPCF8583ReadCounter(t *testing.T) { @@ -430,11 +430,11 @@ func TestPCF8583ReadCounter(t *testing.T) { // act got, err := d.ReadCounter() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, got, want) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, want, got) } func TestPCF8583ReadCounterNoCounterModeFails(t *testing.T) { @@ -456,12 +456,12 @@ func TestPCF8583ReadCounterNoCounterModeFails(t *testing.T) { // act got, err := d.ReadCounter() // assert - gobottest.Refute(t, err, nil) - gobottest.Assert(t, strings.Contains(err.Error(), "wrong mode 0x30"), true) - gobottest.Assert(t, got, int32(0)) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, numCallsRead, 1) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "wrong mode 0x30") + assert.Equal(t, int32(0), got) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, 1, numCallsRead) } func TestPCF8583WriteRam(t *testing.T) { @@ -480,10 +480,10 @@ func TestPCF8583WriteRam(t *testing.T) { // act err := d.WriteRAM(wantRAMAddress-pcf8583RamOffset, wantRAMValue) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], wantRAMAddress) - gobottest.Assert(t, a.written[1], wantRAMValue) + assert.Nil(t, err) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, wantRAMAddress, a.written[0]) + assert.Equal(t, wantRAMValue, a.written[1]) } func TestPCF8583WriteRamAddressOverflowFails(t *testing.T) { @@ -493,9 +493,9 @@ func TestPCF8583WriteRamAddressOverflowFails(t *testing.T) { // act err := d.WriteRAM(uint8(0xF0), 15) // assert - gobottest.Refute(t, err, nil) - gobottest.Assert(t, strings.Contains(err.Error(), "overflow 256"), true) - gobottest.Assert(t, len(a.written), 0) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "overflow 256") + assert.Equal(t, 0, len(a.written)) } func TestPCF8583ReadRam(t *testing.T) { @@ -521,11 +521,11 @@ func TestPCF8583ReadRam(t *testing.T) { // act got, err := d.ReadRAM(wantRAMAddress - pcf8583RamOffset) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, want) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], wantRAMAddress) - gobottest.Assert(t, numCallsRead, 1) + assert.Nil(t, err) + assert.Equal(t, want, got) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, wantRAMAddress, a.written[0]) + assert.Equal(t, 1, numCallsRead) } func TestPCF8583ReadRamAddressOverflowFails(t *testing.T) { @@ -545,11 +545,11 @@ func TestPCF8583ReadRamAddressOverflowFails(t *testing.T) { // act got, err := d.ReadRAM(uint8(0xF0)) // assert - gobottest.Refute(t, err, nil) - gobottest.Assert(t, strings.Contains(err.Error(), "overflow 256"), true) - gobottest.Assert(t, got, uint8(0)) - gobottest.Assert(t, len(a.written), 0) - gobottest.Assert(t, numCallsRead, 0) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "overflow 256") + assert.Equal(t, uint8(0), got) + assert.Equal(t, 0, len(a.written)) + assert.Equal(t, 0, numCallsRead) } func TestPCF8583_initializeNoModeSwitch(t *testing.T) { @@ -572,10 +572,10 @@ func TestPCF8583_initializeNoModeSwitch(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) } func TestPCF8583_initializeWithModeSwitch(t *testing.T) { @@ -604,10 +604,10 @@ func TestPCF8583_initializeWithModeSwitch(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, numCallsRead, 1) - gobottest.Assert(t, len(a.written), 3) - gobottest.Assert(t, a.written[0], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, a.written[1], uint8(pcf8583Reg_CTRL)) - gobottest.Assert(t, a.written[2], uint8(wantReg0Val)) + assert.Nil(t, err) + assert.Equal(t, 1, numCallsRead) + assert.Equal(t, 3, len(a.written)) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) + assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[1]) + assert.Equal(t, uint8(wantReg0Val), a.written[2]) } diff --git a/drivers/i2c/pcf8591_driver_test.go b/drivers/i2c/pcf8591_driver_test.go index d00f5de68..b12032ec3 100644 --- a/drivers/i2c/pcf8591_driver_test.go +++ b/drivers/i2c/pcf8591_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -28,25 +28,25 @@ func TestNewPCF8591Driver(t *testing.T) { if !ok { t.Errorf("NewPCF8591Driver() should have returned a *PCF8591Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "PCF8591"), true) - gobottest.Assert(t, d.defaultAddress, 0x48) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "PCF8591")) + assert.Equal(t, 0x48, d.defaultAddress) } func TestPCF8591Start(t *testing.T) { d := NewPCF8591Driver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestPCF8591Halt(t *testing.T) { d := NewPCF8591Driver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestPCF8591WithPCF8591With400kbitStabilization(t *testing.T) { d := NewPCF8591Driver(newI2cTestAdaptor(), WithPCF8591With400kbitStabilization(5, 6)) - gobottest.Assert(t, d.additionalReadWrite, uint8(5)) - gobottest.Assert(t, d.additionalRead, uint8(6)) + assert.Equal(t, uint8(5), d.additionalReadWrite) + assert.Equal(t, uint8(6), d.additionalRead) } func TestPCF8591AnalogReadSingle(t *testing.T) { @@ -78,11 +78,11 @@ func TestPCF8591AnalogReadSingle(t *testing.T) { // act got, err := d.AnalogRead(description) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], ctrlByteOn) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, got, want) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, ctrlByteOn, a.written[0]) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, want, got) } func TestPCF8591AnalogReadDiff(t *testing.T) { @@ -120,11 +120,11 @@ func TestPCF8591AnalogReadDiff(t *testing.T) { // act got, err := d.AnalogRead(description) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], ctrlByteOn) - gobottest.Assert(t, numCallsRead, 2) - gobottest.Assert(t, got, want) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, ctrlByteOn, a.written[0]) + assert.Equal(t, 2, numCallsRead) + assert.Equal(t, want, got) } func TestPCF8591AnalogWrite(t *testing.T) { @@ -146,10 +146,10 @@ func TestPCF8591AnalogWrite(t *testing.T) { // act err := d.AnalogWrite("", int(want)) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], ctrlByteOn) - gobottest.Assert(t, a.written[1], want) + assert.Nil(t, err) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, ctrlByteOn, a.written[0]) + assert.Equal(t, want, a.written[1]) } func TestPCF8591AnalogOutputState(t *testing.T) { @@ -171,8 +171,8 @@ func TestPCF8591AnalogOutputState(t *testing.T) { // act err := d.AnalogOutputState(bitState == 1) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], wantCtrlByteVal) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, wantCtrlByteVal, a.written[0]) } } diff --git a/drivers/i2c/sht2x_driver_test.go b/drivers/i2c/sht2x_driver_test.go index 2578c6757..1fb630b90 100644 --- a/drivers/i2c/sht2x_driver_test.go +++ b/drivers/i2c/sht2x_driver_test.go @@ -2,12 +2,11 @@ package i2c import ( "bytes" - "errors" "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -29,26 +28,26 @@ func TestNewSHT2xDriver(t *testing.T) { if !ok { t.Errorf("NewSHT2xDriver() should have returned a *SHT2xDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "SHT2x"), true) - gobottest.Assert(t, d.defaultAddress, 0x40) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "SHT2x")) + assert.Equal(t, 0x40, d.defaultAddress) } func TestSHT2xOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". b := NewSHT2xDriver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, b.GetBusOrDefault(1), 2) + assert.Equal(t, 2, b.GetBusOrDefault(1)) } func TestSHT2xStart(t *testing.T) { d := NewSHT2xDriver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestSHT2xHalt(t *testing.T) { d, _ := initTestSHT2xDriverWithStubbedAdaptor() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestSHT2xReset(t *testing.T) { @@ -58,7 +57,7 @@ func TestSHT2xReset(t *testing.T) { } _ = d.Start() err := d.Reset() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestSHT2xMeasurements(t *testing.T) { @@ -76,11 +75,11 @@ func TestSHT2xMeasurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, temp, float32(18.809052)) + assert.Nil(t, err) + assert.Equal(t, float32(18.809052), temp) hum, err := d.Humidity() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, hum, float32(40.279907)) + assert.Nil(t, err) + assert.Equal(t, float32(40.279907), hum) } func TestSHT2xAccuracy(t *testing.T) { @@ -99,9 +98,9 @@ func TestSHT2xAccuracy(t *testing.T) { } _ = d.Start() _ = d.SetAccuracy(SHT2xAccuracyLow) - gobottest.Assert(t, d.Accuracy(), SHT2xAccuracyLow) + assert.Equal(t, SHT2xAccuracyLow, d.Accuracy()) err := d.sendAccuracy() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestSHT2xTemperatureCrcError(t *testing.T) { @@ -117,8 +116,8 @@ func TestSHT2xTemperatureCrcError(t *testing.T) { return buf.Len(), nil } temp, err := d.Temperature() - gobottest.Assert(t, err, errors.New("Invalid crc")) - gobottest.Assert(t, temp, float32(0.0)) + assert.Errorf(t, err, "Invalid crc") + assert.Equal(t, float32(0.0), temp) } func TestSHT2xHumidityCrcError(t *testing.T) { @@ -134,8 +133,8 @@ func TestSHT2xHumidityCrcError(t *testing.T) { return buf.Len(), nil } hum, err := d.Humidity() - gobottest.Assert(t, err, errors.New("Invalid crc")) - gobottest.Assert(t, hum, float32(0.0)) + assert.Errorf(t, err, "Invalid crc") + assert.Equal(t, float32(0.0), hum) } func TestSHT2xTemperatureLengthError(t *testing.T) { @@ -151,8 +150,8 @@ func TestSHT2xTemperatureLengthError(t *testing.T) { return buf.Len(), nil } temp, err := d.Temperature() - gobottest.Assert(t, err, ErrNotEnoughBytes) - gobottest.Assert(t, temp, float32(0.0)) + assert.Equal(t, ErrNotEnoughBytes, err) + assert.Equal(t, float32(0.0), temp) } func TestSHT2xHumidityLengthError(t *testing.T) { @@ -168,6 +167,6 @@ func TestSHT2xHumidityLengthError(t *testing.T) { return buf.Len(), nil } hum, err := d.Humidity() - gobottest.Assert(t, err, ErrNotEnoughBytes) - gobottest.Assert(t, hum, float32(0.0)) + assert.Equal(t, ErrNotEnoughBytes, err) + assert.Equal(t, float32(0.0), hum) } diff --git a/drivers/i2c/sht3x_driver_test.go b/drivers/i2c/sht3x_driver_test.go index 522b66b9f..15a0e64bd 100644 --- a/drivers/i2c/sht3x_driver_test.go +++ b/drivers/i2c/sht3x_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -28,26 +28,26 @@ func TestNewSHT3xDriver(t *testing.T) { if !ok { t.Errorf("NewSHT3xDriver() should have returned a *SHT3xDriver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "SHT3x"), true) - gobottest.Assert(t, d.defaultAddress, 0x44) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "SHT3x")) + assert.Equal(t, 0x44, d.defaultAddress) } func TestSHT3xOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewSHT3xDriver(newI2cTestAdaptor(), WithBus(2)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) + assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestSHT3xStart(t *testing.T) { d := NewSHT3xDriver(newI2cTestAdaptor()) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestSHT3xHalt(t *testing.T) { d, _ := initTestSHT3xDriverWithStubbedAdaptor() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestSHT3xSampleNormal(t *testing.T) { @@ -58,13 +58,13 @@ func TestSHT3xSampleNormal(t *testing.T) { } temp, rh, _ := d.Sample() - gobottest.Assert(t, temp, float32(85.523003)) - gobottest.Assert(t, rh, float32(74.5845)) + assert.Equal(t, float32(85.523003), temp) + assert.Equal(t, float32(74.5845), rh) // check the temp with the units in F d.Units = "F" temp, _, _ = d.Sample() - gobottest.Assert(t, temp, float32(185.9414)) + assert.Equal(t, float32(185.9414), temp) } func TestSHT3xSampleBadCrc(t *testing.T) { @@ -76,7 +76,7 @@ func TestSHT3xSampleBadCrc(t *testing.T) { } _, _, err := d.Sample() - gobottest.Assert(t, err, ErrInvalidCrc) + assert.Equal(t, ErrInvalidCrc, err) // Check that the 2nd crc failure is caught a.i2cReadImpl = func(b []byte) (int, error) { @@ -85,7 +85,7 @@ func TestSHT3xSampleBadCrc(t *testing.T) { } _, _, err = d.Sample() - gobottest.Assert(t, err, ErrInvalidCrc) + assert.Equal(t, ErrInvalidCrc, err) } func TestSHT3xSampleBadRead(t *testing.T) { @@ -97,7 +97,7 @@ func TestSHT3xSampleBadRead(t *testing.T) { } _, _, err := d.Sample() - gobottest.Assert(t, err, ErrNotEnoughBytes) + assert.Equal(t, ErrNotEnoughBytes, err) } func TestSHT3xSampleUnits(t *testing.T) { @@ -110,7 +110,7 @@ func TestSHT3xSampleUnits(t *testing.T) { d.Units = "K" _, _, err := d.Sample() - gobottest.Assert(t, err, ErrInvalidTemp) + assert.Equal(t, ErrInvalidTemp, err) } // Test internal sendCommandDelayGetResponse @@ -126,7 +126,7 @@ func TestSHT3xSCDGRIoFailures(t *testing.T) { } _, err := d.sendCommandDelayGetResponse(nil, nil, 2) - gobottest.Assert(t, err, ErrNotEnoughBytes) + assert.Equal(t, ErrNotEnoughBytes, err) // Don't read any bytes and return an error a.i2cReadImpl = func([]byte) (int, error) { @@ -134,7 +134,7 @@ func TestSHT3xSCDGRIoFailures(t *testing.T) { } _, err = d.sendCommandDelayGetResponse(nil, nil, 1) - gobottest.Assert(t, err, invalidRead) + assert.Equal(t, invalidRead, err) // Don't write any bytes and return an error a.i2cWriteImpl = func([]byte) (int, error) { @@ -142,7 +142,7 @@ func TestSHT3xSCDGRIoFailures(t *testing.T) { } _, err = d.sendCommandDelayGetResponse(nil, nil, 1) - gobottest.Assert(t, err, invalidWrite) + assert.Equal(t, invalidWrite, err) } // Test Heater and getStatusRegister @@ -155,8 +155,8 @@ func TestSHT3xHeater(t *testing.T) { } status, err := d.Heater() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, status, true) + assert.Nil(t, err) + assert.True(t, status) // heater disabled a.i2cReadImpl = func(b []byte) (int, error) { @@ -165,8 +165,8 @@ func TestSHT3xHeater(t *testing.T) { } status, err = d.Heater() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, status, false) + assert.Nil(t, err) + assert.False(t, status) // heater crc failed a.i2cReadImpl = func(b []byte) (int, error) { @@ -175,7 +175,7 @@ func TestSHT3xHeater(t *testing.T) { } _, err = d.Heater() - gobottest.Assert(t, err, ErrInvalidCrc) + assert.Equal(t, ErrInvalidCrc, err) // heater read failed a.i2cReadImpl = func(b []byte) (int, error) { @@ -184,7 +184,7 @@ func TestSHT3xHeater(t *testing.T) { } _, err = d.Heater() - gobottest.Refute(t, err, nil) + assert.NotNil(t, err) } func TestSHT3xSetHeater(t *testing.T) { @@ -196,18 +196,18 @@ func TestSHT3xSetHeater(t *testing.T) { func TestSHT3xSetAccuracy(t *testing.T) { d, _ := initTestSHT3xDriverWithStubbedAdaptor() - gobottest.Assert(t, d.Accuracy(), byte(SHT3xAccuracyHigh)) + assert.Equal(t, byte(SHT3xAccuracyHigh), d.Accuracy()) err := d.SetAccuracy(SHT3xAccuracyMedium) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, d.Accuracy(), byte(SHT3xAccuracyMedium)) + assert.Nil(t, err) + assert.Equal(t, byte(SHT3xAccuracyMedium), d.Accuracy()) err = d.SetAccuracy(SHT3xAccuracyLow) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, d.Accuracy(), byte(SHT3xAccuracyLow)) + assert.Nil(t, err) + assert.Equal(t, byte(SHT3xAccuracyLow), d.Accuracy()) err = d.SetAccuracy(0xff) - gobottest.Assert(t, err, ErrInvalidAccuracy) + assert.Equal(t, ErrInvalidAccuracy, err) } func TestSHT3xSerialNumber(t *testing.T) { @@ -219,6 +219,6 @@ func TestSHT3xSerialNumber(t *testing.T) { sn, err := d.SerialNumber() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, sn, uint32(0x2000beef)) + assert.Nil(t, err) + assert.Equal(t, uint32(0x2000beef), sn) } diff --git a/drivers/i2c/ssd1306_driver_test.go b/drivers/i2c/ssd1306_driver_test.go index 420446a4b..b140a9e5a 100644 --- a/drivers/i2c/ssd1306_driver_test.go +++ b/drivers/i2c/ssd1306_driver_test.go @@ -1,15 +1,14 @@ package i2c import ( - "errors" "fmt" "image" "reflect" "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -31,9 +30,9 @@ func TestNewSSD1306Driver(t *testing.T) { if !ok { t.Errorf("new should have returned a *SSD1306Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "SSD1306"), true) - gobottest.Assert(t, d.defaultAddress, 0x3c) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "SSD1306")) + assert.Equal(t, 0x3c, d.defaultAddress) } func TestSSD1306StartDefault(t *testing.T) { @@ -44,7 +43,7 @@ func TestSSD1306StartDefault(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestSSD1306Start128x32(t *testing.T) { @@ -55,7 +54,7 @@ func TestSSD1306Start128x32(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestSSD1306Start96x16(t *testing.T) { @@ -66,7 +65,7 @@ func TestSSD1306Start96x16(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestSSD1306StartExternalVCC(t *testing.T) { @@ -77,7 +76,7 @@ func TestSSD1306StartExternalVCC(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestSSD1306StartSizeError(t *testing.T) { @@ -88,35 +87,35 @@ func TestSSD1306StartSizeError(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - gobottest.Assert(t, d.Start(), errors.New("128x54 resolution is unsupported, supported resolutions: 128x64, 128x32, 96x16")) + assert.Errorf(t, d.Start(), "128x54 resolution is unsupported, supported resolutions: 128x64, 128x32, 96x16") } func TestSSD1306Halt(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) - gobottest.Assert(t, s.Halt(), nil) + assert.Nil(t, s.Halt()) } func TestSSD1306Options(t *testing.T) { s := NewSSD1306Driver(newI2cTestAdaptor(), WithBus(2), WithSSD1306DisplayHeight(32), WithSSD1306DisplayWidth(128)) - gobottest.Assert(t, s.GetBusOrDefault(1), 2) - gobottest.Assert(t, s.displayHeight, 32) - gobottest.Assert(t, s.displayWidth, 128) + assert.Equal(t, 2, s.GetBusOrDefault(1)) + assert.Equal(t, 32, s.displayHeight) + assert.Equal(t, 128, s.displayWidth) } func TestSSD1306Display(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(96, 16, false) _ = s.Start() - gobottest.Assert(t, s.Display(), nil) + assert.Nil(t, s.Display()) } func TestSSD1306ShowImage(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) _ = s.Start() img := image.NewRGBA(image.Rect(0, 0, 640, 480)) - gobottest.Assert(t, s.ShowImage(img), errors.New("image must match display width and height: 128x64")) + assert.Errorf(t, s.ShowImage(img), "image must match display width and height: 128x64") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) - gobottest.Assert(t, s.ShowImage(img), nil) + assert.Nil(t, s.ShowImage(img)) } func TestSSD1306Command(t *testing.T) { @@ -132,7 +131,7 @@ func TestSSD1306Command(t *testing.T) { return 0, nil } err := s.command(0xFF) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestSSD1306Commands(t *testing.T) { @@ -148,7 +147,7 @@ func TestSSD1306Commands(t *testing.T) { return 0, nil } err := s.commands([]byte{0x00, 0xFF}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestSSD1306On(t *testing.T) { @@ -164,7 +163,7 @@ func TestSSD1306On(t *testing.T) { return 0, nil } err := s.On() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestSSD1306Off(t *testing.T) { @@ -180,7 +179,7 @@ func TestSSD1306Off(t *testing.T) { return 0, nil } err := s.Off() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } func TestSSD1306Reset(t *testing.T) { @@ -197,7 +196,7 @@ func TestSSD1306Reset(t *testing.T) { return 0, nil } err := s.Reset() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } // COMMANDS @@ -205,28 +204,28 @@ func TestSSD1306Reset(t *testing.T) { func TestSSD1306CommandsDisplay(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) result := s.Command("Display")(map[string]interface{}{}) - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestSSD1306CommandsOn(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) result := s.Command("On")(map[string]interface{}{}) - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestSSD1306CommandsOff(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) result := s.Command("Off")(map[string]interface{}{}) - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestSSD1306CommandsClear(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) result := s.Command("Clear")(map[string]interface{}{}) - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestSSD1306CommandsSetContrast(t *testing.T) { @@ -243,19 +242,19 @@ func TestSSD1306CommandsSetContrast(t *testing.T) { result := s.Command("SetContrast")(map[string]interface{}{ "contrast": byte(0x10), }) - gobottest.Assert(t, result.(map[string]interface{})["err"], nil) + assert.Nil(t, result.(map[string]interface{})["err"]) } func TestSSD1306CommandsSet(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) - gobottest.Assert(t, s.buffer.buffer[0], byte(0)) + assert.Equal(t, byte(0), s.buffer.buffer[0]) s.Command("Set")(map[string]interface{}{ "x": int(0), "y": int(0), "c": int(1), }) - gobottest.Assert(t, s.buffer.buffer[0], byte(1)) + assert.Equal(t, byte(1), s.buffer.buffer[0]) } func TestDisplayBuffer(t *testing.T) { @@ -273,17 +272,17 @@ func TestDisplayBuffer(t *testing.T) { len(display.buffer), size) } - gobottest.Assert(t, display.buffer[0], byte(0)) - gobottest.Assert(t, display.buffer[1], byte(0)) + assert.Equal(t, byte(0), display.buffer[0]) + assert.Equal(t, byte(0), display.buffer[1]) display.SetPixel(0, 0, 1) display.SetPixel(1, 0, 1) display.SetPixel(2, 0, 1) display.SetPixel(0, 1, 1) - gobottest.Assert(t, display.buffer[0], byte(3)) - gobottest.Assert(t, display.buffer[1], byte(1)) + assert.Equal(t, byte(3), display.buffer[0]) + assert.Equal(t, byte(1), display.buffer[1]) display.SetPixel(0, 1, 0) - gobottest.Assert(t, display.buffer[0], byte(1)) - gobottest.Assert(t, display.buffer[1], byte(1)) + assert.Equal(t, byte(1), display.buffer[0]) + assert.Equal(t, byte(1), display.buffer[1]) } diff --git a/drivers/i2c/th02_driver_test.go b/drivers/i2c/th02_driver_test.go index 1276424c9..51a46c66e 100644 --- a/drivers/i2c/th02_driver_test.go +++ b/drivers/i2c/th02_driver_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -29,17 +29,17 @@ func TestNewTH02Driver(t *testing.T) { if !ok { t.Errorf("NewTH02Driver() should have returned a *NewTH02Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "TH02"), true) - gobottest.Assert(t, d.defaultAddress, 0x40) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "TH02")) + assert.Equal(t, 0x40, d.defaultAddress) } func TestTH02Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common options. // Further tests for options can also be done by call of "WithOption(val)(d)". d := NewTH02Driver(newI2cTestAdaptor(), WithBus(2), WithAddress(0x42)) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.GetAddressOrDefault(0x33), 0x42) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, 0x42, d.GetAddressOrDefault(0x33)) } func TestTH02SetAccuracy(t *testing.T) { @@ -74,7 +74,7 @@ func TestTH02WithFastMode(t *testing.T) { // act WithTH02FastMode(tc.value)(d) // assert - gobottest.Assert(t, d.fastMode, tc.want) + assert.Equal(t, tc.want, d.fastMode) }) } } @@ -102,10 +102,10 @@ func TestTH02FastMode(t *testing.T) { // act got, err := d.FastMode() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(0x03)) - gobottest.Assert(t, got, tc.want) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(0x03), a.written[0]) + assert.Equal(t, tc.want, got) }) } } @@ -130,11 +130,11 @@ func TestTH02SetHeater(t *testing.T) { // act err := d.SetHeater(tc.heater) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, d.heating, tc.heater) - gobottest.Assert(t, len(a.written), 2) - gobottest.Assert(t, a.written[0], uint8(0x03)) - gobottest.Assert(t, a.written[1], tc.want) + assert.Nil(t, err) + assert.Equal(t, tc.heater, d.heating) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, uint8(0x03), a.written[0]) + assert.Equal(t, tc.want, a.written[1]) }) } } @@ -162,10 +162,10 @@ func TestTH02Heater(t *testing.T) { // act got, err := d.Heater() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(0x03)) - gobottest.Assert(t, got, tc.want) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(0x03), a.written[0]) + assert.Equal(t, tc.want, got) }) } } @@ -186,10 +186,10 @@ func TestTH02SerialNumber(t *testing.T) { // act sn, err := d.SerialNumber() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.written), 1) - gobottest.Assert(t, a.written[0], uint8(0x11)) - gobottest.Assert(t, sn, want) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.written)) + assert.Equal(t, uint8(0x11), a.written[0]) + assert.Equal(t, want, sn) } func TestTH02Sample(t *testing.T) { @@ -289,7 +289,7 @@ func TestTH02Sample(t *testing.T) { b[0] = byte(data >> 8) // first read MSB from register 0x01 b[1] = byte(data & 0xFF) // second read LSB from register 0x02 default: - gobottest.Assert(t, fmt.Sprintf("unexpected register %d", reg), "only register 0 and 1 expected") + assert.Equal(t, "only register 0 and 1 expected", fmt.Sprintf("unexpected register %d", reg)) return 0, nil } return len(b), nil @@ -297,9 +297,9 @@ func TestTH02Sample(t *testing.T) { // act temp, rh, err := d.Sample() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, rh, float32(tc.wantRH)) - gobottest.Assert(t, temp, float32(tc.wantT)) + assert.Nil(t, err) + assert.Equal(t, float32(tc.wantRH), rh) + assert.Equal(t, float32(tc.wantT), temp) }) } } @@ -415,8 +415,8 @@ func TestTH02_readData(t *testing.T) { // act got, err := d.waitAndReadData() // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, got, tc.rtn) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.rtn, got) }) } } @@ -485,7 +485,7 @@ func TestTH02_createConfig(t *testing.T) { d.fastMode = tc.fast d.heating = tc.heating got := d.createConfig(tc.meas, tc.readTemp) - gobottest.Assert(t, tc.want, got) + assert.Equal(t, got, tc.want) }) } } diff --git a/drivers/i2c/tsl2561_driver_test.go b/drivers/i2c/tsl2561_driver_test.go index 276c484fd..2c363b997 100644 --- a/drivers/i2c/tsl2561_driver_test.go +++ b/drivers/i2c/tsl2561_driver_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver @@ -39,20 +39,20 @@ func TestNewTSL2561Driver(t *testing.T) { if !ok { t.Errorf("NewTSL2561Driver() should have returned a *TSL2561Driver") } - gobottest.Refute(t, d.Driver, nil) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "TSL2561"), true) - gobottest.Assert(t, d.defaultAddress, 0x39) - gobottest.Assert(t, d.autoGain, false) - gobottest.Assert(t, d.gain, TSL2561Gain(0)) - gobottest.Assert(t, d.integrationTime, TSL2561IntegrationTime(2)) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.Name(), "TSL2561")) + assert.Equal(t, 0x39, d.defaultAddress) + assert.False(t, d.autoGain) + assert.Equal(t, TSL2561Gain(0), d.gain) + assert.Equal(t, TSL2561IntegrationTime(2), d.integrationTime) } func TestTSL2561DriverOptions(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". d := NewTSL2561Driver(newI2cTestAdaptor(), WithBus(2), WithTSL2561AutoGain) - gobottest.Assert(t, d.GetBusOrDefault(1), 2) - gobottest.Assert(t, d.autoGain, true) + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.True(t, d.autoGain) } func TestTSL2561DriverStart(t *testing.T) { @@ -60,7 +60,7 @@ func TestTSL2561DriverStart(t *testing.T) { d := NewTSL2561Driver(a) a.i2cReadImpl = testIDReader - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestTSL2561DriverStartNotFound(t *testing.T) { @@ -72,12 +72,12 @@ func TestTSL2561DriverStartNotFound(t *testing.T) { copy(b, buf.Bytes()) return buf.Len(), nil } - gobottest.Assert(t, d.Start(), errors.New("TSL2561 device not found (0x1)")) + assert.Errorf(t, d.Start(), "TSL2561 device not found (0x1)") } func TestTSL2561DriverHalt(t *testing.T) { d, _ := initTestTSL2561Driver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestTSL2561DriverRead16(t *testing.T) { @@ -93,8 +93,8 @@ func TestTSL2561DriverRead16(t *testing.T) { return buf.Len(), nil } val, err := d.connection.ReadWordData(1) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, val, uint16(0xAEEA)) + assert.Nil(t, err) + assert.Equal(t, uint16(0xAEEA), val) } func TestTSL2561DriverValidOptions(t *testing.T) { @@ -105,9 +105,9 @@ func TestTSL2561DriverValidOptions(t *testing.T) { WithAddress(TSL2561AddressLow), WithTSL2561AutoGain) - gobottest.Refute(t, d, nil) - gobottest.Assert(t, d.autoGain, true) - gobottest.Assert(t, d.integrationTime, TSL2561IntegrationTime101MS) + assert.NotNil(t, d) + assert.True(t, d.autoGain) + assert.Equal(t, TSL2561IntegrationTime101MS, d.integrationTime) } func TestTSL2561DriverMoreOptions(t *testing.T) { @@ -118,9 +118,9 @@ func TestTSL2561DriverMoreOptions(t *testing.T) { WithAddress(TSL2561AddressLow), WithTSL2561Gain16X) - gobottest.Refute(t, d, nil) - gobottest.Assert(t, d.autoGain, false) - gobottest.Assert(t, d.gain, TSL2561Gain(TSL2561Gain16X)) + assert.NotNil(t, d) + assert.False(t, d.autoGain) + assert.Equal(t, TSL2561Gain(TSL2561Gain16X), d.gain) } func TestTSL2561DriverEvenMoreOptions(t *testing.T) { @@ -131,10 +131,10 @@ func TestTSL2561DriverEvenMoreOptions(t *testing.T) { WithAddress(TSL2561AddressLow), WithTSL2561Gain1X) - gobottest.Refute(t, d, nil) - gobottest.Assert(t, d.autoGain, false) - gobottest.Assert(t, d.gain, TSL2561Gain(TSL2561Gain1X)) - gobottest.Assert(t, d.integrationTime, TSL2561IntegrationTime13MS) + assert.NotNil(t, d) + assert.False(t, d.autoGain) + assert.Equal(t, TSL2561Gain(TSL2561Gain1X), d.gain) + assert.Equal(t, TSL2561IntegrationTime13MS, d.integrationTime) } func TestTSL2561DriverYetEvenMoreOptions(t *testing.T) { @@ -145,9 +145,9 @@ func TestTSL2561DriverYetEvenMoreOptions(t *testing.T) { WithAddress(TSL2561AddressLow), WithTSL2561AutoGain) - gobottest.Refute(t, d, nil) - gobottest.Assert(t, d.autoGain, true) - gobottest.Assert(t, d.integrationTime, TSL2561IntegrationTime402MS) + assert.NotNil(t, d) + assert.True(t, d.autoGain) + assert.Equal(t, TSL2561IntegrationTime402MS, d.integrationTime) } func TestTSL2561DriverGetDataWriteError(t *testing.T) { @@ -157,7 +157,7 @@ func TestTSL2561DriverGetDataWriteError(t *testing.T) { } _, _, err := d.getData() - gobottest.Assert(t, err, errors.New("write error")) + assert.Errorf(t, err, "write error") } func TestTSL2561DriverGetDataReadError(t *testing.T) { @@ -167,7 +167,7 @@ func TestTSL2561DriverGetDataReadError(t *testing.T) { } _, _, err := d.getData() - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } func TestTSL2561DriverGetLuminocity(t *testing.T) { @@ -180,10 +180,10 @@ func TestTSL2561DriverGetLuminocity(t *testing.T) { return buf.Len(), nil } bb, ir, err := d.GetLuminocity() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, bb, uint16(12365)) - gobottest.Assert(t, ir, uint16(12365)) - gobottest.Assert(t, d.CalculateLux(bb, ir), uint32(72)) + assert.Nil(t, err) + assert.Equal(t, uint16(12365), bb) + assert.Equal(t, uint16(12365), ir) + assert.Equal(t, uint32(72), d.CalculateLux(bb, ir)) } func TestTSL2561DriverGetLuminocityAutoGain(t *testing.T) { @@ -202,10 +202,10 @@ func TestTSL2561DriverGetLuminocityAutoGain(t *testing.T) { _ = d.Start() bb, ir, err := d.GetLuminocity() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, bb, uint16(12365)) - gobottest.Assert(t, ir, uint16(12365)) - gobottest.Assert(t, d.CalculateLux(bb, ir), uint32(72)) + assert.Nil(t, err) + assert.Equal(t, uint16(12365), bb) + assert.Equal(t, uint16(12365), ir) + assert.Equal(t, uint32(72), d.CalculateLux(bb, ir)) } func TestTSL2561SetIntegrationTimeError(t *testing.T) { @@ -213,7 +213,7 @@ func TestTSL2561SetIntegrationTimeError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.SetIntegrationTime(TSL2561IntegrationTime101MS), errors.New("write error")) + assert.Errorf(t, d.SetIntegrationTime(TSL2561IntegrationTime101MS), "write error") } func TestTSL2561SetGainError(t *testing.T) { @@ -221,7 +221,7 @@ func TestTSL2561SetGainError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - gobottest.Assert(t, d.SetGain(TSL2561Gain16X), errors.New("write error")) + assert.Errorf(t, d.SetGain(TSL2561Gain16X), "write error") } func TestTSL2561getHiLo13MS(t *testing.T) { @@ -231,8 +231,8 @@ func TestTSL2561getHiLo13MS(t *testing.T) { WithTSL2561AutoGain) hi, lo := d.getHiLo() - gobottest.Assert(t, hi, uint16(tsl2561AgcTHi13MS)) - gobottest.Assert(t, lo, uint16(tsl2561AgcTLo13MS)) + assert.Equal(t, uint16(tsl2561AgcTHi13MS), hi) + assert.Equal(t, uint16(tsl2561AgcTLo13MS), lo) } func TestTSL2561getHiLo101MS(t *testing.T) { @@ -242,8 +242,8 @@ func TestTSL2561getHiLo101MS(t *testing.T) { WithTSL2561AutoGain) hi, lo := d.getHiLo() - gobottest.Assert(t, hi, uint16(tsl2561AgcTHi101MS)) - gobottest.Assert(t, lo, uint16(tsl2561AgcTLo101MS)) + assert.Equal(t, uint16(tsl2561AgcTHi101MS), hi) + assert.Equal(t, uint16(tsl2561AgcTLo101MS), lo) } func TestTSL2561getHiLo402MS(t *testing.T) { @@ -253,8 +253,8 @@ func TestTSL2561getHiLo402MS(t *testing.T) { WithTSL2561AutoGain) hi, lo := d.getHiLo() - gobottest.Assert(t, hi, uint16(tsl2561AgcTHi402MS)) - gobottest.Assert(t, lo, uint16(tsl2561AgcTLo402MS)) + assert.Equal(t, uint16(tsl2561AgcTHi402MS), hi) + assert.Equal(t, uint16(tsl2561AgcTLo402MS), lo) } func TestTSL2561getClipScaling13MS(t *testing.T) { @@ -265,8 +265,8 @@ func TestTSL2561getClipScaling13MS(t *testing.T) { c, s := d.getClipScaling() d.waitForADC() - gobottest.Assert(t, c, uint16(tsl2561Clipping13MS)) - gobottest.Assert(t, s, uint32(tsl2561LuxCHScaleTInt0)) + assert.Equal(t, uint16(tsl2561Clipping13MS), c) + assert.Equal(t, uint32(tsl2561LuxCHScaleTInt0), s) } func TestTSL2561getClipScaling101MS(t *testing.T) { @@ -277,8 +277,8 @@ func TestTSL2561getClipScaling101MS(t *testing.T) { c, s := d.getClipScaling() d.waitForADC() - gobottest.Assert(t, c, uint16(tsl2561Clipping101MS)) - gobottest.Assert(t, s, uint32(tsl2561LuxChScaleTInt1)) + assert.Equal(t, uint16(tsl2561Clipping101MS), c) + assert.Equal(t, uint32(tsl2561LuxChScaleTInt1), s) } func TestTSL2561getClipScaling402MS(t *testing.T) { @@ -289,8 +289,8 @@ func TestTSL2561getClipScaling402MS(t *testing.T) { c, s := d.getClipScaling() d.waitForADC() - gobottest.Assert(t, c, uint16(tsl2561Clipping402MS)) - gobottest.Assert(t, s, uint32(1<>8)) + assert.Nil(t, err) + assert.Equal(t, 3, len(brd.i2cWritten)) + assert.Equal(t, reg, brd.i2cWritten[0]) + assert.Equal(t, uint8(val&0x00FF), brd.i2cWritten[1]) + assert.Equal(t, uint8(val>>8), brd.i2cWritten[2]) } func TestWriteBlockData(t *testing.T) { @@ -229,19 +228,19 @@ func TestWriteBlockData(t *testing.T) { // act err := con.WriteBlockData(reg, val) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(brd.i2cWritten), 33) - gobottest.Assert(t, brd.i2cWritten[0], reg) - gobottest.Assert(t, brd.i2cWritten[1:], val[0:32]) + assert.Nil(t, err) + assert.Equal(t, 33, len(brd.i2cWritten)) + assert.Equal(t, reg, brd.i2cWritten[0]) + assert.Equal(t, val[0:32], brd.i2cWritten[1:]) } func TestDefaultBus(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.DefaultI2cBus(), 0) + assert.Equal(t, 0, a.DefaultI2cBus()) } func TestGetI2cConnectionInvalidBus(t *testing.T) { a := NewAdaptor() _, err := a.GetI2cConnection(0x01, 99) - gobottest.Assert(t, err, errors.New("Invalid bus number 99, only 0 is supported")) + assert.Errorf(t, err, "Invalid bus number 99, only 0 is supported") } diff --git a/platforms/firmata/tcp_firmata_adaptor_test.go b/platforms/firmata/tcp_firmata_adaptor_test.go index 74b26b8df..71829d16b 100644 --- a/platforms/firmata/tcp_firmata_adaptor_test.go +++ b/platforms/firmata/tcp_firmata_adaptor_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*TCPAdaptor)(nil) @@ -17,5 +17,5 @@ func initTestTCPAdaptor() *TCPAdaptor { func TestFirmataTCPAdaptor(t *testing.T) { a := initTestTCPAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "TCPFirmata"), true) + assert.True(t, strings.HasPrefix(a.Name(), "TCPFirmata")) } diff --git a/platforms/holystone/hs200/hs200_driver_test.go b/platforms/holystone/hs200/hs200_driver_test.go index c63aedc87..42519a829 100644 --- a/platforms/holystone/hs200/hs200_driver_test.go +++ b/platforms/holystone/hs200/hs200_driver_test.go @@ -3,8 +3,8 @@ package hs200 import ( "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -12,6 +12,6 @@ var _ gobot.Driver = (*Driver)(nil) func TestHS200Driver(t *testing.T) { d := NewDriver("127.0.0.1:8080", "127.0.0.1:9090") - gobottest.Assert(t, d.tcpaddress, "127.0.0.1:8080") - gobottest.Assert(t, d.udpaddress, "127.0.0.1:9090") + assert.Equal(t, "127.0.0.1:8080", d.tcpaddress) + assert.Equal(t, "127.0.0.1:9090", d.udpaddress) } diff --git a/platforms/intel-iot/curie/imu_driver_test.go b/platforms/intel-iot/curie/imu_driver_test.go index 845604931..48723d230 100644 --- a/platforms/intel-iot/curie/imu_driver_test.go +++ b/platforms/intel-iot/curie/imu_driver_test.go @@ -2,13 +2,12 @@ package curie import ( "bytes" - "errors" "io" "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/platforms/firmata" "gobot.io/x/gobot/v2/platforms/firmata/client" @@ -89,144 +88,144 @@ func initTestIMUDriver() *IMUDriver { func TestIMUDriverStart(t *testing.T) { d := initTestIMUDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestIMUDriverHalt(t *testing.T) { d := initTestIMUDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestIMUDriverDefaultName(t *testing.T) { d := initTestIMUDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "CurieIMU"), true) + assert.True(t, strings.HasPrefix(d.Name(), "CurieIMU")) } func TestIMUDriverSetName(t *testing.T) { d := initTestIMUDriver() d.SetName("mybot") - gobottest.Assert(t, d.Name(), "mybot") + assert.Equal(t, "mybot", d.Name()) } func TestIMUDriverConnection(t *testing.T) { d := initTestIMUDriver() - gobottest.Refute(t, d.Connection(), nil) + assert.NotNil(t, d.Connection()) } func TestIMUDriverReadAccelerometer(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - gobottest.Assert(t, d.ReadAccelerometer(), nil) + assert.Nil(t, d.ReadAccelerometer()) } func TestIMUDriverReadAccelerometerData(t *testing.T) { _, err := parseAccelerometerData([]byte{}) - gobottest.Assert(t, err, errors.New("Invalid data")) + assert.Errorf(t, err, "Invalid data") result, err := parseAccelerometerData([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, result, &AccelerometerData{X: 1920, Y: 1920, Z: 1920}) + assert.Nil(t, err) + assert.Equal(t, &AccelerometerData{X: 1920, Y: 1920, Z: 1920}, result) } func TestIMUDriverReadGyroscope(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - gobottest.Assert(t, d.ReadGyroscope(), nil) + assert.Nil(t, d.ReadGyroscope()) } func TestIMUDriverReadGyroscopeData(t *testing.T) { _, err := parseGyroscopeData([]byte{}) - gobottest.Assert(t, err, errors.New("Invalid data")) + assert.Errorf(t, err, "Invalid data") result, err := parseGyroscopeData([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, result, &GyroscopeData{X: 1920, Y: 1920, Z: 1920}) + assert.Nil(t, err) + assert.Equal(t, &GyroscopeData{X: 1920, Y: 1920, Z: 1920}, result) } func TestIMUDriverReadTemperature(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - gobottest.Assert(t, d.ReadTemperature(), nil) + assert.Nil(t, d.ReadTemperature()) } func TestIMUDriverReadTemperatureData(t *testing.T) { _, err := parseTemperatureData([]byte{}) - gobottest.Assert(t, err, errors.New("Invalid data")) + assert.Errorf(t, err, "Invalid data") result, err := parseTemperatureData([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, result, float32(31.546875)) + assert.Nil(t, err) + assert.Equal(t, float32(31.546875), result) } func TestIMUDriverEnableShockDetection(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - gobottest.Assert(t, d.EnableShockDetection(true), nil) + assert.Nil(t, d.EnableShockDetection(true)) } func TestIMUDriverShockDetectData(t *testing.T) { _, err := parseShockData([]byte{}) - gobottest.Assert(t, err, errors.New("Invalid data")) + assert.Errorf(t, err, "Invalid data") result, err := parseShockData([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, result, &ShockData{Axis: 0, Direction: 2}) + assert.Nil(t, err) + assert.Equal(t, &ShockData{Axis: 0, Direction: 2}, result) } func TestIMUDriverEnableStepCounter(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - gobottest.Assert(t, d.EnableStepCounter(true), nil) + assert.Nil(t, d.EnableStepCounter(true)) } func TestIMUDriverStepCountData(t *testing.T) { _, err := parseStepData([]byte{}) - gobottest.Assert(t, err, errors.New("Invalid data")) + assert.Errorf(t, err, "Invalid data") result, err := parseStepData([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, result, int16(256)) + assert.Nil(t, err) + assert.Equal(t, int16(256), result) } func TestIMUDriverEnableTapDetection(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - gobottest.Assert(t, d.EnableTapDetection(true), nil) + assert.Nil(t, d.EnableTapDetection(true)) } func TestIMUDriverTapDetectData(t *testing.T) { _, err := parseTapData([]byte{}) - gobottest.Assert(t, err, errors.New("Invalid data")) + assert.Errorf(t, err, "Invalid data") result, err := parseTapData([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, result, &TapData{Axis: 0, Direction: 2}) + assert.Nil(t, err) + assert.Equal(t, &TapData{Axis: 0, Direction: 2}, result) } func TestIMUDriverEnableReadMotion(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - gobottest.Assert(t, d.ReadMotion(), nil) + assert.Nil(t, d.ReadMotion()) } func TestIMUDriverReadMotionData(t *testing.T) { _, err := parseMotionData([]byte{}) - gobottest.Assert(t, err, errors.New("Invalid data")) + assert.Errorf(t, err, "Invalid data") result, err := parseMotionData([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, result, &MotionData{AX: 1920, AY: 1920, AZ: 1920, GX: 1920, GY: 1920, GZ: 1920}) + assert.Nil(t, err) + assert.Equal(t, &MotionData{AX: 1920, AY: 1920, AZ: 1920, GX: 1920, GY: 1920, GZ: 1920}, result) } func TestIMUDriverHandleEvents(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - gobottest.Assert(t, d.handleEvent([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}), nil) - gobottest.Assert(t, d.handleEvent([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}), nil) - gobottest.Assert(t, d.handleEvent([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7}), nil) - gobottest.Assert(t, d.handleEvent([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7}), nil) - gobottest.Assert(t, d.handleEvent([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7}), nil) - gobottest.Assert(t, d.handleEvent([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7}), nil) - gobottest.Assert(t, d.handleEvent([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}), nil) + assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7})) + assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7})) + assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7})) + assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7})) + assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) } diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index 68baab0d7..79e557e7a 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -5,11 +5,11 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -223,17 +223,17 @@ func initTestAdaptorWithMockedFilesystem(boardType string) (*Adaptor, *system.Mo func TestName(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Edison"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Edison")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestConnect(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem("arduino") - gobottest.Assert(t, a.DefaultI2cBus(), 6) - gobottest.Assert(t, a.board, "arduino") - gobottest.Assert(t, a.Connect(), nil) + assert.Equal(t, 6, a.DefaultI2cBus()) + assert.Equal(t, "arduino", a.board) + assert.Nil(t, a.Connect()) } func TestArduinoSetupFail263(t *testing.T) { @@ -241,7 +241,7 @@ func TestArduinoSetupFail263(t *testing.T) { delete(fs.Files, "/sys/class/gpio/gpio263/direction") err := a.arduinoSetup() - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/gpio263/direction: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/gpio/gpio263/direction: no such file") } func TestArduinoSetupFail240(t *testing.T) { @@ -249,7 +249,7 @@ func TestArduinoSetupFail240(t *testing.T) { delete(fs.Files, "/sys/class/gpio/gpio240/direction") err := a.arduinoSetup() - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/gpio240/direction: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/gpio/gpio240/direction: no such file") } func TestArduinoSetupFail111(t *testing.T) { @@ -257,7 +257,7 @@ func TestArduinoSetupFail111(t *testing.T) { delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux") err := a.arduinoSetup() - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux: no such file"), true) + assert.Contains(t, err.Error(), "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux: no such file") } func TestArduinoSetupFail131(t *testing.T) { @@ -265,56 +265,56 @@ func TestArduinoSetupFail131(t *testing.T) { delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux") err := a.arduinoSetup() - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux: no such file"), true) + assert.Contains(t, err.Error(), "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux: no such file") } func TestArduinoI2CSetupFailTristate(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - gobottest.Assert(t, a.arduinoSetup(), nil) + assert.Nil(t, a.arduinoSetup()) fs.WithWriteError = true err := a.arduinoI2CSetup() - gobottest.Assert(t, err, fmt.Errorf("write error")) + assert.Errorf(t, err, "write error") } func TestArduinoI2CSetupFail14(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - gobottest.Assert(t, a.arduinoSetup(), nil) + assert.Nil(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/gpio14/direction") err := a.arduinoI2CSetup() - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/gpio14/direction: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/gpio/gpio14/direction: no such file") } func TestArduinoI2CSetupUnexportFail(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - gobottest.Assert(t, a.arduinoSetup(), nil) + assert.Nil(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/unexport") err := a.arduinoI2CSetup() - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/unexport: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/gpio/unexport: no such file") } func TestArduinoI2CSetupFail236(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - gobottest.Assert(t, a.arduinoSetup(), nil) + assert.Nil(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/gpio236/direction") err := a.arduinoI2CSetup() - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/gpio236/direction: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/gpio/gpio236/direction: no such file") } func TestArduinoI2CSetupFail28(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - gobottest.Assert(t, a.arduinoSetup(), nil) + assert.Nil(t, a.arduinoSetup()) delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux") err := a.arduinoI2CSetup() - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux: no such file"), true) + assert.Contains(t, err.Error(), "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux: no such file") } func TestConnectArduinoError(t *testing.T) { @@ -322,7 +322,7 @@ func TestConnectArduinoError(t *testing.T) { fs.WithWriteError = true err := a.Connect() - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestConnectArduinoWriteError(t *testing.T) { @@ -330,30 +330,30 @@ func TestConnectArduinoWriteError(t *testing.T) { fs.WithWriteError = true err := a.Connect() - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestConnectSparkfun(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem("sparkfun") - gobottest.Assert(t, a.Connect(), nil) - gobottest.Assert(t, a.DefaultI2cBus(), 1) - gobottest.Assert(t, a.board, "sparkfun") + assert.Nil(t, a.Connect()) + assert.Equal(t, 1, a.DefaultI2cBus()) + assert.Equal(t, "sparkfun", a.board) } func TestConnectMiniboard(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem("miniboard") - gobottest.Assert(t, a.Connect(), nil) - gobottest.Assert(t, a.DefaultI2cBus(), 1) - gobottest.Assert(t, a.board, "miniboard") + assert.Nil(t, a.Connect()) + assert.Equal(t, 1, a.DefaultI2cBus()) + assert.Equal(t, "miniboard", a.board) } func TestConnectUnknown(t *testing.T) { a := NewAdaptor("wha") err := a.Connect() - gobottest.Assert(t, strings.Contains(err.Error(), "Unknown board type: wha"), true) + assert.Contains(t, err.Error(), "Unknown board type: wha") } func TestFinalize(t *testing.T) { @@ -363,18 +363,18 @@ func TestFinalize(t *testing.T) { _ = a.PwmWrite("5", 100) _, _ = a.GetI2cConnection(0xff, 6) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) // assert that finalize after finalize is working - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) // assert that re-connect is working _ = a.Connect() // remove one file to force Finalize error delete(fs.Files, "/sys/class/gpio/unexport") err := a.Finalize() - gobottest.Assert(t, strings.Contains(err.Error(), "1 error occurred"), true) - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/unexport"), true) + assert.Contains(t, err.Error(), "1 error occurred") + assert.Contains(t, err.Error(), "/sys/class/gpio/unexport") } func TestFinalizeError(t *testing.T) { @@ -384,22 +384,22 @@ func TestFinalizeError(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - gobottest.Assert(t, strings.Contains(err.Error(), "6 errors occurred"), true) - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) - gobottest.Assert(t, strings.Contains(err.Error(), "SetEnabled(false) failed for id 1 with write error"), true) - gobottest.Assert(t, strings.Contains(err.Error(), "Unexport() failed for id 1 with write error"), true) + assert.Contains(t, err.Error(), "6 errors occurred") + assert.Contains(t, err.Error(), "write error") + assert.Contains(t, err.Error(), "SetEnabled(false) failed for id 1 with write error") + assert.Contains(t, err.Error(), "Unexport() failed for id 1 with write error") } func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") _ = a.DigitalWrite("13", 1) - gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio40/value"].Contents, "1") + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio40/value"].Contents) _ = a.DigitalWrite("2", 0) i, err := a.DigitalRead("2") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, i, 0) + assert.Nil(t, err) + assert.Equal(t, 0, i) } func TestDigitalPinInFileError(t *testing.T) { @@ -410,7 +410,7 @@ func TestDigitalPinInFileError(t *testing.T) { _ = a.Connect() _, err := a.DigitalPin("13") - gobottest.Assert(t, strings.Contains(err.Error(), "no such file"), true) + assert.Contains(t, err.Error(), "no such file") } @@ -422,7 +422,7 @@ func TestDigitalPinInResistorFileError(t *testing.T) { _ = a.Connect() _, err := a.DigitalPin("13") - gobottest.Assert(t, strings.Contains(err.Error(), "no such file"), true) + assert.Contains(t, err.Error(), "no such file") } func TestDigitalPinInLevelShifterFileError(t *testing.T) { @@ -433,7 +433,7 @@ func TestDigitalPinInLevelShifterFileError(t *testing.T) { _ = a.Connect() _, err := a.DigitalPin("13") - gobottest.Assert(t, strings.Contains(err.Error(), "no such file"), true) + assert.Contains(t, err.Error(), "no such file") } func TestDigitalPinInMuxFileError(t *testing.T) { @@ -444,7 +444,7 @@ func TestDigitalPinInMuxFileError(t *testing.T) { _ = a.Connect() _, err := a.DigitalPin("13") - gobottest.Assert(t, strings.Contains(err.Error(), "no such file"), true) + assert.Contains(t, err.Error(), "no such file") } func TestDigitalWriteError(t *testing.T) { @@ -452,7 +452,7 @@ func TestDigitalWriteError(t *testing.T) { fs.WithWriteError = true err := a.DigitalWrite("13", 1) - gobottest.Assert(t, err, fmt.Errorf("write error")) + assert.Errorf(t, err, "write error") } func TestDigitalReadWriteError(t *testing.T) { @@ -460,18 +460,18 @@ func TestDigitalReadWriteError(t *testing.T) { fs.WithWriteError = true _, err := a.DigitalRead("13") - gobottest.Assert(t, err, fmt.Errorf("write error")) + assert.Errorf(t, err, "write error") } func TestPwm(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") err := a.PwmWrite("5", 100) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm1/duty_cycle"].Contents, "1960") + assert.Nil(t, err) + assert.Equal(t, "1960", fs.Files["/sys/class/pwm/pwmchip0/pwm1/duty_cycle"].Contents) err = a.PwmWrite("7", 100) - gobottest.Assert(t, err, fmt.Errorf("'7' is not a valid id for a PWM pin")) + assert.Errorf(t, err, "'7' is not a valid id for a PWM pin") } func TestPwmExportError(t *testing.T) { @@ -479,10 +479,10 @@ func TestPwmExportError(t *testing.T) { fs := a.sys.UseMockFilesystem(pwmMockPathsMux13Arduino) delete(fs.Files, "/sys/class/pwm/pwmchip0/export") err := a.Connect() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) err = a.PwmWrite("5", 100) - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/pwm/pwmchip0/export: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/export: no such file") } func TestPwmEnableError(t *testing.T) { @@ -492,7 +492,7 @@ func TestPwmEnableError(t *testing.T) { _ = a.Connect() err := a.PwmWrite("5", 100) - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/pwm/pwmchip0/pwm1/enable: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/pwm1/enable: no such file") } func TestPwmWritePinError(t *testing.T) { @@ -500,7 +500,7 @@ func TestPwmWritePinError(t *testing.T) { fs.WithWriteError = true err := a.PwmWrite("5", 100) - gobottest.Assert(t, err, fmt.Errorf("write error")) + assert.Errorf(t, err, "write error") } func TestPwmWriteError(t *testing.T) { @@ -508,7 +508,7 @@ func TestPwmWriteError(t *testing.T) { fs.WithWriteError = true err := a.PwmWrite("5", 100) - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestPwmReadError(t *testing.T) { @@ -516,7 +516,7 @@ func TestPwmReadError(t *testing.T) { fs.WithReadError = true err := a.PwmWrite("5", 100) - gobottest.Assert(t, strings.Contains(err.Error(), "read error"), true) + assert.Contains(t, err.Error(), "read error") } func TestAnalog(t *testing.T) { @@ -524,7 +524,7 @@ func TestAnalog(t *testing.T) { fs.Files["/sys/bus/iio/devices/iio:device1/in_voltage0_raw"].Contents = "1000\n" i, _ := a.AnalogRead("0") - gobottest.Assert(t, i, 250) + assert.Equal(t, 250, i) } func TestAnalogError(t *testing.T) { @@ -532,7 +532,7 @@ func TestAnalogError(t *testing.T) { fs.WithReadError = true _, err := a.AnalogRead("0") - gobottest.Assert(t, err, fmt.Errorf("read error")) + assert.Errorf(t, err, "read error") } func TestI2cWorkflow(t *testing.T) { @@ -540,17 +540,17 @@ func TestI2cWorkflow(t *testing.T) { a.sys.UseMockSyscall() con, err := a.GetI2cConnection(0xff, 6) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = con.Write([]byte{0x00, 0x01}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) data := []byte{42, 42} _, err = con.Read(data) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, data, []byte{0x00, 0x01}) + assert.Nil(t, err) + assert.Equal(t, []byte{0x00, 0x01}, data) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -558,17 +558,17 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem(pwmMockPathsMux13ArduinoI2c) - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 6) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = con.Write([]byte{0x0A}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) fs.WithCloseError = true // act err = a.Finalize() // assert - gobottest.Refute(t, err, nil) - gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "close error") } @@ -613,7 +613,7 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateAndSetupI2cBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } diff --git a/platforms/intel-iot/joule/joule_adaptor_test.go b/platforms/intel-iot/joule/joule_adaptor_test.go index 43771dc06..316a1da0d 100644 --- a/platforms/intel-iot/joule/joule_adaptor_test.go +++ b/platforms/intel-iot/joule/joule_adaptor_test.go @@ -1,15 +1,14 @@ package joule import ( - "errors" "fmt" "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -99,9 +98,9 @@ func initTestAdaptorWithMockedFilesystem() (*Adaptor, *system.MockFilesystem) { func TestName(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Joule"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Joule")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestFinalize(t *testing.T) { @@ -110,43 +109,43 @@ func TestFinalize(t *testing.T) { _ = a.DigitalWrite("J12_1", 1) _ = a.PwmWrite("J12_26", 100) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) // assert finalize after finalize is working - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) // assert re-connect is working - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) } func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() _ = a.DigitalWrite("J12_1", 1) - gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio451/value"].Contents, "1") + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio451/value"].Contents) _ = a.DigitalWrite("J12_1", 0) i, err := a.DigitalRead("J12_1") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, i, 0) + assert.Nil(t, err) + assert.Equal(t, 0, i) _, err = a.DigitalRead("P9_99") - gobottest.Assert(t, err, errors.New("'P9_99' is not a valid id for a digital pin")) + assert.Errorf(t, err, "'P9_99' is not a valid id for a digital pin") } func TestPwm(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() err := a.PwmWrite("J12_26", 100) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "3921568") + assert.Nil(t, err) + assert.Equal(t, "3921568", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) err = a.PwmWrite("4", 100) - gobottest.Assert(t, err, errors.New("'4' is not a valid id for a pin")) + assert.Errorf(t, err, "'4' is not a valid id for a pin") err = a.PwmWrite("J12_1", 100) - gobottest.Assert(t, err, errors.New("'J12_1' is not a valid id for a PWM pin")) + assert.Errorf(t, err, "'J12_1' is not a valid id for a PWM pin") } func TestPwmPinExportError(t *testing.T) { @@ -154,7 +153,7 @@ func TestPwmPinExportError(t *testing.T) { delete(fs.Files, "/sys/class/pwm/pwmchip0/export") err := a.PwmWrite("J12_26", 100) - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/pwm/pwmchip0/export: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/export: no such file") } func TestPwmPinEnableError(t *testing.T) { @@ -162,12 +161,12 @@ func TestPwmPinEnableError(t *testing.T) { delete(fs.Files, "/sys/class/pwm/pwmchip0/pwm0/enable") err := a.PwmWrite("J12_26", 100) - gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/pwm/pwmchip0/pwm0/enable: no such file"), true) + assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/pwm0/enable: no such file") } func TestI2cDefaultBus(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.DefaultI2cBus(), 0) + assert.Equal(t, 0, a.DefaultI2cBus()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -175,16 +174,16 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-2"}) - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 2) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = con.Write([]byte{0xbf}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) fs.WithCloseError = true // act err = a.Finalize() // assert - gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true) + assert.Contains(t, err.Error(), "close error") } func Test_validateI2cBusNumber(t *testing.T) { @@ -217,7 +216,7 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateI2cBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } diff --git a/platforms/jetson/jetson_adaptor_test.go b/platforms/jetson/jetson_adaptor_test.go index cc44db01a..a7529f16f 100644 --- a/platforms/jetson/jetson_adaptor_test.go +++ b/platforms/jetson/jetson_adaptor_test.go @@ -1,7 +1,6 @@ package jetson import ( - "errors" "fmt" "strings" "testing" @@ -10,11 +9,11 @@ import ( "strconv" "sync" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/drivers/spi" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -39,10 +38,10 @@ func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system. func TestNewAdaptor(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "JetsonNano"), true) + assert.True(t, strings.HasPrefix(a.Name(), "JetsonNano")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestFinalize(t *testing.T) { @@ -59,20 +58,20 @@ func TestFinalize(t *testing.T) { _ = a.DigitalWrite("3", 1) _, _ = a.GetI2cConnection(0xff, 0) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } func TestPWMPinsConnect(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.pwmPins, (map[string]gobot.PWMPinner)(nil)) + assert.Equal(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) err := a.PwmWrite("33", 1) - gobottest.Assert(t, err.Error(), "not connected") + assert.Errorf(t, err, "not connected") err = a.Connect() - gobottest.Assert(t, err, nil) - gobottest.Refute(t, a.pwmPins, (map[string]gobot.PWMPinner)(nil)) - gobottest.Assert(t, len(a.pwmPins), 0) + assert.Nil(t, err) + assert.NotEqual(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) + assert.Equal(t, 0, len(a.pwmPins)) } func TestPWMPinsReConnect(t *testing.T) { @@ -85,15 +84,15 @@ func TestPWMPinsReConnect(t *testing.T) { "/sys/class/pwm/pwmchip0/pwm2/enable", } a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) - gobottest.Assert(t, len(a.pwmPins), 0) - gobottest.Assert(t, a.PwmWrite("33", 1), nil) - gobottest.Assert(t, len(a.pwmPins), 1) - gobottest.Assert(t, a.Finalize(), nil) + assert.Equal(t, 0, len(a.pwmPins)) + assert.Nil(t, a.PwmWrite("33", 1)) + assert.Equal(t, 1, len(a.pwmPins)) + assert.Nil(t, a.Finalize()) // act err := a.Connect() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.pwmPins), 0) + assert.Nil(t, err) + assert.Equal(t, 0, len(a.pwmPins)) } func TestDigitalIO(t *testing.T) { @@ -108,17 +107,17 @@ func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) err := a.DigitalWrite("7", 1) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio216/value"].Contents, "1") + assert.Nil(t, err) + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio216/value"].Contents) err = a.DigitalWrite("13", 1) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) i, err := a.DigitalRead("13") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, i, 1) + assert.Nil(t, err) + assert.Equal(t, 1, i) - gobottest.Assert(t, a.DigitalWrite("notexist", 1), errors.New("'notexist' is not a valid id for a digital pin")) - gobottest.Assert(t, a.Finalize(), nil) + assert.Errorf(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid id for a digital pin") + assert.Nil(t, a.Finalize()) } func TestDigitalPinConcurrency(t *testing.T) { @@ -147,15 +146,15 @@ func TestDigitalPinConcurrency(t *testing.T) { func TestSpiDefaultValues(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.SpiDefaultBusNumber(), 0) - gobottest.Assert(t, a.SpiDefaultChipNumber(), 0) - gobottest.Assert(t, a.SpiDefaultMode(), 0) - gobottest.Assert(t, a.SpiDefaultMaxSpeed(), int64(10000000)) + assert.Equal(t, 0, a.SpiDefaultBusNumber()) + assert.Equal(t, 0, a.SpiDefaultChipNumber()) + assert.Equal(t, 0, a.SpiDefaultMode()) + assert.Equal(t, int64(10000000), a.SpiDefaultMaxSpeed()) } func TestI2cDefaultBus(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.DefaultI2cBus(), 1) + assert.Equal(t, 1, a.DefaultI2cBus()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -163,16 +162,16 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = con.Write([]byte{0xbf}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) fs.WithCloseError = true // act err = a.Finalize() // assert - gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true) + assert.Contains(t, err.Error(), "close error") } func Test_validateSpiBusNumber(t *testing.T) { @@ -202,7 +201,7 @@ func Test_validateSpiBusNumber(t *testing.T) { // act err := a.validateSpiBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } @@ -234,7 +233,7 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateI2cBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } diff --git a/platforms/jetson/pwm_pin_test.go b/platforms/jetson/pwm_pin_test.go index a67e58e5f..1c9cede1e 100644 --- a/platforms/jetson/pwm_pin_test.go +++ b/platforms/jetson/pwm_pin_test.go @@ -1,11 +1,10 @@ package jetson import ( - "errors" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -23,33 +22,33 @@ func TestPwmPin(t *testing.T) { a.UseMockFilesystem(mockPaths) pin := NewPWMPin(a, "/sys/class/pwm/pwmchip0", "0") - gobottest.Assert(t, pin.Export(), nil) - gobottest.Assert(t, pin.SetEnabled(true), nil) + assert.Nil(t, pin.Export()) + assert.Nil(t, pin.SetEnabled(true)) val, _ := pin.Polarity() - gobottest.Assert(t, val, true) - gobottest.Assert(t, pin.SetPolarity(false), nil) + assert.True(t, val) + assert.Nil(t, pin.SetPolarity(false)) val, _ = pin.Polarity() - gobottest.Assert(t, val, true) + assert.True(t, val) _, err := pin.Period() - gobottest.Assert(t, err, errors.New("Jetson PWM pin period not set")) - gobottest.Assert(t, pin.SetDutyCycle(10000), errors.New("Jetson PWM pin period not set")) + assert.Errorf(t, err, "Jetson PWM pin period not set") + assert.Errorf(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") - gobottest.Assert(t, pin.SetPeriod(20000000), nil) + assert.Nil(t, pin.SetPeriod(20000000)) period, _ := pin.Period() - gobottest.Assert(t, period, uint32(20000000)) - gobottest.Assert(t, pin.SetPeriod(10000000), errors.New("Cannot set the period of individual PWM pins on Jetson")) + assert.Equal(t, uint32(20000000), period) + assert.Errorf(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") dc, _ := pin.DutyCycle() - gobottest.Assert(t, dc, uint32(0)) + assert.Equal(t, uint32(0), dc) - gobottest.Assert(t, pin.SetDutyCycle(10000), nil) + assert.Nil(t, pin.SetDutyCycle(10000)) dc, _ = pin.DutyCycle() - gobottest.Assert(t, dc, uint32(10000)) + assert.Equal(t, uint32(10000), dc) - gobottest.Assert(t, pin.SetDutyCycle(999999999), errors.New("Duty cycle exceeds period")) + assert.Errorf(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") dc, _ = pin.DutyCycle() - gobottest.Assert(t, dc, uint32(10000)) + assert.Equal(t, uint32(10000), dc) - gobottest.Assert(t, pin.Unexport(), nil) + assert.Nil(t, pin.Unexport()) } diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index 334120584..0c581d4de 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -219,5 +219,5 @@ func TestDriverHandleEventDS4(t *testing.T) { func TestDriverInvalidConfig(t *testing.T) { d, _ := initTestDriver("./configs/doesnotexist") err := d.Start() - assert.True(t, strings.Contains(err.Error(), "loadfile error")) + assert.Contains(t, err.Error(), "loadfile error") } diff --git a/platforms/keyboard/keyboard_driver_test.go b/platforms/keyboard/keyboard_driver_test.go index 9ebb6147c..75327c42d 100644 --- a/platforms/keyboard/keyboard_driver_test.go +++ b/platforms/keyboard/keyboard_driver_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -23,22 +23,22 @@ func initTestKeyboardDriver() *Driver { func TestKeyboardDriver(t *testing.T) { d := initTestKeyboardDriver() - gobottest.Assert(t, d.Connection(), (gobot.Connection)(nil)) + assert.Equal(t, (gobot.Connection)(nil), d.Connection()) } func TestKeyboardDriverName(t *testing.T) { d := initTestKeyboardDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Keyboard"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Keyboard")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestKeyboardDriverStart(t *testing.T) { d := initTestKeyboardDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestKeyboardDriverHalt(t *testing.T) { d := initTestKeyboardDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } diff --git a/platforms/keyboard/keyboard_test.go b/platforms/keyboard/keyboard_test.go index a8275895d..0ce7f0ed8 100644 --- a/platforms/keyboard/keyboard_test.go +++ b/platforms/keyboard/keyboard_test.go @@ -3,65 +3,65 @@ package keyboard import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestParseSpace(t *testing.T) { - gobottest.Assert(t, Parse(bytes{32, 0, 0}).Key, Spacebar) + assert.Equal(t, Spacebar, Parse(bytes{32, 0, 0}).Key) } func TestParseEscape(t *testing.T) { - gobottest.Assert(t, Parse(bytes{27, 0, 0}).Key, Escape) + assert.Equal(t, Escape, Parse(bytes{27, 0, 0}).Key) } func TestParseHyphen(t *testing.T) { - gobottest.Assert(t, Parse(bytes{45, 0, 0}).Key, Hyphen) + assert.Equal(t, Hyphen, Parse(bytes{45, 0, 0}).Key) } func TestParseAsterisk(t *testing.T) { - gobottest.Assert(t, Parse(bytes{42, 0, 0}).Key, Asterisk) + assert.Equal(t, Asterisk, Parse(bytes{42, 0, 0}).Key) } func TestParsePlus(t *testing.T) { - gobottest.Assert(t, Parse(bytes{43, 0, 0}).Key, Plus) + assert.Equal(t, Plus, Parse(bytes{43, 0, 0}).Key) } func TestParseSlash(t *testing.T) { - gobottest.Assert(t, Parse(bytes{47, 0, 0}).Key, Slash) + assert.Equal(t, Slash, Parse(bytes{47, 0, 0}).Key) } func TestParseDot(t *testing.T) { - gobottest.Assert(t, Parse(bytes{46, 0, 0}).Key, Dot) + assert.Equal(t, Dot, Parse(bytes{46, 0, 0}).Key) } func TestParseNotEscape(t *testing.T) { - gobottest.Refute(t, Parse(bytes{27, 91, 65}).Key, Escape) + assert.NotEqual(t, Escape, Parse(bytes{27, 91, 65}).Key) } func TestParseNumberKeys(t *testing.T) { - gobottest.Assert(t, Parse(bytes{48, 0, 0}).Key, 48) - gobottest.Assert(t, Parse(bytes{50, 0, 0}).Key, 50) - gobottest.Assert(t, Parse(bytes{57, 0, 0}).Key, 57) + assert.Equal(t, 48, Parse(bytes{48, 0, 0}).Key) + assert.Equal(t, 50, Parse(bytes{50, 0, 0}).Key) + assert.Equal(t, 57, Parse(bytes{57, 0, 0}).Key) } func TestParseAlphaKeys(t *testing.T) { - gobottest.Assert(t, Parse(bytes{97, 0, 0}).Key, 97) - gobottest.Assert(t, Parse(bytes{101, 0, 0}).Key, 101) - gobottest.Assert(t, Parse(bytes{122, 0, 0}).Key, 122) + assert.Equal(t, 97, Parse(bytes{97, 0, 0}).Key) + assert.Equal(t, 101, Parse(bytes{101, 0, 0}).Key) + assert.Equal(t, 122, Parse(bytes{122, 0, 0}).Key) } func TestParseNotAlphaKeys(t *testing.T) { - gobottest.Refute(t, Parse(bytes{132, 0, 0}).Key, 132) + assert.NotEqual(t, 132, Parse(bytes{132, 0, 0}).Key) } func TestParseArrowKeys(t *testing.T) { - gobottest.Assert(t, Parse(bytes{27, 91, 65}).Key, 65) - gobottest.Assert(t, Parse(bytes{27, 91, 66}).Key, 66) - gobottest.Assert(t, Parse(bytes{27, 91, 67}).Key, 67) - gobottest.Assert(t, Parse(bytes{27, 91, 68}).Key, 68) + assert.Equal(t, 65, Parse(bytes{27, 91, 65}).Key) + assert.Equal(t, 66, Parse(bytes{27, 91, 66}).Key) + assert.Equal(t, 67, Parse(bytes{27, 91, 67}).Key) + assert.Equal(t, 68, Parse(bytes{27, 91, 68}).Key) } func TestParseNotArrowKeys(t *testing.T) { - gobottest.Refute(t, Parse(bytes{27, 91, 65}).Key, Escape) - gobottest.Refute(t, Parse(bytes{27, 91, 70}).Key, 70) + assert.NotEqual(t, Escape, Parse(bytes{27, 91, 65}).Key) + assert.NotEqual(t, 70, Parse(bytes{27, 91, 70}).Key) } diff --git a/platforms/leap/leap_motion_adaptor_test.go b/platforms/leap/leap_motion_adaptor_test.go index bcc6449f4..0b4ef1c9e 100644 --- a/platforms/leap/leap_motion_adaptor_test.go +++ b/platforms/leap/leap_motion_adaptor_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -20,27 +20,27 @@ func initTestLeapMotionAdaptor() *Adaptor { func TestLeapMotionAdaptor(t *testing.T) { a := NewAdaptor("127.0.0.1") - gobottest.Assert(t, a.Port(), "127.0.0.1") + assert.Equal(t, "127.0.0.1", a.Port()) } func TestLeapMotionAdaptorName(t *testing.T) { a := NewAdaptor("127.0.0.1") - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Leap"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Leap")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestLeapMotionAdaptorConnect(t *testing.T) { a := initTestLeapMotionAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") } - gobottest.Assert(t, a.Connect(), errors.New("connection error")) + assert.Errorf(t, a.Connect(), "connection error") } func TestLeapMotionAdaptorFinalize(t *testing.T) { a := initTestLeapMotionAdaptor() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } diff --git a/platforms/leap/leap_motion_driver_test.go b/platforms/leap/leap_motion_driver_test.go index 73dc0cd8c..735ad8e4a 100644 --- a/platforms/leap/leap_motion_driver_test.go +++ b/platforms/leap/leap_motion_driver_test.go @@ -8,8 +8,8 @@ import ( "sync" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -55,29 +55,29 @@ func initTestLeapMotionDriver() (*Driver, *NullReadWriteCloser) { func TestLeapMotionDriver(t *testing.T) { d, _ := initTestLeapMotionDriver() - gobottest.Refute(t, d.Connection(), nil) + assert.NotNil(t, d.Connection()) } func TestLeapMotionDriverName(t *testing.T) { d, _ := initTestLeapMotionDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Leap"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Leap")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestLeapMotionDriverStart(t *testing.T) { d, _ := initTestLeapMotionDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) d2, rwc := initTestLeapMotionDriver() e := errors.New("write error") rwc.WriteError(e) - gobottest.Assert(t, d2.Start(), e) + assert.Equal(t, e, d2.Start()) } func TestLeapMotionDriverHalt(t *testing.T) { d, _ := initTestLeapMotionDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestLeapMotionDriverParser(t *testing.T) { @@ -89,18 +89,18 @@ func TestLeapMotionDriverParser(t *testing.T) { t.Errorf("ParseFrame incorrectly parsed frame") } - gobottest.Assert(t, parsedFrame.Timestamp, uint64(134211791358)) - gobottest.Assert(t, parsedFrame.Hands[0].X(), 247.410) - gobottest.Assert(t, parsedFrame.Hands[0].Y(), 275.868) - gobottest.Assert(t, parsedFrame.Hands[0].Z(), 132.843) + assert.Equal(t, uint64(134211791358), parsedFrame.Timestamp) + assert.Equal(t, 247.410, parsedFrame.Hands[0].X()) + assert.Equal(t, 275.868, parsedFrame.Hands[0].Y()) + assert.Equal(t, 132.843, parsedFrame.Hands[0].Z()) - gobottest.Assert(t, parsedFrame.Pointables[0].BTipPosition[0], 214.293) - gobottest.Assert(t, parsedFrame.Pointables[0].BTipPosition[1], 213.865) - gobottest.Assert(t, parsedFrame.Pointables[0].BTipPosition[2], 95.0224) + assert.Equal(t, 214.293, parsedFrame.Pointables[0].BTipPosition[0]) + assert.Equal(t, 213.865, parsedFrame.Pointables[0].BTipPosition[1]) + assert.Equal(t, 95.0224, parsedFrame.Pointables[0].BTipPosition[2]) - gobottest.Assert(t, parsedFrame.Pointables[0].Bases[0][0][0], -0.468069) - gobottest.Assert(t, parsedFrame.Pointables[0].Bases[0][0][1], 0.807844) - gobottest.Assert(t, parsedFrame.Pointables[0].Bases[0][0][2], -0.358190) + assert.Equal(t, -0.468069, parsedFrame.Pointables[0].Bases[0][0][0]) + assert.Equal(t, 0.807844, parsedFrame.Pointables[0].Bases[0][0][1]) + assert.Equal(t, -0.358190, parsedFrame.Pointables[0].Bases[0][0][2]) - gobottest.Assert(t, parsedFrame.Pointables[0].Width, 19.7871) + assert.Equal(t, 19.7871, parsedFrame.Pointables[0].Width) } diff --git a/platforms/mavlink/mavlink_adaptor_test.go b/platforms/mavlink/mavlink_adaptor_test.go index edc484a27..91408b295 100644 --- a/platforms/mavlink/mavlink_adaptor_test.go +++ b/platforms/mavlink/mavlink_adaptor_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -54,30 +54,30 @@ func initTestMavlinkAdaptor() *Adaptor { func TestMavlinkAdaptor(t *testing.T) { a := initTestMavlinkAdaptor() - gobottest.Assert(t, a.Port(), "/dev/null") + assert.Equal(t, "/dev/null", a.Port()) } func TestMavlinkAdaptorName(t *testing.T) { a := initTestMavlinkAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Mavlink"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Mavlink")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestMavlinkAdaptorConnect(t *testing.T) { a := initTestMavlinkAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - gobottest.Assert(t, a.Connect(), errors.New("connect error")) + assert.Errorf(t, a.Connect(), "connect error") } func TestMavlinkAdaptorFinalize(t *testing.T) { a := initTestMavlinkAdaptor() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) testAdaptorClose = func() error { return errors.New("close error") } - gobottest.Assert(t, a.Finalize(), errors.New("close error")) + assert.Errorf(t, a.Finalize(), "close error") } diff --git a/platforms/mavlink/mavlink_driver_test.go b/platforms/mavlink/mavlink_driver_test.go index 4ac9c5cb4..fd7e628c3 100644 --- a/platforms/mavlink/mavlink_driver_test.go +++ b/platforms/mavlink/mavlink_driver_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" common "gobot.io/x/gobot/v2/platforms/mavlink/common" ) @@ -26,18 +26,18 @@ func TestMavlinkDriver(t *testing.T) { m.connect = func(port string) (io.ReadWriteCloser, error) { return nil, nil } d := NewDriver(m) - gobottest.Refute(t, d.Connection(), nil) - gobottest.Assert(t, d.interval, 10*time.Millisecond) + assert.NotNil(t, d.Connection()) + assert.Equal(t, 10*time.Millisecond, d.interval) d = NewDriver(m, 100*time.Millisecond) - gobottest.Assert(t, d.interval, 100*time.Millisecond) + assert.Equal(t, 100*time.Millisecond, d.interval) } func TestMavlinkDriverName(t *testing.T) { d := initTestMavlinkDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Mavlink"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Mavlink")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestMavlinkDriverStart(t *testing.T) { @@ -59,11 +59,11 @@ func TestMavlinkDriverStart(t *testing.T) { err <- data.(error) }) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) select { case p := <-packet: - gobottest.Assert(t, d.SendPacket(p), nil) + assert.Nil(t, d.SendPacket(p)) case <-time.After(100 * time.Millisecond): t.Errorf("packet was not emitted") @@ -82,5 +82,5 @@ func TestMavlinkDriverStart(t *testing.T) { func TestMavlinkDriverHalt(t *testing.T) { d := initTestMavlinkDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } diff --git a/platforms/mavlink/mavlink_udp_adaptor_test.go b/platforms/mavlink/mavlink_udp_adaptor_test.go index 5e9f1dd00..0bec533c8 100644 --- a/platforms/mavlink/mavlink_udp_adaptor_test.go +++ b/platforms/mavlink/mavlink_udp_adaptor_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" mavlink "gobot.io/x/gobot/v2/platforms/mavlink/common" ) @@ -53,20 +53,20 @@ func initTestMavlinkUDPAdaptor() *UDPAdaptor { func TestMavlinkUDPAdaptor(t *testing.T) { a := initTestMavlinkUDPAdaptor() - gobottest.Assert(t, a.Port(), ":14550") + assert.Equal(t, ":14550", a.Port()) } func TestMavlinkUDPAdaptorName(t *testing.T) { a := initTestMavlinkUDPAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Mavlink"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Mavlink")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestMavlinkUDPAdaptorConnectAndFinalize(t *testing.T) { a := initTestMavlinkUDPAdaptor() - gobottest.Assert(t, a.Connect(), nil) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Connect()) + assert.Nil(t, a.Finalize()) } func TestMavlinkUDPAdaptorWrite(t *testing.T) { @@ -81,8 +81,8 @@ func TestMavlinkUDPAdaptorWrite(t *testing.T) { a.sock = m i, err := a.Write([]byte{0x01, 0x02, 0x03}) - gobottest.Assert(t, i, 3) - gobottest.Assert(t, err, nil) + assert.Equal(t, 3, i) + assert.Nil(t, err) } func TestMavlinkReadMAVLinkReadDefaultPacket(t *testing.T) { @@ -101,7 +101,7 @@ func TestMavlinkReadMAVLinkReadDefaultPacket(t *testing.T) { a.sock = m p, _ := a.ReadMAVLinkPacket() - gobottest.Assert(t, p.Protocol, uint8(254)) + assert.Equal(t, uint8(254), p.Protocol) } func TestMavlinkReadMAVLinkPacketReadError(t *testing.T) { @@ -136,5 +136,5 @@ func TestMavlinkReadMAVLinkPacketReadError(t *testing.T) { a.sock = m _, err := a.ReadMAVLinkPacket() - gobottest.Assert(t, err, errors.New("read error")) + assert.Errorf(t, err, "read error") } diff --git a/platforms/microbit/accelerometer_driver_test.go b/platforms/microbit/accelerometer_driver_test.go index 7e1786c11..538cff44c 100644 --- a/platforms/microbit/accelerometer_driver_test.go +++ b/platforms/microbit/accelerometer_driver_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*AccelerometerDriver)(nil) @@ -18,15 +18,15 @@ func initTestAccelerometerDriver() *AccelerometerDriver { func TestAccelerometerDriver(t *testing.T) { d := initTestAccelerometerDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit Accelerometer"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Microbit Accelerometer")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestAccelerometerDriverStartAndHalt(t *testing.T) { d := initTestAccelerometerDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestAccelerometerDriverReadData(t *testing.T) { @@ -35,9 +35,9 @@ func TestAccelerometerDriverReadData(t *testing.T) { d := NewAccelerometerDriver(a) _ = d.Start() _ = d.On(Accelerometer, func(data interface{}) { - gobottest.Assert(t, data.(*AccelerometerData).X, float32(8.738)) - gobottest.Assert(t, data.(*AccelerometerData).Y, float32(8.995)) - gobottest.Assert(t, data.(*AccelerometerData).Z, float32(9.252)) + assert.Equal(t, float32(8.738), data.(*AccelerometerData).X) + assert.Equal(t, float32(8.995), data.(*AccelerometerData).Y) + assert.Equal(t, float32(9.252), data.(*AccelerometerData).Z) sem <- true }) diff --git a/platforms/microbit/button_driver_test.go b/platforms/microbit/button_driver_test.go index 007f3881c..adde9c703 100644 --- a/platforms/microbit/button_driver_test.go +++ b/platforms/microbit/button_driver_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*ButtonDriver)(nil) @@ -18,15 +18,15 @@ func initTestButtonDriver() *ButtonDriver { func TestButtonDriver(t *testing.T) { d := initTestButtonDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit Button"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Microbit Button")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestButtonDriverStartAndHalt(t *testing.T) { d := initTestButtonDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestButtonDriverReadData(t *testing.T) { diff --git a/platforms/microbit/io_pin_driver_test.go b/platforms/microbit/io_pin_driver_test.go index ceda71d95..ace606c7d 100644 --- a/platforms/microbit/io_pin_driver_test.go +++ b/platforms/microbit/io_pin_driver_test.go @@ -5,10 +5,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/gobottest" ) // the IOPinDriver is a Driver @@ -26,9 +26,9 @@ func initTestIOPinDriver() *IOPinDriver { func TestIOPinDriver(t *testing.T) { d := initTestIOPinDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit IO Pin"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Microbit IO Pin")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestIOPinDriverStartAndHalt(t *testing.T) { @@ -37,8 +37,8 @@ func TestIOPinDriverStartAndHalt(t *testing.T) { a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { return []byte{0, 1, 1, 0}, nil }) - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestIOPinDriverStartError(t *testing.T) { @@ -47,7 +47,7 @@ func TestIOPinDriverStartError(t *testing.T) { a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { return nil, errors.New("read error") }) - gobottest.Assert(t, d.Start(), errors.New("read error")) + assert.Errorf(t, d.Start(), "read error") } func TestIOPinDriverDigitalRead(t *testing.T) { @@ -58,10 +58,10 @@ func TestIOPinDriverDigitalRead(t *testing.T) { }) val, _ := d.DigitalRead("0") - gobottest.Assert(t, val, 1) + assert.Equal(t, 1, val) val, _ = d.DigitalRead("1") - gobottest.Assert(t, val, 0) + assert.Equal(t, 0, val) } func TestIOPinDriverDigitalReadInvalidPin(t *testing.T) { @@ -69,10 +69,10 @@ func TestIOPinDriverDigitalReadInvalidPin(t *testing.T) { d := NewIOPinDriver(a) _, err := d.DigitalRead("A3") - gobottest.Refute(t, err, nil) + assert.NotNil(t, err) _, err = d.DigitalRead("6") - gobottest.Assert(t, err, errors.New("Invalid pin.")) + assert.Errorf(t, err, "Invalid pin.") } func TestIOPinDriverDigitalWrite(t *testing.T) { @@ -80,15 +80,15 @@ func TestIOPinDriverDigitalWrite(t *testing.T) { d := NewIOPinDriver(a) // TODO: a better test - gobottest.Assert(t, d.DigitalWrite("0", 1), nil) + assert.Nil(t, d.DigitalWrite("0", 1)) } func TestIOPinDriverDigitalWriteInvalidPin(t *testing.T) { a := NewBleTestAdaptor() d := NewIOPinDriver(a) - gobottest.Refute(t, d.DigitalWrite("A3", 1), nil) - gobottest.Assert(t, d.DigitalWrite("6", 1), errors.New("Invalid pin.")) + assert.NotNil(t, d.DigitalWrite("A3", 1)) + assert.Errorf(t, d.DigitalWrite("6", 1), "Invalid pin.") } func TestIOPinDriverAnalogRead(t *testing.T) { @@ -99,10 +99,10 @@ func TestIOPinDriverAnalogRead(t *testing.T) { }) val, _ := d.AnalogRead("0") - gobottest.Assert(t, val, 0) + assert.Equal(t, 0, val) val, _ = d.AnalogRead("1") - gobottest.Assert(t, val, 128) + assert.Equal(t, 128, val) } func TestIOPinDriverAnalogReadInvalidPin(t *testing.T) { @@ -110,10 +110,10 @@ func TestIOPinDriverAnalogReadInvalidPin(t *testing.T) { d := NewIOPinDriver(a) _, err := d.AnalogRead("A3") - gobottest.Refute(t, err, nil) + assert.NotNil(t, err) _, err = d.AnalogRead("6") - gobottest.Assert(t, err, errors.New("Invalid pin.")) + assert.Errorf(t, err, "Invalid pin.") } func TestIOPinDriverDigitalAnalogRead(t *testing.T) { @@ -124,10 +124,10 @@ func TestIOPinDriverDigitalAnalogRead(t *testing.T) { }) val, _ := d.DigitalRead("0") - gobottest.Assert(t, val, 0) + assert.Equal(t, 0, val) val, _ = d.AnalogRead("0") - gobottest.Assert(t, val, 0) + assert.Equal(t, 0, val) } func TestIOPinDriverDigitalWriteAnalogRead(t *testing.T) { @@ -137,10 +137,10 @@ func TestIOPinDriverDigitalWriteAnalogRead(t *testing.T) { return []byte{0, 0, 1, 128, 2, 1}, nil }) - gobottest.Assert(t, d.DigitalWrite("1", 0), nil) + assert.Nil(t, d.DigitalWrite("1", 0)) val, _ := d.AnalogRead("1") - gobottest.Assert(t, val, 128) + assert.Equal(t, 128, val) } func TestIOPinDriverAnalogReadDigitalWrite(t *testing.T) { @@ -151,7 +151,7 @@ func TestIOPinDriverAnalogReadDigitalWrite(t *testing.T) { }) val, _ := d.AnalogRead("1") - gobottest.Assert(t, val, 128) + assert.Equal(t, 128, val) - gobottest.Assert(t, d.DigitalWrite("1", 0), nil) + assert.Nil(t, d.DigitalWrite("1", 0)) } diff --git a/platforms/microbit/led_driver_test.go b/platforms/microbit/led_driver_test.go index 9d4003c20..fb24f147b 100644 --- a/platforms/microbit/led_driver_test.go +++ b/platforms/microbit/led_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*LEDDriver)(nil) @@ -17,39 +17,39 @@ func initTestLEDDriver() *LEDDriver { func TestLEDDriver(t *testing.T) { d := initTestLEDDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit LED"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Microbit LED")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestLEDDriverStartAndHalt(t *testing.T) { d := initTestLEDDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestLEDDriverWriteMatrix(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - gobottest.Assert(t, d.WriteMatrix([]byte{0x01, 0x02}), nil) + assert.Nil(t, d.WriteMatrix([]byte{0x01, 0x02})) } func TestLEDDriverWriteText(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - gobottest.Assert(t, d.WriteText("Hello"), nil) + assert.Nil(t, d.WriteText("Hello")) } func TestLEDDriverCommands(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - gobottest.Assert(t, d.Blank(), nil) - gobottest.Assert(t, d.Solid(), nil) - gobottest.Assert(t, d.UpRightArrow(), nil) - gobottest.Assert(t, d.UpLeftArrow(), nil) - gobottest.Assert(t, d.DownRightArrow(), nil) - gobottest.Assert(t, d.DownLeftArrow(), nil) - gobottest.Assert(t, d.Dimond(), nil) - gobottest.Assert(t, d.Smile(), nil) - gobottest.Assert(t, d.Wink(), nil) + assert.Nil(t, d.Blank()) + assert.Nil(t, d.Solid()) + assert.Nil(t, d.UpRightArrow()) + assert.Nil(t, d.UpLeftArrow()) + assert.Nil(t, d.DownRightArrow()) + assert.Nil(t, d.DownLeftArrow()) + assert.Nil(t, d.Dimond()) + assert.Nil(t, d.Smile()) + assert.Nil(t, d.Wink()) } diff --git a/platforms/microbit/magnetometer_driver_test.go b/platforms/microbit/magnetometer_driver_test.go index 03ef4145f..7a9e0bde9 100644 --- a/platforms/microbit/magnetometer_driver_test.go +++ b/platforms/microbit/magnetometer_driver_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*MagnetometerDriver)(nil) @@ -18,15 +18,15 @@ func initTestMagnetometerDriver() *MagnetometerDriver { func TestMagnetometerDriver(t *testing.T) { d := initTestMagnetometerDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit Magnetometer"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Microbit Magnetometer")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestMagnetometerDriverStartAndHalt(t *testing.T) { d := initTestMagnetometerDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestMagnetometerDriverReadData(t *testing.T) { @@ -35,9 +35,9 @@ func TestMagnetometerDriverReadData(t *testing.T) { d := NewMagnetometerDriver(a) _ = d.Start() _ = d.On(Magnetometer, func(data interface{}) { - gobottest.Assert(t, data.(*MagnetometerData).X, float32(8.738)) - gobottest.Assert(t, data.(*MagnetometerData).Y, float32(8.995)) - gobottest.Assert(t, data.(*MagnetometerData).Z, float32(9.252)) + assert.Equal(t, float32(8.738), data.(*MagnetometerData).X) + assert.Equal(t, float32(8.995), data.(*MagnetometerData).Y) + assert.Equal(t, float32(9.252), data.(*MagnetometerData).Z) sem <- true }) diff --git a/platforms/microbit/temperature_driver_test.go b/platforms/microbit/temperature_driver_test.go index 8abeef661..4ab2bb4a1 100644 --- a/platforms/microbit/temperature_driver_test.go +++ b/platforms/microbit/temperature_driver_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*TemperatureDriver)(nil) @@ -18,15 +18,15 @@ func initTestTemperatureDriver() *TemperatureDriver { func TestTemperatureDriver(t *testing.T) { d := initTestTemperatureDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit Temperature"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Microbit Temperature")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestTemperatureDriverStartAndHalt(t *testing.T) { d := initTestTemperatureDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestTemperatureDriverReadData(t *testing.T) { @@ -35,7 +35,7 @@ func TestTemperatureDriverReadData(t *testing.T) { d := NewTemperatureDriver(a) _ = d.Start() _ = d.On(Temperature, func(data interface{}) { - gobottest.Assert(t, data, int8(0x22)) + assert.Equal(t, int8(0x22), data) sem <- true }) diff --git a/platforms/mqtt/mqtt_adaptor_test.go b/platforms/mqtt/mqtt_adaptor_test.go index db27ec67e..b36a4e4eb 100644 --- a/platforms/mqtt/mqtt_adaptor_test.go +++ b/platforms/mqtt/mqtt_adaptor_test.go @@ -1,13 +1,12 @@ package mqtt import ( - "errors" "fmt" "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -18,112 +17,112 @@ func initTestMqttAdaptor() *Adaptor { func TestMqttAdaptorName(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "MQTT"), true) + assert.True(t, strings.HasPrefix(a.Name(), "MQTT")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestMqttAdaptorPort(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.Port(), "tcp://localhost:1883") + assert.Equal(t, "tcp://localhost:1883", a.Port()) } func TestMqttAdaptorAutoReconnect(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.AutoReconnect(), false) + assert.False(t, a.AutoReconnect()) a.SetAutoReconnect(true) - gobottest.Assert(t, a.AutoReconnect(), true) + assert.True(t, a.AutoReconnect()) } func TestMqttAdaptorCleanSession(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.CleanSession(), true) + assert.True(t, a.CleanSession()) a.SetCleanSession(false) - gobottest.Assert(t, a.CleanSession(), false) + assert.False(t, a.CleanSession()) } func TestMqttAdaptorUseSSL(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.UseSSL(), false) + assert.False(t, a.UseSSL()) a.SetUseSSL(true) - gobottest.Assert(t, a.UseSSL(), true) + assert.True(t, a.UseSSL()) } func TestMqttAdaptorUseServerCert(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.ServerCert(), "") + assert.Equal(t, "", a.ServerCert()) a.SetServerCert("/path/to/server.cert") - gobottest.Assert(t, a.ServerCert(), "/path/to/server.cert") + assert.Equal(t, "/path/to/server.cert", a.ServerCert()) } func TestMqttAdaptorUseClientCert(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.ClientCert(), "") + assert.Equal(t, "", a.ClientCert()) a.SetClientCert("/path/to/client.cert") - gobottest.Assert(t, a.ClientCert(), "/path/to/client.cert") + assert.Equal(t, "/path/to/client.cert", a.ClientCert()) } func TestMqttAdaptorUseClientKey(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.ClientKey(), "") + assert.Equal(t, "", a.ClientKey()) a.SetClientKey("/path/to/client.key") - gobottest.Assert(t, a.ClientKey(), "/path/to/client.key") + assert.Equal(t, "/path/to/client.key", a.ClientKey()) } func TestMqttAdaptorConnectError(t *testing.T) { a := NewAdaptor("tcp://localhost:1884", "client") err := a.Connect() - gobottest.Assert(t, strings.Contains(err.Error(), "connection refused"), true) + assert.Contains(t, err.Error(), "connection refused") } func TestMqttAdaptorConnectSSLError(t *testing.T) { a := NewAdaptor("tcp://localhost:1884", "client") a.SetUseSSL(true) err := a.Connect() - gobottest.Assert(t, strings.Contains(err.Error(), "connection refused"), true) + assert.Contains(t, err.Error(), "connection refused") } func TestMqttAdaptorConnectWithAuthError(t *testing.T) { a := NewAdaptorWithAuth("xyz://localhost:1883", "client", "user", "pass") - gobottest.Assert(t, a.Connect(), errors.New("network Error : unknown protocol")) + assert.Errorf(t, a.Connect(), "network Error : unknown protocol") } func TestMqttAdaptorFinalize(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } func TestMqttAdaptorCannotPublishUnlessConnected(t *testing.T) { a := initTestMqttAdaptor() data := []byte("o") - gobottest.Assert(t, a.Publish("test", data), false) + assert.False(t, a.Publish("test", data)) } func TestMqttAdaptorPublishWhenConnected(t *testing.T) { a := initTestMqttAdaptor() _ = a.Connect() data := []byte("o") - gobottest.Assert(t, a.Publish("test", data), true) + assert.True(t, a.Publish("test", data)) } func TestMqttAdaptorCannotOnUnlessConnected(t *testing.T) { a := initTestMqttAdaptor() - gobottest.Assert(t, a.On("hola", func(msg Message) { + assert.False(t, a.On("hola", func(msg Message) { fmt.Println("hola") - }), false) + })) } func TestMqttAdaptorOnWhenConnected(t *testing.T) { a := initTestMqttAdaptor() _ = a.Connect() - gobottest.Assert(t, a.On("hola", func(msg Message) { + assert.True(t, a.On("hola", func(msg Message) { fmt.Println("hola") - }), true) + })) } func TestMqttAdaptorQoS(t *testing.T) { a := initTestMqttAdaptor() a.SetQoS(1) - gobottest.Assert(t, 1, a.qos) + assert.Equal(t, a.qos, 1) } diff --git a/platforms/mqtt/mqtt_driver_test.go b/platforms/mqtt/mqtt_driver_test.go index 028838db7..1cbfe29db 100644 --- a/platforms/mqtt/mqtt_driver_test.go +++ b/platforms/mqtt/mqtt_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -13,25 +13,25 @@ var _ gobot.Driver = (*Driver)(nil) func TestMqttDriver(t *testing.T) { d := NewDriver(initTestMqttAdaptor(), "/test/topic") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "MQTT"), true) - gobottest.Assert(t, strings.HasPrefix(d.Connection().Name(), "MQTT"), true) + assert.True(t, strings.HasPrefix(d.Name(), "MQTT")) + assert.True(t, strings.HasPrefix(d.Connection().Name(), "MQTT")) - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestMqttDriverName(t *testing.T) { d := NewDriver(initTestMqttAdaptor(), "/test/topic") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "MQTT"), true) + assert.True(t, strings.HasPrefix(d.Name(), "MQTT")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestMqttDriverTopic(t *testing.T) { d := NewDriver(initTestMqttAdaptor(), "/test/topic") - gobottest.Assert(t, d.Topic(), "/test/topic") + assert.Equal(t, "/test/topic", d.Topic()) d.SetTopic("/test/newtopic") - gobottest.Assert(t, d.Topic(), "/test/newtopic") + assert.Equal(t, "/test/newtopic", d.Topic()) } func TestMqttDriverPublish(t *testing.T) { @@ -40,7 +40,7 @@ func TestMqttDriverPublish(t *testing.T) { _ = a.Connect() _ = d.Start() defer func() { _ = d.Halt() }() - gobottest.Assert(t, d.Publish([]byte{0x01, 0x02, 0x03}), true) + assert.True(t, d.Publish([]byte{0x01, 0x02, 0x03})) } func TestMqttDriverPublishError(t *testing.T) { @@ -48,5 +48,5 @@ func TestMqttDriverPublishError(t *testing.T) { d := NewDriver(a, "/test/topic") _ = d.Start() defer func() { _ = d.Halt() }() - gobottest.Assert(t, d.Publish([]byte{0x01, 0x02, 0x03}), false) + assert.False(t, d.Publish([]byte{0x01, 0x02, 0x03})) } diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index e6681c047..e75bc6397 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -5,10 +5,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -74,9 +74,9 @@ func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system. func TestName(t *testing.T) { a := NewNeoAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "NanoPi NEO Board"), true) + assert.True(t, strings.HasPrefix(a.Name(), "NanoPi NEO Board")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestDigitalIO(t *testing.T) { @@ -84,14 +84,14 @@ func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) _ = a.DigitalWrite("7", 1) - gobottest.Assert(t, fs.Files[gpio203Path+"value"].Contents, "1") + assert.Equal(t, "1", fs.Files[gpio203Path+"value"].Contents) fs.Files[gpio199Path+"value"].Contents = "1" i, _ := a.DigitalRead("10") - gobottest.Assert(t, i, 1) + assert.Equal(t, 1, i) - gobottest.Assert(t, a.DigitalWrite("99", 1), fmt.Errorf("'99' is not a valid id for a digital pin")) - gobottest.Assert(t, a.Finalize(), nil) + assert.Errorf(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.Nil(t, a.Finalize()) } func TestInvalidPWMPin(t *testing.T) { @@ -99,16 +99,16 @@ func TestInvalidPWMPin(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("666", 42) - gobottest.Assert(t, err.Error(), "'666' is not a valid id for a PWM pin") + assert.Errorf(t, err, "'666' is not a valid id for a PWM pin") err = a.ServoWrite("666", 120) - gobottest.Assert(t, err.Error(), "'666' is not a valid id for a PWM pin") + assert.Errorf(t, err, "'666' is not a valid id for a PWM pin") err = a.PwmWrite("3", 42) - gobottest.Assert(t, err.Error(), "'3' is not a valid id for a PWM pin") + assert.Errorf(t, err, "'3' is not a valid id for a PWM pin") err = a.ServoWrite("3", 120) - gobottest.Assert(t, err.Error(), "'3' is not a valid id for a PWM pin") + assert.Errorf(t, err, "'3' is not a valid id for a PWM pin") } func TestPwmWrite(t *testing.T) { @@ -116,24 +116,24 @@ func TestPwmWrite(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("PWM", 100) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files[pwmExportPath].Contents, "0") - gobottest.Assert(t, fs.Files[pwmEnablePath].Contents, "1") - gobottest.Assert(t, fs.Files[pwmPeriodPath].Contents, fmt.Sprintf("%d", 10000000)) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, "3921568") - gobottest.Assert(t, fs.Files[pwmPolarityPath].Contents, "normal") + assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) + assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) + assert.Equal(t, fmt.Sprintf("%d", 10000000), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.ServoWrite("PWM", 0) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, "500000") + assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("PWM", 180) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, "2000000") - gobottest.Assert(t, a.Finalize(), nil) + assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) + assert.Nil(t, a.Finalize()) } func TestSetPeriod(t *testing.T) { @@ -145,25 +145,25 @@ func TestSetPeriod(t *testing.T) { // act err := a.SetPeriod("PWM", newPeriod) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files[pwmExportPath].Contents, "0") - gobottest.Assert(t, fs.Files[pwmEnablePath].Contents, "1") - gobottest.Assert(t, fs.Files[pwmPeriodPath].Contents, fmt.Sprintf("%d", newPeriod)) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, "0") - gobottest.Assert(t, fs.Files[pwmPolarityPath].Contents, "normal") + assert.Nil(t, err) + assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) + assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) + assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, "0", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("PWM", 127) // 127 is a little bit smaller than 50% of period - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, fmt.Sprintf("%d", 1270000)) + assert.Nil(t, err) + assert.Equal(t, fmt.Sprintf("%d", 1270000), fs.Files[pwmDutyCyclePath].Contents) newPeriod = newPeriod / 10 // act err = a.SetPeriod("PWM", newPeriod) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, fmt.Sprintf("%d", 127000)) + assert.Nil(t, err) + assert.Equal(t, fmt.Sprintf("%d", 127000), fs.Files[pwmDutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value newPeriod = newPeriod * 20 @@ -172,46 +172,46 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("PWM", newPeriod) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, fmt.Sprintf("%d", 2540000)) + assert.Nil(t, err) + assert.Equal(t, fmt.Sprintf("%d", 2540000), fs.Files[pwmDutyCyclePath].Contents) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - gobottest.Assert(t, a.DigitalWrite("7", 1), nil) + assert.Nil(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true err := a.Finalize() - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) - gobottest.Assert(t, a.PwmWrite("PWM", 1), nil) + assert.Nil(t, a.PwmWrite("PWM", 1)) fs.WithWriteError = true err := a.Finalize() - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestSpiDefaultValues(t *testing.T) { a := NewNeoAdaptor() - gobottest.Assert(t, a.SpiDefaultBusNumber(), 0) - gobottest.Assert(t, a.SpiDefaultChipNumber(), 0) - gobottest.Assert(t, a.SpiDefaultMode(), 0) - gobottest.Assert(t, a.SpiDefaultBitCount(), 8) - gobottest.Assert(t, a.SpiDefaultMaxSpeed(), int64(500000)) + assert.Equal(t, 0, a.SpiDefaultBusNumber()) + assert.Equal(t, 0, a.SpiDefaultChipNumber()) + assert.Equal(t, 0, a.SpiDefaultMode()) + assert.Equal(t, 8, a.SpiDefaultBitCount()) + assert.Equal(t, int64(500000), a.SpiDefaultMaxSpeed()) } func TestI2cDefaultBus(t *testing.T) { a := NewNeoAdaptor() - gobottest.Assert(t, a.DefaultI2cBus(), 0) + assert.Equal(t, 0, a.DefaultI2cBus()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -219,16 +219,16 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewNeoAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = con.Write([]byte{0xbf}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) fs.WithCloseError = true // act err = a.Finalize() // assert - gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true) + assert.Contains(t, err.Error(), "close error") } func Test_validateSpiBusNumber(t *testing.T) { @@ -255,7 +255,7 @@ func Test_validateSpiBusNumber(t *testing.T) { // act err := a.validateSpiBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } @@ -290,7 +290,7 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateI2cBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } @@ -330,9 +330,9 @@ func Test_translateDigitalPin(t *testing.T) { // act chip, line, err := a.translateDigitalPin(tc.pin) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, chip, tc.wantChip) - gobottest.Assert(t, line, tc.wantLine) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantChip, chip) + assert.Equal(t, tc.wantLine, line) }) } } @@ -370,9 +370,9 @@ func Test_translatePWMPin(t *testing.T) { // act dir, channel, err := a.translatePWMPin(tc.pin) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, dir, tc.wantDir) - gobottest.Assert(t, channel, tc.wantChannel) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantDir, dir) + assert.Equal(t, tc.wantChannel, channel) }) } } diff --git a/platforms/nats/nats_adaptor_test.go b/platforms/nats/nats_adaptor_test.go index 469ec6f2b..9ab2dcbde 100644 --- a/platforms/nats/nats_adaptor_test.go +++ b/platforms/nats/nats_adaptor_test.go @@ -1,15 +1,14 @@ package nats import ( - "errors" "fmt" "log" "strings" "testing" "github.com/nats-io/nats.go" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -53,55 +52,55 @@ func initTestNatsAdaptorTLS(options ...nats.Option) *Adaptor { func TestNatsAdaptorName(t *testing.T) { a := initTestNatsAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "NATS"), true) + assert.True(t, strings.HasPrefix(a.Name(), "NATS")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestNatsAdaptorReturnsHost(t *testing.T) { a := initTestNatsAdaptor() - gobottest.Assert(t, a.Host, "nats://localhost:4222") + assert.Equal(t, "nats://localhost:4222", a.Host) } func TestNatsAdaptorWithAuth(t *testing.T) { a := initTestNatsAdaptorWithAuth() - gobottest.Assert(t, a.username, "user") - gobottest.Assert(t, a.password, "pass") + assert.Equal(t, "user", a.username) + assert.Equal(t, "pass", a.password) } func TestNatsAdapterSetsRootCAs(t *testing.T) { a := initTestNatsAdaptorTLS(nats.RootCAs("test_certs/catest.pem")) - gobottest.Assert(t, a.Host, "tls://localhost:4242") + assert.Equal(t, "tls://localhost:4242", a.Host) _ = a.Connect() o := a.client.Opts casPool, err := o.RootCAsCB() - gobottest.Assert(t, err, nil) - gobottest.Refute(t, casPool, nil) - gobottest.Assert(t, o.Secure, true) + assert.Nil(t, err) + assert.NotNil(t, casPool) + assert.True(t, o.Secure) } func TestNatsAdapterSetsClientCerts(t *testing.T) { a := initTestNatsAdaptorTLS(nats.ClientCert("test_certs/client-cert.pem", "test_certs/client-key.pem")) - gobottest.Assert(t, a.Host, "tls://localhost:4242") + assert.Equal(t, "tls://localhost:4242", a.Host) _ = a.Connect() cert, err := a.client.Opts.TLSCertCB() - gobottest.Assert(t, err, nil) - gobottest.Refute(t, cert, nil) - gobottest.Refute(t, cert.Leaf, nil) - gobottest.Assert(t, a.client.Opts.Secure, true) + assert.Nil(t, err) + assert.NotNil(t, cert) + assert.NotNil(t, cert.Leaf) + assert.True(t, a.client.Opts.Secure) } func TestNatsAdapterSetsClientCertsWithUserInfo(t *testing.T) { a := initTestNatsAdaptorTLS(nats.ClientCert("test_certs/client-cert.pem", "test_certs/client-key.pem"), nats.UserInfo("test", "testwd")) - gobottest.Assert(t, a.Host, "tls://localhost:4242") + assert.Equal(t, "tls://localhost:4242", a.Host) _ = a.Connect() cert, err := a.client.Opts.TLSCertCB() - gobottest.Assert(t, err, nil) - gobottest.Refute(t, cert, nil) - gobottest.Refute(t, cert.Leaf, nil) - gobottest.Assert(t, a.client.Opts.Secure, true) - gobottest.Assert(t, a.client.Opts.User, "test") - gobottest.Assert(t, a.client.Opts.Password, "testwd") + assert.Nil(t, err) + assert.NotNil(t, cert) + assert.NotNil(t, cert.Leaf) + assert.True(t, a.client.Opts.Secure) + assert.Equal(t, "test", a.client.Opts.User) + assert.Equal(t, "testwd", a.client.Opts.Password) } // TODO: implement this test without requiring actual server connection @@ -110,7 +109,7 @@ func TestNatsAdaptorPublishWhenConnected(t *testing.T) { a := initTestNatsAdaptor() _ = a.Connect() data := []byte("o") - gobottest.Assert(t, a.Publish("test", data), true) + assert.True(t, a.Publish("test", data)) } // TODO: implement this test without requiring actual server connection @@ -118,9 +117,9 @@ func TestNatsAdaptorOnWhenConnected(t *testing.T) { t.Skip("TODO: implement this test without requiring actual server connection") a := initTestNatsAdaptor() _ = a.Connect() - gobottest.Assert(t, a.On("hola", func(msg Message) { + assert.True(t, a.On("hola", func(msg Message) { fmt.Println("hola") - }), true) + })) } // TODO: implement this test without requiring actual server connection @@ -129,7 +128,7 @@ func TestNatsAdaptorPublishWhenConnectedWithAuth(t *testing.T) { a := NewAdaptorWithAuth("localhost:4222", 49999, "test", "testwd") _ = a.Connect() data := []byte("o") - gobottest.Assert(t, a.Publish("test", data), true) + assert.True(t, a.Publish("test", data)) } // TODO: implement this test without requiring actual server connection @@ -138,9 +137,9 @@ func TestNatsAdaptorOnWhenConnectedWithAuth(t *testing.T) { log.Println("###not skipped###") a := NewAdaptorWithAuth("localhost:4222", 59999, "test", "testwd") _ = a.Connect() - gobottest.Assert(t, a.On("hola", func(msg Message) { + assert.True(t, a.On("hola", func(msg Message) { fmt.Println("hola") - }), true) + })) } func TestNatsAdaptorFailedConnect(t *testing.T) { @@ -149,23 +148,23 @@ func TestNatsAdaptorFailedConnect(t *testing.T) { if err != nil && strings.Contains(err.Error(), "cannot assign requested address") { t.Skip("FLAKY: Can not test, because IP or port is in use.") } - gobottest.Assert(t, err, errors.New("nats: no servers available for connection")) + assert.Errorf(t, err, "nats: no servers available for connection") } func TestNatsAdaptorFinalize(t *testing.T) { a := NewAdaptor("localhost:9999", 79999) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } func TestNatsAdaptorCannotPublishUnlessConnected(t *testing.T) { a := NewAdaptor("localhost:9999", 89999) data := []byte("o") - gobottest.Assert(t, a.Publish("test", data), false) + assert.False(t, a.Publish("test", data)) } func TestNatsAdaptorCannotOnUnlessConnected(t *testing.T) { a := NewAdaptor("localhost:9999", 99999) - gobottest.Assert(t, a.On("hola", func(msg Message) { + assert.False(t, a.On("hola", func(msg Message) { fmt.Println("hola") - }), false) + })) } diff --git a/platforms/nats/nats_driver_test.go b/platforms/nats/nats_driver_test.go index 2725df02f..7c8a14c61 100644 --- a/platforms/nats/nats_driver_test.go +++ b/platforms/nats/nats_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -13,23 +13,23 @@ var _ gobot.Driver = (*Driver)(nil) func TestNatsDriver(t *testing.T) { d := NewDriver(initTestNatsAdaptor(), "/test/topic") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "NATS"), true) - gobottest.Assert(t, strings.HasPrefix(d.Connection().Name(), "NATS"), true) - gobottest.Refute(t, d.adaptor(), nil) + assert.True(t, strings.HasPrefix(d.Name(), "NATS")) + assert.True(t, strings.HasPrefix(d.Connection().Name(), "NATS")) + assert.NotNil(t, d.adaptor()) - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestNatsDriverName(t *testing.T) { d := NewDriver(initTestNatsAdaptor(), "/test/topic") - gobottest.Assert(t, strings.HasPrefix(d.Name(), "NATS"), true) + assert.True(t, strings.HasPrefix(d.Name(), "NATS")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestNatsDriverTopic(t *testing.T) { d := NewDriver(initTestNatsAdaptor(), "/test/topic") d.SetTopic("interestingtopic") - gobottest.Assert(t, d.Topic(), "interestingtopic") + assert.Equal(t, "interestingtopic", d.Topic()) } diff --git a/platforms/neurosky/neurosky_adaptor_test.go b/platforms/neurosky/neurosky_adaptor_test.go index 74237ec7a..2089d16d4 100644 --- a/platforms/neurosky/neurosky_adaptor_test.go +++ b/platforms/neurosky/neurosky_adaptor_test.go @@ -7,8 +7,8 @@ import ( "sync" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -57,24 +57,24 @@ func initTestNeuroskyAdaptor() *Adaptor { func TestNeuroskyAdaptor(t *testing.T) { a := NewAdaptor("/dev/null") - gobottest.Assert(t, a.Port(), "/dev/null") + assert.Equal(t, "/dev/null", a.Port()) } func TestNeuroskyAdaptorName(t *testing.T) { a := NewAdaptor("/dev/null") - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Neurosky"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Neurosky")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestNeuroskyAdaptorConnect(t *testing.T) { a := initTestNeuroskyAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") } - gobottest.Assert(t, a.Connect(), errors.New("connection error")) + assert.Errorf(t, a.Connect(), "connection error") } func TestNeuroskyAdaptorFinalize(t *testing.T) { @@ -84,9 +84,9 @@ func TestNeuroskyAdaptorFinalize(t *testing.T) { return rwc, nil } _ = a.Connect() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) rwc.CloseError(errors.New("close error")) _ = a.Connect() - gobottest.Assert(t, a.Finalize(), errors.New("close error")) + assert.Errorf(t, a.Finalize(), "close error") } diff --git a/platforms/neurosky/neurosky_driver_test.go b/platforms/neurosky/neurosky_driver_test.go index 9f83f5387..6a85a44a4 100644 --- a/platforms/neurosky/neurosky_driver_test.go +++ b/platforms/neurosky/neurosky_driver_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -25,14 +25,14 @@ func initTestNeuroskyDriver() *Driver { func TestNeuroskyDriver(t *testing.T) { d := initTestNeuroskyDriver() - gobottest.Refute(t, d.Connection(), nil) + assert.NotNil(t, d.Connection()) } func TestNeuroskyDriverName(t *testing.T) { d := initTestNeuroskyDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Neurosky"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Neurosky")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestNeuroskyDriverStart(t *testing.T) { @@ -48,11 +48,11 @@ func TestNeuroskyDriverStart(t *testing.T) { d := NewDriver(a) e := errors.New("read error") _ = d.Once(d.Event(Error), func(data interface{}) { - gobottest.Assert(t, data.(error), e) + assert.Equal(t, e, data.(error)) sem <- true }) - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) time.Sleep(50 * time.Millisecond) rwc.ReadError(e) @@ -69,7 +69,7 @@ func TestNeuroskyDriverStart(t *testing.T) { func TestNeuroskyDriverHalt(t *testing.T) { d := initTestNeuroskyDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestNeuroskyDriverParse(t *testing.T) { @@ -99,7 +99,7 @@ func TestNeuroskyDriverParse(t *testing.T) { }() _ = d.On(d.Event(Signal), func(data interface{}) { - gobottest.Assert(t, data.(byte), byte(100)) + assert.Equal(t, byte(100), data.(byte)) sem <- true }) @@ -112,7 +112,7 @@ func TestNeuroskyDriverParse(t *testing.T) { }() _ = d.On(d.Event(Attention), func(data interface{}) { - gobottest.Assert(t, data.(byte), byte(40)) + assert.Equal(t, byte(40), data.(byte)) sem <- true }) @@ -125,7 +125,7 @@ func TestNeuroskyDriverParse(t *testing.T) { }() _ = d.On(d.Event(Meditation), func(data interface{}) { - gobottest.Assert(t, data.(byte), byte(60)) + assert.Equal(t, byte(60), data.(byte)) sem <- true }) @@ -138,7 +138,7 @@ func TestNeuroskyDriverParse(t *testing.T) { }() _ = d.On(d.Event(Blink), func(data interface{}) { - gobottest.Assert(t, data.(byte), byte(150)) + assert.Equal(t, byte(150), data.(byte)) sem <- true }) @@ -151,7 +151,7 @@ func TestNeuroskyDriverParse(t *testing.T) { }() _ = d.On(d.Event(Wave), func(data interface{}) { - gobottest.Assert(t, data.(int16), int16(16401)) + assert.Equal(t, int16(16401), data.(int16)) sem <- true }) @@ -166,8 +166,7 @@ func TestNeuroskyDriverParse(t *testing.T) { }() _ = d.On(d.Event(EEG), func(data interface{}) { - gobottest.Assert(t, - data.(EEGData), + assert.Equal(t, EEGData{ Delta: 1573241, Theta: 5832801, @@ -177,7 +176,8 @@ func TestNeuroskyDriverParse(t *testing.T) { HiBeta: 10485791, LoGamma: 8323090, MidGamma: 13565965, - }) + }, + data.(EEGData)) sem <- true }) <-sem diff --git a/platforms/opencv/camera_driver_test.go b/platforms/opencv/camera_driver_test.go index dd3ae7bf8..989c0e95e 100644 --- a/platforms/opencv/camera_driver_test.go +++ b/platforms/opencv/camera_driver_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*CameraDriver)(nil) @@ -22,21 +22,21 @@ func initTestCameraDriver() *CameraDriver { func TestCameraDriver(t *testing.T) { d := initTestCameraDriver() - gobottest.Assert(t, d.Name(), "Camera") - gobottest.Assert(t, d.Connection(), (gobot.Connection)(nil)) + assert.Equal(t, "Camera", d.Name()) + assert.Equal(t, (gobot.Connection)(nil), d.Connection()) } func TestCameraDriverName(t *testing.T) { d := initTestCameraDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Camera"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Camera")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestCameraDriverStart(t *testing.T) { sem := make(chan bool) d := initTestCameraDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) d.On(d.Event("frame"), func(data interface{}) { sem <- true }) @@ -47,13 +47,13 @@ func TestCameraDriverStart(t *testing.T) { } d = NewCameraDriver("") - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) d = NewCameraDriver(true) - gobottest.Refute(t, d.Start(), nil) + assert.NotNil(t, d.Start()) } func TestCameraDriverHalt(t *testing.T) { d := initTestCameraDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } diff --git a/platforms/opencv/utils_test.go b/platforms/opencv/utils_test.go index b89a95c00..924dd53d7 100644 --- a/platforms/opencv/utils_test.go +++ b/platforms/opencv/utils_test.go @@ -5,7 +5,7 @@ import ( "runtime" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" "gocv.io/x/gocv" ) @@ -13,6 +13,6 @@ func TestUtils(t *testing.T) { _, currentfile, _, _ := runtime.Caller(0) image := gocv.IMRead(path.Join(path.Dir(currentfile), "lena-256x256.jpg"), gocv.IMReadColor) rect := DetectObjects("haarcascade_frontalface_alt.xml", image) - gobottest.Refute(t, len(rect), 0) + assert.NotEqual(t, 0, len(rect)) DrawRectangles(image, rect, 0, 0, 0, 0) } diff --git a/platforms/opencv/window_driver_test.go b/platforms/opencv/window_driver_test.go index 9a1127744..7d5d2acd5 100644 --- a/platforms/opencv/window_driver_test.go +++ b/platforms/opencv/window_driver_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" "gocv.io/x/gocv" ) @@ -20,25 +20,25 @@ func initTestWindowDriver() *WindowDriver { func TestWindowDriver(t *testing.T) { d := initTestWindowDriver() - gobottest.Assert(t, d.Name(), "Window") - gobottest.Assert(t, d.Connection(), (gobot.Connection)(nil)) + assert.Equal(t, "Window", d.Name()) + assert.Equal(t, (gobot.Connection)(nil), d.Connection()) } func TestWindowDriverName(t *testing.T) { d := initTestWindowDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Window"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Window")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestWindowDriverStart(t *testing.T) { d := initTestWindowDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestWindowDriverHalt(t *testing.T) { d := initTestWindowDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestWindowDriverShowImage(t *testing.T) { diff --git a/platforms/parrot/ardrone/ardrone_adaptor_test.go b/platforms/parrot/ardrone/ardrone_adaptor_test.go index beb8ffe89..bcfd75357 100644 --- a/platforms/parrot/ardrone/ardrone_adaptor_test.go +++ b/platforms/parrot/ardrone/ardrone_adaptor_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -21,30 +21,30 @@ func initTestArdroneAdaptor() *Adaptor { func TestArdroneAdaptor(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.config.Ip, "192.168.1.1") + assert.Equal(t, "192.168.1.1", a.config.Ip) a = NewAdaptor("192.168.100.100") - gobottest.Assert(t, a.config.Ip, "192.168.100.100") + assert.Equal(t, "192.168.100.100", a.config.Ip) } func TestArdroneAdaptorConnect(t *testing.T) { a := initTestArdroneAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) a.connect = func(a *Adaptor) (drone, error) { return nil, errors.New("connection error") } - gobottest.Assert(t, a.Connect(), errors.New("connection error")) + assert.Errorf(t, a.Connect(), "connection error") } func TestArdroneAdaptorName(t *testing.T) { a := initTestArdroneAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "ARDrone"), true) + assert.True(t, strings.HasPrefix(a.Name(), "ARDrone")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestArdroneAdaptorFinalize(t *testing.T) { a := initTestArdroneAdaptor() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } diff --git a/platforms/parrot/ardrone/ardrone_driver_test.go b/platforms/parrot/ardrone/ardrone_driver_test.go index dfdf6e26c..3f37b1d2d 100644 --- a/platforms/parrot/ardrone/ardrone_driver_test.go +++ b/platforms/parrot/ardrone/ardrone_driver_test.go @@ -3,8 +3,8 @@ package ardrone import ( "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -22,24 +22,24 @@ func initTestArdroneDriver() *Driver { func TestArdroneDriver(t *testing.T) { d := initTestArdroneDriver() - gobottest.Assert(t, d.Name(), "mydrone") + assert.Equal(t, "mydrone", d.Name()) } func TestArdroneDriverName(t *testing.T) { d := initTestArdroneDriver() - gobottest.Assert(t, d.Name(), "mydrone") + assert.Equal(t, "mydrone", d.Name()) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestArdroneDriverStart(t *testing.T) { d := initTestArdroneDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestArdroneDriverHalt(t *testing.T) { d := initTestArdroneDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestArdroneDriverTakeOff(t *testing.T) { d := initTestArdroneDriver() diff --git a/platforms/parrot/ardrone/pitch_test.go b/platforms/parrot/ardrone/pitch_test.go index 97e3ac9ae..c4f5870c2 100644 --- a/platforms/parrot/ardrone/pitch_test.go +++ b/platforms/parrot/ardrone/pitch_test.go @@ -3,17 +3,17 @@ package ardrone import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestArdroneValidatePitchWhenEqualOffset(t *testing.T) { - gobottest.Assert(t, ValidatePitch(32767.0, 32767.0), 1.0) + assert.Equal(t, 1.0, ValidatePitch(32767.0, 32767.0)) } func TestArdroneValidatePitchWhenTiny(t *testing.T) { - gobottest.Assert(t, ValidatePitch(1.1, 32767.0), 0.0) + assert.Equal(t, 0.0, ValidatePitch(1.1, 32767.0)) } func TestArdroneValidatePitchWhenCentered(t *testing.T) { - gobottest.Assert(t, ValidatePitch(16383.5, 32767.0), 0.5) + assert.Equal(t, 0.5, ValidatePitch(16383.5, 32767.0)) } diff --git a/platforms/parrot/bebop/bebop_adaptor_test.go b/platforms/parrot/bebop/bebop_adaptor_test.go index 7faf839ca..a2ebba5ef 100644 --- a/platforms/parrot/bebop/bebop_adaptor_test.go +++ b/platforms/parrot/bebop/bebop_adaptor_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -22,23 +22,23 @@ func initTestBebopAdaptor() *Adaptor { func TestBebopAdaptorName(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Bebop"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Bebop")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestBebopAdaptorConnect(t *testing.T) { a := initTestBebopAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) a.connect = func(a *Adaptor) error { return errors.New("connection error") } - gobottest.Assert(t, a.Connect(), errors.New("connection error")) + assert.Errorf(t, a.Connect(), "connection error") } func TestBebopAdaptorFinalize(t *testing.T) { a := initTestBebopAdaptor() _ = a.Connect() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } diff --git a/platforms/parrot/bebop/bebop_driver_test.go b/platforms/parrot/bebop/bebop_driver_test.go index 0565114ba..6685eb650 100644 --- a/platforms/parrot/bebop/bebop_driver_test.go +++ b/platforms/parrot/bebop/bebop_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -13,7 +13,7 @@ var _ gobot.Driver = (*Driver)(nil) func TestBebopDriverName(t *testing.T) { a := initTestBebopAdaptor() d := NewDriver(a) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Bebop"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Bebop")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } diff --git a/platforms/parrot/bebop/pitch_test.go b/platforms/parrot/bebop/pitch_test.go index 62dc13980..bf119f347 100644 --- a/platforms/parrot/bebop/pitch_test.go +++ b/platforms/parrot/bebop/pitch_test.go @@ -3,17 +3,17 @@ package bebop import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestBebopValidatePitchWhenEqualOffset(t *testing.T) { - gobottest.Assert(t, ValidatePitch(32767.0, 32767.0), 100) + assert.Equal(t, 100, ValidatePitch(32767.0, 32767.0)) } func TestBebopValidatePitchWhenTiny(t *testing.T) { - gobottest.Assert(t, ValidatePitch(1.1, 32767.0), 0) + assert.Equal(t, 0, ValidatePitch(1.1, 32767.0)) } func TestBebopValidatePitchWhenCentered(t *testing.T) { - gobottest.Assert(t, ValidatePitch(16383.5, 32767.0), 50) + assert.Equal(t, 50, ValidatePitch(16383.5, 32767.0)) } diff --git a/platforms/parrot/minidrone/minidrone_driver_test.go b/platforms/parrot/minidrone/minidrone_driver_test.go index d57a65ae2..5ab313a45 100644 --- a/platforms/parrot/minidrone/minidrone_driver_test.go +++ b/platforms/parrot/minidrone/minidrone_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -17,154 +17,154 @@ func initTestMinidroneDriver() *Driver { func TestMinidroneDriver(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Minidrone"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Minidrone")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestMinidroneDriverStartAndHalt(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestMinidroneTakeoff(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.TakeOff(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.TakeOff()) } func TestMinidroneEmergency(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Emergency(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Emergency()) } func TestMinidroneTakePicture(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.TakePicture(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.TakePicture()) } func TestMinidroneUp(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Up(25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Up(25)) } func TestMinidroneUpTooFar(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Up(125), nil) - gobottest.Assert(t, d.Up(-50), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Up(125)) + assert.Nil(t, d.Up(-50)) } func TestMinidroneDown(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Down(25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Down(25)) } func TestMinidroneForward(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Forward(25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Forward(25)) } func TestMinidroneBackward(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Backward(25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Backward(25)) } func TestMinidroneRight(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Right(25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Right(25)) } func TestMinidroneLeft(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Left(25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Left(25)) } func TestMinidroneClockwise(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Clockwise(25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Clockwise(25)) } func TestMinidroneCounterClockwise(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.CounterClockwise(25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.CounterClockwise(25)) } func TestMinidroneStop(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Stop(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Stop()) } func TestMinidroneStartStopRecording(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.StartRecording(), nil) - gobottest.Assert(t, d.StopRecording(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.StartRecording()) + assert.Nil(t, d.StopRecording()) } func TestMinidroneHullProtectionOutdoor(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.HullProtection(true), nil) - gobottest.Assert(t, d.Outdoor(true), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.HullProtection(true)) + assert.Nil(t, d.Outdoor(true)) } func TestMinidroneHullFlips(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.FrontFlip(), nil) - gobottest.Assert(t, d.BackFlip(), nil) - gobottest.Assert(t, d.RightFlip(), nil) - gobottest.Assert(t, d.LeftFlip(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.FrontFlip()) + assert.Nil(t, d.BackFlip()) + assert.Nil(t, d.RightFlip()) + assert.Nil(t, d.LeftFlip()) } func TestMinidroneLightControl(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.LightControl(0, LightBlinked, 25), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.LightControl(0, LightBlinked, 25)) } func TestMinidroneClawControl(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.ClawControl(0, ClawOpen), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.ClawControl(0, ClawOpen)) } func TestMinidroneGunControl(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.GunControl(0), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.GunControl(0)) } func TestMinidroneProcessFlightData(t *testing.T) { d := initTestMinidroneDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) d.processFlightStatus([]byte{0x00, 0x00, 0x00}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x00}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}) - gobottest.Assert(t, d.flying, false) + assert.False(t, d.flying) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01}) - gobottest.Assert(t, d.flying, false) + assert.False(t, d.flying) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02}) - gobottest.Assert(t, d.flying, true) + assert.True(t, d.flying) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03}) - gobottest.Assert(t, d.flying, true) + assert.True(t, d.flying) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06}) - gobottest.Assert(t, d.Stop(), nil) + assert.Nil(t, d.Stop()) } diff --git a/platforms/parrot/minidrone/pitch_test.go b/platforms/parrot/minidrone/pitch_test.go index 8b0261715..51b838bed 100644 --- a/platforms/parrot/minidrone/pitch_test.go +++ b/platforms/parrot/minidrone/pitch_test.go @@ -3,17 +3,17 @@ package minidrone import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestMinidroneValidatePitchWhenEqualOffset(t *testing.T) { - gobottest.Assert(t, ValidatePitch(32767.0, 32767.0), 100) + assert.Equal(t, 100, ValidatePitch(32767.0, 32767.0)) } func TestMinidroneValidatePitchWhenTiny(t *testing.T) { - gobottest.Assert(t, ValidatePitch(1.1, 32767.0), 0) + assert.Equal(t, 0, ValidatePitch(1.1, 32767.0)) } func TestMinidroneValidatePitchWhenCentered(t *testing.T) { - gobottest.Assert(t, ValidatePitch(16383.5, 32767.0), 50) + assert.Equal(t, 50, ValidatePitch(16383.5, 32767.0)) } diff --git a/platforms/particle/adaptor_test.go b/platforms/particle/adaptor_test.go index 0c55db12e..e1e028a53 100644 --- a/platforms/particle/adaptor_test.go +++ b/platforms/particle/adaptor_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/donovanhide/eventsource" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) // HELPERS @@ -79,22 +79,22 @@ func TestNewAdaptor(t *testing.T) { t.Errorf("NewAdaptor() should have returned a *Adaptor") } - gobottest.Assert(t, core.APIServer, "https://api.particle.io") - gobottest.Assert(t, strings.HasPrefix(core.Name(), "Particle"), true) + assert.Equal(t, "https://api.particle.io", core.APIServer) + assert.True(t, strings.HasPrefix(core.Name(), "Particle")) core.SetName("sparkie") - gobottest.Assert(t, core.Name(), "sparkie") + assert.Equal(t, "sparkie", core.Name()) } func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) } func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() _ = a.Connect() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } func TestAdaptorAnalogRead(t *testing.T) { @@ -109,7 +109,7 @@ func TestAdaptorAnalogRead(t *testing.T) { defer testServer.Close() val, _ := a.AnalogRead("A1") - gobottest.Assert(t, val, 5) + assert.Equal(t, 5, val) } func TestAdaptorAnalogReadError(t *testing.T) { @@ -122,7 +122,7 @@ func TestAdaptorAnalogReadError(t *testing.T) { a.setAPIServer(testServer.URL) val, _ := a.AnalogRead("A1") - gobottest.Assert(t, val, 0) + assert.Equal(t, 0, val) } func TestAdaptorPwmWrite(t *testing.T) { @@ -206,7 +206,7 @@ func TestAdaptorDigitalRead(t *testing.T) { a.setAPIServer(testServer.URL) val, _ := a.DigitalRead("D7") - gobottest.Assert(t, val, 1) + assert.Equal(t, 1, val) testServer.Close() // When LOW @@ -218,7 +218,7 @@ func TestAdaptorDigitalRead(t *testing.T) { defer testServer.Close() val, _ = a.DigitalRead("D7") - gobottest.Assert(t, val, 0) + assert.Equal(t, 0, val) } func TestAdaptorDigitalReadError(t *testing.T) { @@ -232,7 +232,7 @@ func TestAdaptorDigitalReadError(t *testing.T) { a.setAPIServer(testServer.URL) val, _ := a.DigitalRead("D7") - gobottest.Assert(t, val, -1) + assert.Equal(t, -1, val) } func TestAdaptorFunction(t *testing.T) { @@ -244,7 +244,7 @@ func TestAdaptorFunction(t *testing.T) { a.setAPIServer(testServer.URL) val, _ := a.Function("hello", "100,200") - gobottest.Assert(t, val, 1) + assert.Equal(t, 1, val) testServer.Close() // When not existent @@ -254,7 +254,7 @@ func TestAdaptorFunction(t *testing.T) { a.setAPIServer(testServer.URL) _, err := a.Function("hello", "") - gobottest.Assert(t, err.Error(), "timeout") + assert.Errorf(t, err, "timeout") testServer.Close() } @@ -269,7 +269,7 @@ func TestAdaptorVariable(t *testing.T) { a.setAPIServer(testServer.URL) val, _ := a.Variable("variable_name") - gobottest.Assert(t, val, "1") + assert.Equal(t, "1", val) testServer.Close() // When float @@ -279,7 +279,7 @@ func TestAdaptorVariable(t *testing.T) { a.setAPIServer(testServer.URL) val, _ = a.Variable("variable_name") - gobottest.Assert(t, val, "1.1") + assert.Equal(t, "1.1", val) testServer.Close() // When int @@ -289,7 +289,7 @@ func TestAdaptorVariable(t *testing.T) { a.setAPIServer(testServer.URL) val, _ = a.Variable("variable_name") - gobottest.Assert(t, val, "1") + assert.Equal(t, "1", val) testServer.Close() // When bool @@ -299,7 +299,7 @@ func TestAdaptorVariable(t *testing.T) { a.setAPIServer(testServer.URL) val, _ = a.Variable("variable_name") - gobottest.Assert(t, val, "true") + assert.Equal(t, "true", val) testServer.Close() // When not existent @@ -309,7 +309,7 @@ func TestAdaptorVariable(t *testing.T) { a.setAPIServer(testServer.URL) _, err := a.Variable("not_existent") - gobottest.Assert(t, err.Error(), "Variable not found") + assert.Errorf(t, err, "Variable not found") testServer.Close() } @@ -317,10 +317,10 @@ func TestAdaptorVariable(t *testing.T) { func TestAdaptorSetAPIServer(t *testing.T) { a := initTestAdaptor() apiServer := "new_api_server" - gobottest.Refute(t, a.APIServer, apiServer) + assert.NotEqual(t, apiServer, a.APIServer) a.setAPIServer(apiServer) - gobottest.Assert(t, a.APIServer, apiServer) + assert.Equal(t, apiServer, a.APIServer) } func TestAdaptorDeviceURL(t *testing.T) { @@ -328,19 +328,19 @@ func TestAdaptorDeviceURL(t *testing.T) { a := initTestAdaptor() a.setAPIServer("http://server") a.DeviceID = "devID" - gobottest.Assert(t, a.deviceURL(), "http://server/v1/devices/devID") + assert.Equal(t, "http://server/v1/devices/devID", a.deviceURL()) // When APIServer is not set a = &Adaptor{name: "particleie", DeviceID: "myDevice", AccessToken: "token"} - gobottest.Assert(t, a.deviceURL(), "https://api.particle.io/v1/devices/myDevice") + assert.Equal(t, "https://api.particle.io/v1/devices/myDevice", a.deviceURL()) } func TestAdaptorPinLevel(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, a.pinLevel(1), "HIGH") - gobottest.Assert(t, a.pinLevel(0), "LOW") - gobottest.Assert(t, a.pinLevel(5), "LOW") + assert.Equal(t, "HIGH", a.pinLevel(1)) + assert.Equal(t, "LOW", a.pinLevel(0)) + assert.Equal(t, "LOW", a.pinLevel(5)) } func TestAdaptorPostToparticle(t *testing.T) { @@ -377,23 +377,23 @@ func TestAdaptorEventStream(t *testing.T) { return nil, nil, nil } _, _ = a.EventStream("all", "ping") - gobottest.Assert(t, url, "https://api.particle.io/v1/events/ping?access_token=token") + assert.Equal(t, "https://api.particle.io/v1/events/ping?access_token=token", url) _, _ = a.EventStream("devices", "ping") - gobottest.Assert(t, url, "https://api.particle.io/v1/devices/events/ping?access_token=token") + assert.Equal(t, "https://api.particle.io/v1/devices/events/ping?access_token=token", url) _, _ = a.EventStream("device", "ping") - gobottest.Assert(t, url, "https://api.particle.io/v1/devices/myDevice/events/ping?access_token=token") + assert.Equal(t, "https://api.particle.io/v1/devices/myDevice/events/ping?access_token=token", url) _, err := a.EventStream("nothing", "ping") - gobottest.Assert(t, err.Error(), "source param should be: all, devices or device") + assert.Errorf(t, err, "source param should be: all, devices or device") eventSource = func(u string) (chan eventsource.Event, chan error, error) { return nil, nil, errors.New("error connecting sse") } _, err = a.EventStream("devices", "") - gobottest.Assert(t, err.Error(), "error connecting sse") + assert.Errorf(t, err, "error connecting sse") eventChan := make(chan eventsource.Event) errorChan := make(chan error) @@ -403,5 +403,5 @@ func TestAdaptorEventStream(t *testing.T) { } _, err = a.EventStream("devices", "") - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } diff --git a/platforms/pebble/pebble_adaptor_test.go b/platforms/pebble/pebble_adaptor_test.go index 2ae333ab6..e15597863 100644 --- a/platforms/pebble/pebble_adaptor_test.go +++ b/platforms/pebble/pebble_adaptor_test.go @@ -3,8 +3,8 @@ package pebble import ( "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -15,14 +15,14 @@ func initTestAdaptor() *Adaptor { func TestAdaptor(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, a.Name(), "Pebble") + assert.Equal(t, "Pebble", a.Name()) } func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) } func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } diff --git a/platforms/pebble/pebble_driver_test.go b/platforms/pebble/pebble_driver_test.go index cbf0cd695..997afe9b6 100644 --- a/platforms/pebble/pebble_driver_test.go +++ b/platforms/pebble/pebble_driver_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*Driver)(nil) @@ -16,28 +16,28 @@ func initTestDriver() *Driver { func TestDriverStart(t *testing.T) { d := initTestDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestDriverHalt(t *testing.T) { d := initTestDriver() - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestDriver(t *testing.T) { d := initTestDriver() - gobottest.Assert(t, d.Name(), "Pebble") - gobottest.Assert(t, d.Connection().Name(), "Pebble") + assert.Equal(t, "Pebble", d.Name()) + assert.Equal(t, "Pebble", d.Connection().Name()) sem := make(chan bool) d.SendNotification("Hello") d.SendNotification("World") - gobottest.Assert(t, d.Messages[0], "Hello") - gobottest.Assert(t, d.PendingMessage(), "Hello") - gobottest.Assert(t, d.PendingMessage(), "World") - gobottest.Assert(t, d.PendingMessage(), "") + assert.Equal(t, "Hello", d.Messages[0]) + assert.Equal(t, "Hello", d.PendingMessage()) + assert.Equal(t, "World", d.PendingMessage()) + assert.Equal(t, "", d.PendingMessage()) _ = d.On(d.Event("button"), func(data interface{}) { sem <- true @@ -64,8 +64,8 @@ func TestDriver(t *testing.T) { } d.Command("send_notification")(map[string]interface{}{"message": "Hey buddy!"}) - gobottest.Assert(t, d.Messages[0], "Hey buddy!") + assert.Equal(t, "Hey buddy!", d.Messages[0]) message := d.Command("pending_message")(map[string]interface{}{}) - gobottest.Assert(t, message, "Hey buddy!") + assert.Equal(t, "Hey buddy!", message) } diff --git a/platforms/raspi/pwm_pin_test.go b/platforms/raspi/pwm_pin_test.go index df0cc2f6c..080d4a862 100644 --- a/platforms/raspi/pwm_pin_test.go +++ b/platforms/raspi/pwm_pin_test.go @@ -1,11 +1,10 @@ package raspi import ( - "errors" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -18,37 +17,37 @@ func TestPwmPin(t *testing.T) { pin := NewPWMPin(a, path, "1") - gobottest.Assert(t, pin.Export(), nil) - gobottest.Assert(t, pin.SetEnabled(true), nil) + assert.Nil(t, pin.Export()) + assert.Nil(t, pin.SetEnabled(true)) val, _ := pin.Polarity() - gobottest.Assert(t, val, true) + assert.True(t, val) - gobottest.Assert(t, pin.SetPolarity(false), nil) + assert.Nil(t, pin.SetPolarity(false)) val, _ = pin.Polarity() - gobottest.Assert(t, val, true) + assert.True(t, val) _, err := pin.Period() - gobottest.Assert(t, err, errors.New("Raspi PWM pin period not set")) - gobottest.Assert(t, pin.SetDutyCycle(10000), errors.New("Raspi PWM pin period not set")) + assert.Errorf(t, err, "Raspi PWM pin period not set") + assert.Errorf(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") - gobottest.Assert(t, pin.SetPeriod(20000000), nil) + assert.Nil(t, pin.SetPeriod(20000000)) period, _ := pin.Period() - gobottest.Assert(t, period, uint32(20000000)) - gobottest.Assert(t, pin.SetPeriod(10000000), errors.New("Cannot set the period of individual PWM pins on Raspi")) + assert.Equal(t, uint32(20000000), period) + assert.Errorf(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") dc, _ := pin.DutyCycle() - gobottest.Assert(t, dc, uint32(0)) + assert.Equal(t, uint32(0), dc) - gobottest.Assert(t, pin.SetDutyCycle(10000), nil) + assert.Nil(t, pin.SetDutyCycle(10000)) dc, _ = pin.DutyCycle() - gobottest.Assert(t, dc, uint32(10000)) + assert.Equal(t, uint32(10000), dc) - gobottest.Assert(t, pin.SetDutyCycle(999999999), errors.New("Duty cycle exceeds period")) + assert.Errorf(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") dc, _ = pin.DutyCycle() - gobottest.Assert(t, dc, uint32(10000)) + assert.Equal(t, uint32(10000), dc) - gobottest.Assert(t, pin.Unexport(), nil) + assert.Nil(t, pin.Unexport()) } diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index 560fed662..f73e3f2df 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -1,7 +1,6 @@ package raspi import ( - "errors" "fmt" "strings" "testing" @@ -10,11 +9,11 @@ import ( "strconv" "sync" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/drivers/spi" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -39,9 +38,9 @@ func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system. func TestName(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "RaspberryPi"), true) + assert.True(t, strings.HasPrefix(a.Name(), "RaspberryPi")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestGetDefaultBus(t *testing.T) { @@ -77,12 +76,12 @@ func TestGetDefaultBus(t *testing.T) { a := NewAdaptor() fs := a.sys.UseMockFilesystem([]string{infoFile}) fs.Files[infoFile].Contents = fmt.Sprintf(contentPattern, tc.revisionPart) - gobottest.Assert(t, a.revision, "") + assert.Equal(t, "", a.revision) //act, will read and refresh the revision gotBus := a.DefaultI2cBus() //assert - gobottest.Assert(t, a.revision, tc.wantRev) - gobottest.Assert(t, gotBus, tc.wantBus) + assert.Equal(t, tc.wantRev, a.revision) + assert.Equal(t, tc.wantBus, gotBus) }) } } @@ -103,7 +102,7 @@ func TestFinalize(t *testing.T) { _ = a.PwmWrite("7", 255) _, _ = a.GetI2cConnection(0xff, 0) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } func TestDigitalPWM(t *testing.T) { @@ -111,30 +110,30 @@ func TestDigitalPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockedPaths) a.PiBlasterPeriod = 20000000 - gobottest.Assert(t, a.PwmWrite("7", 4), nil) + assert.Nil(t, a.PwmWrite("7", 4)) pin, _ := a.PWMPin("7") period, _ := pin.Period() - gobottest.Assert(t, period, uint32(20000000)) + assert.Equal(t, uint32(20000000), period) - gobottest.Assert(t, a.PwmWrite("7", 255), nil) + assert.Nil(t, a.PwmWrite("7", 255)) - gobottest.Assert(t, strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0], "4=1") + assert.Equal(t, "4=1", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - gobottest.Assert(t, a.ServoWrite("11", 90), nil) + assert.Nil(t, a.ServoWrite("11", 90)) - gobottest.Assert(t, strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0], "17=0.5") + assert.Equal(t, "17=0.5", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - gobottest.Assert(t, a.PwmWrite("notexist", 1), errors.New("Not a valid pin")) - gobottest.Assert(t, a.ServoWrite("notexist", 1), errors.New("Not a valid pin")) + assert.Errorf(t, a.PwmWrite("notexist", 1), "Not a valid pin") + assert.Errorf(t, a.ServoWrite("notexist", 1), "Not a valid pin") pin, _ = a.PWMPin("12") period, _ = pin.Period() - gobottest.Assert(t, period, uint32(20000000)) + assert.Equal(t, uint32(20000000), period) - gobottest.Assert(t, pin.SetDutyCycle(1.5*1000*1000), nil) + assert.Nil(t, pin.SetDutyCycle(1.5*1000*1000)) - gobottest.Assert(t, strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0], "18=0.075") + assert.Equal(t, "18=0.075", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) } func TestDigitalIO(t *testing.T) { @@ -149,19 +148,19 @@ func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockedPaths) err := a.DigitalWrite("7", 1) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio4/value"].Contents, "1") + assert.Nil(t, err) + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio4/value"].Contents) a.revision = "2" err = a.DigitalWrite("13", 1) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) i, err := a.DigitalRead("13") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, i, 1) + assert.Nil(t, err) + assert.Equal(t, 1, i) - gobottest.Assert(t, a.DigitalWrite("notexist", 1), errors.New("Not a valid pin")) - gobottest.Assert(t, a.Finalize(), nil) + assert.Errorf(t, a.DigitalWrite("notexist", 1), "Not a valid pin") + assert.Nil(t, a.Finalize()) } func TestDigitalPinConcurrency(t *testing.T) { @@ -193,24 +192,24 @@ func TestPWMPin(t *testing.T) { panic(err) } - gobottest.Assert(t, len(a.pwmPins), 0) + assert.Equal(t, 0, len(a.pwmPins)) a.revision = "3" firstSysPin, err := a.PWMPin("35") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.pwmPins), 1) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.pwmPins)) secondSysPin, err := a.PWMPin("35") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.pwmPins), 1) - gobottest.Assert(t, firstSysPin, secondSysPin) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.pwmPins)) + assert.Equal(t, secondSysPin, firstSysPin) otherSysPin, err := a.PWMPin("36") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.pwmPins), 2) - gobottest.Refute(t, firstSysPin, otherSysPin) + assert.Nil(t, err) + assert.Equal(t, 2, len(a.pwmPins)) + assert.NotEqual(t, otherSysPin, firstSysPin) } func TestPWMPinsReConnect(t *testing.T) { @@ -222,27 +221,27 @@ func TestPWMPinsReConnect(t *testing.T) { } _, err := a.PWMPin("35") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.pwmPins), 1) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, err) + assert.Equal(t, 1, len(a.pwmPins)) + assert.Nil(t, a.Finalize()) // act err = a.Connect() // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.pwmPins), 0) + assert.Nil(t, err) + assert.Equal(t, 0, len(a.pwmPins)) _, _ = a.PWMPin("35") _, err = a.PWMPin("36") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, len(a.pwmPins), 2) + assert.Nil(t, err) + assert.Equal(t, 2, len(a.pwmPins)) } func TestSpiDefaultValues(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.SpiDefaultBusNumber(), 0) - gobottest.Assert(t, a.SpiDefaultChipNumber(), 0) - gobottest.Assert(t, a.SpiDefaultMode(), 0) - gobottest.Assert(t, a.SpiDefaultMaxSpeed(), int64(500000)) + assert.Equal(t, 0, a.SpiDefaultBusNumber()) + assert.Equal(t, 0, a.SpiDefaultChipNumber()) + assert.Equal(t, 0, a.SpiDefaultMode()) + assert.Equal(t, int64(500000), a.SpiDefaultMaxSpeed()) } func TestI2cDefaultBus(t *testing.T) { @@ -251,10 +250,10 @@ func TestI2cDefaultBus(t *testing.T) { a.sys.UseMockSyscall() a.revision = "0" - gobottest.Assert(t, a.DefaultI2cBus(), 0) + assert.Equal(t, 0, a.DefaultI2cBus()) a.revision = "2" - gobottest.Assert(t, a.DefaultI2cBus(), 1) + assert.Equal(t, 1, a.DefaultI2cBus()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -262,16 +261,16 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = con.Write([]byte{0xbf}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) fs.WithCloseError = true // act err = a.Finalize() // assert - gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true) + assert.Contains(t, err.Error(), "close error") } func Test_validateSpiBusNumber(t *testing.T) { @@ -301,7 +300,7 @@ func Test_validateSpiBusNumber(t *testing.T) { // act err := a.validateSpiBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } @@ -333,7 +332,7 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateI2cBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } diff --git a/platforms/rockpi/rockpi_adaptor_test.go b/platforms/rockpi/rockpi_adaptor_test.go index 1e3186298..121777a13 100644 --- a/platforms/rockpi/rockpi_adaptor_test.go +++ b/platforms/rockpi/rockpi_adaptor_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2/system" ) @@ -17,7 +17,7 @@ func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system. func TestDefaultI2cBus(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem([]string{}) - gobottest.Assert(t, a.DefaultI2cBus(), 7) + assert.Equal(t, 7, a.DefaultI2cBus()) } func Test_getPinTranslatorFunction(t *testing.T) { @@ -63,9 +63,9 @@ func Test_getPinTranslatorFunction(t *testing.T) { // act chip, line, err := fn(tc.pin) // assert - gobottest.Assert(t, chip, "") - gobottest.Assert(t, err, tc.expectedErr) - gobottest.Assert(t, line, tc.expectedLine) + assert.Equal(t, "", chip) + assert.Equal(t, tc.expectedErr, err) + assert.Equal(t, tc.expectedLine, line) }) } } @@ -97,7 +97,7 @@ func Test_validateSpiBusNumber(t *testing.T) { // act err := a.validateSpiBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.expectedErr) + assert.Equal(t, tc.expectedErr, err) }) } } @@ -132,7 +132,7 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateI2cBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } diff --git a/platforms/sphero/bb8/bb8_driver_test.go b/platforms/sphero/bb8/bb8_driver_test.go index a56ed5155..e5ed22afa 100644 --- a/platforms/sphero/bb8/bb8_driver_test.go +++ b/platforms/sphero/bb8/bb8_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*BB8Driver)(nil) @@ -17,13 +17,13 @@ func initTestBB8Driver() *BB8Driver { func TestBB8Driver(t *testing.T) { d := initTestBB8Driver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "BB8"), true) + assert.True(t, strings.HasPrefix(d.Name(), "BB8")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestBB8DriverStartAndHalt(t *testing.T) { d := initTestBB8Driver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } diff --git a/platforms/sphero/ollie/ollie_driver_test.go b/platforms/sphero/ollie/ollie_driver_test.go index 847c48dcf..472cc55bf 100644 --- a/platforms/sphero/ollie/ollie_driver_test.go +++ b/platforms/sphero/ollie/ollie_driver_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/platforms/sphero" ) @@ -21,13 +21,13 @@ func initTestOllieDriver() *Driver { func TestOllieDriver(t *testing.T) { d := initTestOllieDriver() d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestOllieDriverStartAndHalt(t *testing.T) { d := initTestOllieDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } func TestLocatorData(t *testing.T) { @@ -53,7 +53,7 @@ func TestLocatorData(t *testing.T) { packet := []byte{0xFF, 0xFF, 0x00, 0x00, 0x0B, point.x1, point.x2, point.y1, point.y2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} d.GetLocatorData(func(p Point2D) { - gobottest.Assert(t, p.Y, point.y) + assert.Equal(t, point.y, p.Y) }) d.HandleResponses(packet, nil) } @@ -68,7 +68,7 @@ func TestDataStreaming(t *testing.T) { _ = d.On("sensordata", func(data interface{}) { cont := data.(DataStreamingPacket) fmt.Printf("got streaming packet: %+v \n", cont) - gobottest.Assert(t, cont.RawAccX, int16(10)) + assert.Equal(t, int16(10), cont.RawAccX) response = true }) diff --git a/platforms/sphero/sphero_adaptor_test.go b/platforms/sphero/sphero_adaptor_test.go index cd9403359..ea9224a9f 100644 --- a/platforms/sphero/sphero_adaptor_test.go +++ b/platforms/sphero/sphero_adaptor_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) @@ -56,49 +56,49 @@ func initTestSpheroAdaptor() (*Adaptor, *nullReadWriteCloser) { func TestSpheroAdaptorName(t *testing.T) { a, _ := initTestSpheroAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Sphero"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Sphero")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestSpheroAdaptor(t *testing.T) { a, _ := initTestSpheroAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Sphero"), true) - gobottest.Assert(t, a.Port(), "/dev/null") + assert.True(t, strings.HasPrefix(a.Name(), "Sphero")) + assert.Equal(t, "/dev/null", a.Port()) } func TestSpheroAdaptorReconnect(t *testing.T) { a, _ := initTestSpheroAdaptor() _ = a.Connect() - gobottest.Assert(t, a.connected, true) + assert.True(t, a.connected) _ = a.Reconnect() - gobottest.Assert(t, a.connected, true) + assert.True(t, a.connected) _ = a.Disconnect() - gobottest.Assert(t, a.connected, false) + assert.False(t, a.connected) _ = a.Reconnect() - gobottest.Assert(t, a.connected, true) + assert.True(t, a.connected) } func TestSpheroAdaptorFinalize(t *testing.T) { a, rwc := initTestSpheroAdaptor() _ = a.Connect() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) rwc.testAdaptorClose = func() error { return errors.New("close error") } a.connected = true - gobottest.Assert(t, a.Finalize(), errors.New("close error")) + assert.Errorf(t, a.Finalize(), "close error") } func TestSpheroAdaptorConnect(t *testing.T) { a, _ := initTestSpheroAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) a.connect = func(string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - gobottest.Assert(t, a.Connect(), errors.New("connect error")) + assert.Errorf(t, a.Connect(), "connect error") } diff --git a/platforms/sphero/sphero_driver_test.go b/platforms/sphero/sphero_driver_test.go index 28a3d79f7..a3d5df1ca 100644 --- a/platforms/sphero/sphero_driver_test.go +++ b/platforms/sphero/sphero_driver_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*SpheroDriver)(nil) @@ -20,9 +20,9 @@ func initTestSpheroDriver() *SpheroDriver { func TestSpheroDriverName(t *testing.T) { d := initTestSpheroDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Sphero"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Sphero")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestSpheroDriver(t *testing.T) { @@ -32,65 +32,65 @@ func TestSpheroDriver(t *testing.T) { ret = d.Command("SetRGB")( map[string]interface{}{"r": 100.0, "g": 100.0, "b": 100.0}, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("Roll")( map[string]interface{}{"speed": 100.0, "heading": 100.0}, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("SetBackLED")( map[string]interface{}{"level": 100.0}, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("ConfigureLocator")( map[string]interface{}{"Flags": 1.0, "X": 100.0, "Y": 100.0, "YawTare": 100.0}, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("SetHeading")( map[string]interface{}{"heading": 100.0}, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("SetRotationRate")( map[string]interface{}{"level": 100.0}, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("SetStabilization")( map[string]interface{}{"enable": true}, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("SetStabilization")( map[string]interface{}{"enable": false}, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("Stop")(nil) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) ret = d.Command("GetRGB")(nil) - gobottest.Assert(t, ret.([]byte), []byte{}) + assert.Equal(t, []byte{}, ret.([]byte)) ret = d.Command("ReadLocator")(nil) - gobottest.Assert(t, ret, []int16{}) + assert.Equal(t, []int16{}, ret) - gobottest.Assert(t, strings.HasPrefix(d.Name(), "Sphero"), true) - gobottest.Assert(t, strings.HasPrefix(d.Connection().Name(), "Sphero"), true) + assert.True(t, strings.HasPrefix(d.Name(), "Sphero")) + assert.True(t, strings.HasPrefix(d.Connection().Name(), "Sphero")) } func TestSpheroDriverStart(t *testing.T) { d := initTestSpheroDriver() - gobottest.Assert(t, d.Start(), nil) + assert.Nil(t, d.Start()) } func TestSpheroDriverHalt(t *testing.T) { d := initTestSpheroDriver() d.adaptor().connected = true - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Halt()) } func TestSpheroDriverSetDataStreaming(t *testing.T) { @@ -102,7 +102,7 @@ func TestSpheroDriverSetDataStreaming(t *testing.T) { buf := new(bytes.Buffer) _ = binary.Write(buf, binary.BigEndian, DefaultDataStreamingConfig()) - gobottest.Assert(t, data.body, buf.Bytes()) + assert.Equal(t, buf.Bytes(), data.body) ret := d.Command("SetDataStreaming")( map[string]interface{}{ @@ -113,14 +113,14 @@ func TestSpheroDriverSetDataStreaming(t *testing.T) { "Mask2": 400.0, }, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) data = <-d.packetChannel dconfig := DataStreamingConfig{N: 100, M: 200, Mask: 300, Pcnt: 255, Mask2: 400} buf = new(bytes.Buffer) _ = binary.Write(buf, binary.BigEndian, dconfig) - gobottest.Assert(t, data.body, buf.Bytes()) + assert.Equal(t, buf.Bytes(), data.body) } func TestConfigureLocator(t *testing.T) { @@ -131,7 +131,7 @@ func TestConfigureLocator(t *testing.T) { buf := new(bytes.Buffer) _ = binary.Write(buf, binary.BigEndian, DefaultLocatorConfig()) - gobottest.Assert(t, data.body, buf.Bytes()) + assert.Equal(t, buf.Bytes(), data.body) ret := d.Command("ConfigureLocator")( map[string]interface{}{ @@ -141,14 +141,14 @@ func TestConfigureLocator(t *testing.T) { "YawTare": 0.0, }, ) - gobottest.Assert(t, ret, nil) + assert.Nil(t, ret) data = <-d.packetChannel lconfig := LocatorConfig{Flags: 1, X: 100, Y: 100, YawTare: 0} buf = new(bytes.Buffer) _ = binary.Write(buf, binary.BigEndian, lconfig) - gobottest.Assert(t, data.body, buf.Bytes()) + assert.Equal(t, buf.Bytes(), data.body) } func TestCalculateChecksum(t *testing.T) { diff --git a/platforms/sphero/sprkplus/sprkplus_driver_test.go b/platforms/sphero/sprkplus/sprkplus_driver_test.go index 6bb1ed2d2..0c28c86ea 100644 --- a/platforms/sphero/sprkplus/sprkplus_driver_test.go +++ b/platforms/sphero/sprkplus/sprkplus_driver_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Driver = (*SPRKPlusDriver)(nil) @@ -17,13 +17,13 @@ func initTestSPRKPlusDriver() *SPRKPlusDriver { func TestSPRKPlusDriver(t *testing.T) { d := initTestSPRKPlusDriver() - gobottest.Assert(t, strings.HasPrefix(d.Name(), "SPRK"), true) + assert.True(t, strings.HasPrefix(d.Name(), "SPRK")) d.SetName("NewName") - gobottest.Assert(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestSPRKPlusDriverStartAndHalt(t *testing.T) { d := initTestSPRKPlusDriver() - gobottest.Assert(t, d.Start(), nil) - gobottest.Assert(t, d.Halt(), nil) + assert.Nil(t, d.Start()) + assert.Nil(t, d.Halt()) } diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index c25ae6145..9509388e7 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -5,10 +5,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -74,9 +74,9 @@ func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system. func TestName(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Tinker Board"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Tinker Board")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestDigitalIO(t *testing.T) { @@ -84,14 +84,14 @@ func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) _ = a.DigitalWrite("7", 1) - gobottest.Assert(t, fs.Files[gpio17Path+"value"].Contents, "1") + assert.Equal(t, "1", fs.Files[gpio17Path+"value"].Contents) fs.Files[gpio160Path+"value"].Contents = "1" i, _ := a.DigitalRead("10") - gobottest.Assert(t, i, 1) + assert.Equal(t, 1, i) - gobottest.Assert(t, a.DigitalWrite("99", 1), fmt.Errorf("'99' is not a valid id for a digital pin")) - gobottest.Assert(t, a.Finalize(), nil) + assert.Errorf(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.Nil(t, a.Finalize()) } func TestInvalidPWMPin(t *testing.T) { @@ -99,16 +99,16 @@ func TestInvalidPWMPin(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("666", 42) - gobottest.Assert(t, err.Error(), "'666' is not a valid id for a PWM pin") + assert.Errorf(t, err, "'666' is not a valid id for a PWM pin") err = a.ServoWrite("666", 120) - gobottest.Assert(t, err.Error(), "'666' is not a valid id for a PWM pin") + assert.Errorf(t, err, "'666' is not a valid id for a PWM pin") err = a.PwmWrite("3", 42) - gobottest.Assert(t, err.Error(), "'3' is not a valid id for a PWM pin") + assert.Errorf(t, err, "'3' is not a valid id for a PWM pin") err = a.ServoWrite("3", 120) - gobottest.Assert(t, err.Error(), "'3' is not a valid id for a PWM pin") + assert.Errorf(t, err, "'3' is not a valid id for a PWM pin") } func TestPwmWrite(t *testing.T) { @@ -116,24 +116,24 @@ func TestPwmWrite(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("33", 100) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files[pwmExportPath].Contents, "0") - gobottest.Assert(t, fs.Files[pwmEnablePath].Contents, "1") - gobottest.Assert(t, fs.Files[pwmPeriodPath].Contents, fmt.Sprintf("%d", 10000000)) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, "3921568") - gobottest.Assert(t, fs.Files[pwmPolarityPath].Contents, "normal") + assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) + assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) + assert.Equal(t, fmt.Sprintf("%d", 10000000), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.ServoWrite("33", 0) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, "500000") + assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("33", 180) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, "2000000") - gobottest.Assert(t, a.Finalize(), nil) + assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) + assert.Nil(t, a.Finalize()) } func TestSetPeriod(t *testing.T) { @@ -145,25 +145,25 @@ func TestSetPeriod(t *testing.T) { // act err := a.SetPeriod("33", newPeriod) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files[pwmExportPath].Contents, "0") - gobottest.Assert(t, fs.Files[pwmEnablePath].Contents, "1") - gobottest.Assert(t, fs.Files[pwmPeriodPath].Contents, fmt.Sprintf("%d", newPeriod)) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, "0") - gobottest.Assert(t, fs.Files[pwmPolarityPath].Contents, "normal") + assert.Nil(t, err) + assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) + assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) + assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, "0", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("33", 127) // 127 is a little bit smaller than 50% of period - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, fmt.Sprintf("%d", 1270000)) + assert.Nil(t, err) + assert.Equal(t, fmt.Sprintf("%d", 1270000), fs.Files[pwmDutyCyclePath].Contents) newPeriod = newPeriod / 10 // act err = a.SetPeriod("33", newPeriod) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, fmt.Sprintf("%d", 127000)) + assert.Nil(t, err) + assert.Equal(t, fmt.Sprintf("%d", 127000), fs.Files[pwmDutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value newPeriod = newPeriod * 20 @@ -172,46 +172,46 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("33", newPeriod) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files[pwmDutyCyclePath].Contents, fmt.Sprintf("%d", 2540000)) + assert.Nil(t, err) + assert.Equal(t, fmt.Sprintf("%d", 2540000), fs.Files[pwmDutyCyclePath].Contents) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - gobottest.Assert(t, a.DigitalWrite("7", 1), nil) + assert.Nil(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true err := a.Finalize() - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) - gobottest.Assert(t, a.PwmWrite("33", 1), nil) + assert.Nil(t, a.PwmWrite("33", 1)) fs.WithWriteError = true err := a.Finalize() - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestSpiDefaultValues(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.SpiDefaultBusNumber(), 0) - gobottest.Assert(t, a.SpiDefaultChipNumber(), 0) - gobottest.Assert(t, a.SpiDefaultMode(), 0) - gobottest.Assert(t, a.SpiDefaultBitCount(), 8) - gobottest.Assert(t, a.SpiDefaultMaxSpeed(), int64(500000)) + assert.Equal(t, 0, a.SpiDefaultBusNumber()) + assert.Equal(t, 0, a.SpiDefaultChipNumber()) + assert.Equal(t, 0, a.SpiDefaultMode()) + assert.Equal(t, 8, a.SpiDefaultBitCount()) + assert.Equal(t, int64(500000), a.SpiDefaultMaxSpeed()) } func TestI2cDefaultBus(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.DefaultI2cBus(), 1) + assert.Equal(t, 1, a.DefaultI2cBus()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -219,16 +219,16 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-4"}) - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 4) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = con.Write([]byte{0xbf}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) fs.WithCloseError = true // act err = a.Finalize() // assert - gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true) + assert.Contains(t, err.Error(), "close error") } func Test_validateSpiBusNumber(t *testing.T) { @@ -262,7 +262,7 @@ func Test_validateSpiBusNumber(t *testing.T) { // act err := a.validateSpiBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } @@ -303,7 +303,7 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateI2cBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } @@ -343,9 +343,9 @@ func Test_translateDigitalPin(t *testing.T) { // act chip, line, err := a.translateDigitalPin(tc.pin) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, chip, tc.wantChip) - gobottest.Assert(t, line, tc.wantLine) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantChip, chip) + assert.Equal(t, tc.wantLine, line) }) } } @@ -422,9 +422,9 @@ func Test_translatePWMPin(t *testing.T) { // act dir, channel, err := a.translatePWMPin(tc.pin) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, dir, tc.wantDir) - gobottest.Assert(t, channel, tc.wantChannel) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantDir, dir) + assert.Equal(t, tc.wantChannel, channel) }) } } diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index 8b76f9766..998df6882 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -1,16 +1,15 @@ package up2 import ( - "errors" "fmt" "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/drivers/spi" - "gobot.io/x/gobot/v2/gobottest" "gobot.io/x/gobot/v2/system" ) @@ -55,29 +54,29 @@ func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system. func TestName(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "UP2"), true) + assert.True(t, strings.HasPrefix(a.Name(), "UP2")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) _ = a.DigitalWrite("7", 1) - gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio462/value"].Contents, "1") + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio462/value"].Contents) fs.Files["/sys/class/gpio/gpio432/value"].Contents = "1" i, _ := a.DigitalRead("13") - gobottest.Assert(t, i, 1) + assert.Equal(t, 1, i) _ = a.DigitalWrite("green", 1) - gobottest.Assert(t, - fs.Files["/sys/class/leds/upboard:green:/brightness"].Contents, + assert.Equal(t, "1", + fs.Files["/sys/class/leds/upboard:green:/brightness"].Contents, ) - gobottest.Assert(t, a.DigitalWrite("99", 1), errors.New("'99' is not a valid id for a digital pin")) - gobottest.Assert(t, a.Finalize(), nil) + assert.Errorf(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.Nil(t, a.Finalize()) } func TestPWM(t *testing.T) { @@ -86,38 +85,38 @@ func TestPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" err := a.PwmWrite("32", 100) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/export"].Contents, "0") - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents, "1") - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "3921568") - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") // pwmPeriodDefault - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents, "normal") + assert.Equal(t, "0", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) + assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents) + assert.Equal(t, "3921568", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) + assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault + assert.Equal(t, "normal", fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents) err = a.ServoWrite("32", 0) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "500000") - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") + assert.Equal(t, "500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) + assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) err = a.ServoWrite("32", 180) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "2000000") - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents, "10000000") + assert.Equal(t, "2000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) + assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - gobottest.Assert(t, a.DigitalWrite("7", 1), nil) + assert.Nil(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true err := a.Finalize() - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestFinalizeErrorAfterPWM(t *testing.T) { @@ -125,20 +124,20 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" - gobottest.Assert(t, a.PwmWrite("32", 1), nil) + assert.Nil(t, a.PwmWrite("32", 1)) fs.WithWriteError = true err := a.Finalize() - gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) + assert.Contains(t, err.Error(), "write error") } func TestSpiDefaultValues(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.SpiDefaultBusNumber(), 0) - gobottest.Assert(t, a.SpiDefaultMode(), 0) - gobottest.Assert(t, a.SpiDefaultMaxSpeed(), int64(500000)) + assert.Equal(t, 0, a.SpiDefaultBusNumber()) + assert.Equal(t, 0, a.SpiDefaultMode()) + assert.Equal(t, int64(500000), a.SpiDefaultMaxSpeed()) } func Test_validateSpiBusNumber(t *testing.T) { @@ -168,14 +167,14 @@ func Test_validateSpiBusNumber(t *testing.T) { // act err := a.validateSpiBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } func TestI2cDefaultBus(t *testing.T) { a := NewAdaptor() - gobottest.Assert(t, a.DefaultI2cBus(), 5) + assert.Equal(t, 5, a.DefaultI2cBus()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -183,16 +182,16 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-5"}) - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 5) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = con.Write([]byte{0xbf}) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) fs.WithCloseError = true // act err = a.Finalize() // assert - gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true) + assert.Contains(t, err.Error(), "close error") } func Test_validateI2cBusNumber(t *testing.T) { @@ -226,7 +225,7 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateI2cBusNumber(tc.busNr) // assert - gobottest.Assert(t, err, tc.wantErr) + assert.Equal(t, tc.wantErr, err) }) } } @@ -267,9 +266,9 @@ func Test_translatePWMPin(t *testing.T) { // act dir, channel, err := a.translatePWMPin(name) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, dir, tc.wantDir) - gobottest.Assert(t, channel, tc.wantChannel) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantDir, dir) + assert.Equal(t, tc.wantChannel, channel) }) } } diff --git a/robot_test.go b/robot_test.go index 7bee3324a..4d34634f6 100644 --- a/robot_test.go +++ b/robot_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestRobotConnectionEach(t *testing.T) { @@ -14,7 +14,7 @@ func TestRobotConnectionEach(t *testing.T) { r.Connections().Each(func(conn Connection) { i++ }) - gobottest.Assert(t, r.Connections().Len(), i) + assert.Equal(t, i, r.Connections().Len()) } func TestRobotToJSON(t *testing.T) { @@ -23,25 +23,25 @@ func TestRobotToJSON(t *testing.T) { return nil }) json := NewJSONRobot(r) - gobottest.Assert(t, len(json.Devices), r.Devices().Len()) - gobottest.Assert(t, len(json.Commands), len(r.Commands())) + assert.Equal(t, r.Devices().Len(), len(json.Devices)) + assert.Equal(t, len(r.Commands()), len(json.Commands)) } func TestRobotDevicesToJSON(t *testing.T) { r := newTestRobot("Robot99") json := NewJSONRobot(r) - gobottest.Assert(t, len(json.Devices), r.Devices().Len()) - gobottest.Assert(t, json.Devices[0].Name, "Device1") - gobottest.Assert(t, json.Devices[0].Driver, "*gobot.testDriver") - gobottest.Assert(t, json.Devices[0].Connection, "Connection1") - gobottest.Assert(t, len(json.Devices[0].Commands), 1) + assert.Equal(t, r.Devices().Len(), len(json.Devices)) + assert.Equal(t, "Device1", json.Devices[0].Name) + assert.Equal(t, "*gobot.testDriver", json.Devices[0].Driver) + assert.Equal(t, "Connection1", json.Devices[0].Connection) + assert.Equal(t, 1, len(json.Devices[0].Commands)) } func TestRobotStart(t *testing.T) { r := newTestRobot("Robot99") - gobottest.Assert(t, r.Start(), nil) - gobottest.Assert(t, r.Stop(), nil) - gobottest.Assert(t, r.Running(), false) + assert.Nil(t, r.Start()) + assert.Nil(t, r.Stop()) + assert.False(t, r.Running()) } func TestRobotStartAutoRun(t *testing.T) { @@ -55,13 +55,13 @@ func TestRobotStartAutoRun(t *testing.T) { ) go func() { - gobottest.Assert(t, r.Start(), nil) + assert.Nil(t, r.Start()) }() time.Sleep(10 * time.Millisecond) - gobottest.Assert(t, r.Running(), true) + assert.True(t, r.Running()) // stop it - gobottest.Assert(t, r.Stop(), nil) - gobottest.Assert(t, r.Running(), false) + assert.Nil(t, r.Stop()) + assert.False(t, r.Running()) } diff --git a/system/digitalpin_access_test.go b/system/digitalpin_access_test.go index ef822a857..58e5f4292 100644 --- a/system/digitalpin_access_test.go +++ b/system/digitalpin_access_test.go @@ -3,7 +3,7 @@ package system import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func Test_isSupportedSysfs(t *testing.T) { @@ -12,7 +12,7 @@ func Test_isSupportedSysfs(t *testing.T) { // act got := dpa.isSupported() // assert - gobottest.Assert(t, got, true) + assert.True(t, got) } func Test_isSupportedGpiod(t *testing.T) { @@ -37,7 +37,7 @@ func Test_isSupportedGpiod(t *testing.T) { // act got := dpa.isSupported() // assert - gobottest.Assert(t, got, tc.want) + assert.Equal(t, tc.want, got) }) } } @@ -48,10 +48,10 @@ func Test_createAsSysfs(t *testing.T) { // act dp := dpa.createPin("chip", 8) // assert - gobottest.Refute(t, dp, nil) + assert.NotNil(t, dp) dps := dp.(*digitalPinSysfs) // chip is dropped - gobottest.Assert(t, dps.label, "gpio8") + assert.Equal(t, "gpio8", dps.label) } func Test_createAsGpiod(t *testing.T) { @@ -65,10 +65,10 @@ func Test_createAsGpiod(t *testing.T) { // act dp := dpa.createPin(chip, 18) // assert - gobottest.Refute(t, dp, nil) + assert.NotNil(t, dp) dpg := dp.(*digitalPinGpiod) - gobottest.Assert(t, dpg.label, label) - gobottest.Assert(t, dpg.chipName, chip) + assert.Equal(t, label, dpg.label) + assert.Equal(t, chip, dpg.chipName) } func Test_createPinWithOptionsSysfs(t *testing.T) { @@ -82,7 +82,7 @@ func Test_createPinWithOptionsSysfs(t *testing.T) { dp := dpa.createPin("", 9, WithPinLabel(label)) dps := dp.(*digitalPinSysfs) // assert - gobottest.Assert(t, dps.label, label) + assert.Equal(t, label, dps.label) } func Test_createPinWithOptionsGpiod(t *testing.T) { @@ -96,7 +96,7 @@ func Test_createPinWithOptionsGpiod(t *testing.T) { dp := dpa.createPin("", 19, WithPinLabel(label)) dpg := dp.(*digitalPinGpiod) // assert - gobottest.Assert(t, dpg.label, label) + assert.Equal(t, label, dpg.label) // test fallback for empty chip - gobottest.Assert(t, dpg.chipName, "gpiochip0") + assert.Equal(t, "gpiochip0", dpg.chipName) } diff --git a/system/digitalpin_config_test.go b/system/digitalpin_config_test.go index 961543837..808286333 100644 --- a/system/digitalpin_config_test.go +++ b/system/digitalpin_config_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.DigitalPinOptioner = (*digitalPinConfig)(nil) @@ -18,10 +18,10 @@ func Test_newDigitalPinConfig(t *testing.T) { // act d := newDigitalPinConfig(label) // assert - gobottest.Refute(t, d, nil) - gobottest.Assert(t, d.label, label) - gobottest.Assert(t, d.direction, IN) - gobottest.Assert(t, d.outInitialState, 0) + assert.NotNil(t, d) + assert.Equal(t, label, d.label) + assert.Equal(t, IN, d.direction) + assert.Equal(t, 0, d.outInitialState) } func Test_newDigitalPinConfigWithOption(t *testing.T) { @@ -30,8 +30,8 @@ func Test_newDigitalPinConfigWithOption(t *testing.T) { // act d := newDigitalPinConfig("not used", WithPinLabel(label)) // assert - gobottest.Refute(t, d, nil) - gobottest.Assert(t, d.label, label) + assert.NotNil(t, d) + assert.Equal(t, label, d.label) } func TestWithPinLabel(t *testing.T) { @@ -58,8 +58,8 @@ func TestWithPinLabel(t *testing.T) { // act got := WithPinLabel(tc.setLabel)(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.label, tc.setLabel) + assert.Equal(t, tc.want, got) + assert.Equal(t, tc.setLabel, dpc.label) }) } } @@ -92,9 +92,9 @@ func TestWithPinDirectionOutput(t *testing.T) { // act got := WithPinDirectionOutput(newVal)(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.direction, "out") - gobottest.Assert(t, dpc.outInitialState, tc.wantVal) + assert.Equal(t, tc.want, got) + assert.Equal(t, "out", dpc.direction) + assert.Equal(t, tc.wantVal, dpc.outInitialState) }) } } @@ -120,9 +120,9 @@ func TestWithPinDirectionInput(t *testing.T) { // act got := WithPinDirectionInput()(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.direction, "in") - gobottest.Assert(t, dpc.outInitialState, initValOut) + assert.Equal(t, tc.want, got) + assert.Equal(t, "in", dpc.direction) + assert.Equal(t, initValOut, dpc.outInitialState) }) } } @@ -147,8 +147,8 @@ func TestWithPinActiveLow(t *testing.T) { // act got := WithPinActiveLow()(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.activeLow, true) + assert.Equal(t, tc.want, got) + assert.True(t, dpc.activeLow) }) } } @@ -174,8 +174,8 @@ func TestWithPinPullDown(t *testing.T) { // act got := WithPinPullDown()(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.bias, digitalPinBiasPullDown) + assert.Equal(t, tc.want, got) + assert.Equal(t, digitalPinBiasPullDown, dpc.bias) }) } } @@ -201,8 +201,8 @@ func TestWithPinPullUp(t *testing.T) { // act got := WithPinPullUp()(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.bias, digitalPinBiasPullUp) + assert.Equal(t, tc.want, got) + assert.Equal(t, digitalPinBiasPullUp, dpc.bias) }) } } @@ -232,8 +232,8 @@ func TestWithPinOpenDrain(t *testing.T) { // act got := WithPinOpenDrain()(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.drive, digitalPinDriveOpenDrain) + assert.Equal(t, tc.want, got) + assert.Equal(t, digitalPinDriveOpenDrain, dpc.drive) }) } } @@ -263,8 +263,8 @@ func TestWithPinOpenSource(t *testing.T) { // act got := WithPinOpenSource()(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.drive, digitalPinDriveOpenSource) + assert.Equal(t, tc.want, got) + assert.Equal(t, digitalPinDriveOpenSource, dpc.drive) }) } } @@ -294,8 +294,8 @@ func TestWithPinDebounce(t *testing.T) { // act got := WithPinDebounce(newVal)(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.debouncePeriod, newVal) + assert.Equal(t, tc.want, got) + assert.Equal(t, newVal, dpc.debouncePeriod) }) } } @@ -312,6 +312,7 @@ func TestWithPinEventOnFallingEdge(t *testing.T) { }{ "no_change": { oldEdge: newVal, + want: false, }, "change": { oldEdge: oldVal, @@ -326,9 +327,13 @@ func TestWithPinEventOnFallingEdge(t *testing.T) { // act got := WithPinEventOnFallingEdge(handler)(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.edge, newVal) - gobottest.Refute(t, dpc.edgeEventHandler, nil) + assert.Equal(t, tc.want, got) + assert.Equal(t, newVal, dpc.edge) + if tc.want { + assert.NotNil(t, dpc.edgeEventHandler) + } else { + assert.Nil(t, dpc.edgeEventHandler) + } }) } } @@ -345,6 +350,7 @@ func TestWithPinEventOnRisingEdge(t *testing.T) { }{ "no_change": { oldEdge: newVal, + want: false, }, "change": { oldEdge: oldVal, @@ -359,9 +365,13 @@ func TestWithPinEventOnRisingEdge(t *testing.T) { // act got := WithPinEventOnRisingEdge(handler)(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.edge, newVal) - gobottest.Refute(t, dpc.edgeEventHandler, nil) + assert.Equal(t, tc.want, got) + assert.Equal(t, newVal, dpc.edge) + if tc.want { + assert.NotNil(t, dpc.edgeEventHandler) + } else { + assert.Nil(t, dpc.edgeEventHandler) + } }) } } @@ -378,6 +388,7 @@ func TestWithPinEventOnBothEdges(t *testing.T) { }{ "no_change": { oldEdge: newVal, + want: false, }, "change": { oldEdge: oldVal, @@ -392,9 +403,13 @@ func TestWithPinEventOnBothEdges(t *testing.T) { // act got := WithPinEventOnBothEdges(handler)(dpc) // assert - gobottest.Assert(t, got, tc.want) - gobottest.Assert(t, dpc.edge, newVal) - gobottest.Refute(t, dpc.edgeEventHandler, nil) + assert.Equal(t, tc.want, got) + assert.Equal(t, newVal, dpc.edge) + if tc.want { + assert.NotNil(t, dpc.edgeEventHandler) + } else { + assert.Nil(t, dpc.edgeEventHandler) + } }) } } diff --git a/system/digitalpin_gpiod_test.go b/system/digitalpin_gpiod_test.go index 6ed077469..78e69f78a 100644 --- a/system/digitalpin_gpiod_test.go +++ b/system/digitalpin_gpiod_test.go @@ -2,11 +2,10 @@ package system import ( "fmt" - "strings" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.DigitalPinner = (*digitalPinGpiod)(nil) @@ -24,12 +23,12 @@ func Test_newDigitalPinGpiod(t *testing.T) { // act d := newDigitalPinGpiod(chip, pin) // assert - gobottest.Refute(t, d, nil) - gobottest.Assert(t, d.chipName, chip) - gobottest.Assert(t, d.pin, pin) - gobottest.Assert(t, d.label, label) - gobottest.Assert(t, d.direction, IN) - gobottest.Assert(t, d.outInitialState, 0) + assert.NotNil(t, d) + assert.Equal(t, chip, d.chipName) + assert.Equal(t, pin, d.pin) + assert.Equal(t, label, d.label) + assert.Equal(t, IN, d.direction) + assert.Equal(t, 0, d.outInitialState) } func Test_newDigitalPinGpiodWithOptions(t *testing.T) { @@ -41,7 +40,7 @@ func Test_newDigitalPinGpiodWithOptions(t *testing.T) { // act dp := newDigitalPinGpiod("", 9, WithPinLabel(label)) // assert - gobottest.Assert(t, dp.label, label) + assert.Equal(t, label, dp.label) } func TestApplyOptions(t *testing.T) { @@ -102,12 +101,12 @@ func TestApplyOptions(t *testing.T) { // act err := d.ApplyOptions(optionFunction1, optionFunction2) // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, d.digitalPinConfig.direction, "test") - gobottest.Assert(t, d.digitalPinConfig.drive, 15) - gobottest.Assert(t, reconfigured, tc.wantReconfigured) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, "test", d.digitalPinConfig.direction) + assert.Equal(t, 15, d.digitalPinConfig.drive) + assert.Equal(t, tc.wantReconfigured, reconfigured) if reconfigured > 0 { - gobottest.Assert(t, inputForced, false) + assert.False(t, inputForced) } }) } @@ -147,9 +146,9 @@ func TestExport(t *testing.T) { // act err := d.Export() // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, inputForced, false) - gobottest.Assert(t, reconfigured, tc.wantReconfigured) + assert.Equal(t, tc.wantErr, err) + assert.False(t, inputForced) + assert.Equal(t, tc.wantReconfigured, reconfigured) }) } } @@ -207,10 +206,10 @@ func TestUnexport(t *testing.T) { // act err := dp.Unexport() // assert - gobottest.Assert(t, err, tc.wantErr) - gobottest.Assert(t, reconfigured, tc.wantReconfigured) + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantReconfigured, reconfigured) if reconfigured > 0 { - gobottest.Assert(t, inputForced, true) + assert.True(t, inputForced) } }) } @@ -255,12 +254,12 @@ func TestWrite(t *testing.T) { // assert if tc.wantErr != nil { for _, want := range tc.wantErr { - gobottest.Assert(t, strings.Contains(err.Error(), want), true) + assert.Contains(t, err.Error(), want) } } else { - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } - gobottest.Assert(t, lm.lastVal, tc.want) + assert.Equal(t, tc.want, lm.lastVal) }) } } @@ -290,12 +289,12 @@ func TestRead(t *testing.T) { // assert if tc.wantErr != nil { for _, want := range tc.wantErr { - gobottest.Assert(t, strings.Contains(err.Error(), want), true) + assert.Contains(t, err.Error(), want) } } else { - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } - gobottest.Assert(t, tc.simVal, got) + assert.Equal(t, got, tc.simVal) }) } } diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index 992a06be5..5c2fe57b0 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -5,8 +5,8 @@ import ( "os" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.DigitalPinner = (*digitalPinSysfs)(nil) @@ -29,51 +29,51 @@ func TestDigitalPin(t *testing.T) { } pin, fs := initTestDigitalPinSysFsWithMockedFilesystem(mockPaths) - gobottest.Assert(t, pin.pin, "10") - gobottest.Assert(t, pin.label, "gpio10") - gobottest.Assert(t, pin.valFile, nil) + assert.Equal(t, "10", pin.pin) + assert.Equal(t, "gpio10", pin.label) + assert.Nil(t, pin.valFile) err := pin.Unexport() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/gpio/unexport"].Contents, "10") + assert.Nil(t, err) + assert.Equal(t, "10", fs.Files["/sys/class/gpio/unexport"].Contents) err = pin.Export() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/gpio/export"].Contents, "10") - gobottest.Refute(t, pin.valFile, nil) + assert.Nil(t, err) + assert.Equal(t, "10", fs.Files["/sys/class/gpio/export"].Contents) + assert.NotNil(t, pin.valFile) err = pin.Write(1) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio10/value"].Contents, "1") + assert.Nil(t, err) + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio10/value"].Contents) err = pin.ApplyOptions(WithPinDirectionInput()) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio10/direction"].Contents, "in") + assert.Nil(t, err) + assert.Equal(t, "in", fs.Files["/sys/class/gpio/gpio10/direction"].Contents) data, _ := pin.Read() - gobottest.Assert(t, 1, data) + assert.Equal(t, data, 1) pin2 := newDigitalPinSysfs(fs, "30") err = pin2.Write(1) - gobottest.Assert(t, err.Error(), "pin has not been exported") + assert.Errorf(t, err, "pin has not been exported") data, err = pin2.Read() - gobottest.Assert(t, err.Error(), "pin has not been exported") - gobottest.Assert(t, data, 0) + assert.Errorf(t, err, "pin has not been exported") + assert.Equal(t, 0, data) writeFile = func(File, []byte) (int, error) { return 0, &os.PathError{Err: Syscall_EINVAL} } err = pin.Unexport() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) writeFile = func(File, []byte) (int, error) { return 0, &os.PathError{Err: errors.New("write error")} } err = pin.Unexport() - gobottest.Assert(t, err.(*os.PathError).Err, errors.New("write error")) + assert.Errorf(t, err.(*os.PathError).Err, "write error") // assert a busy error is dropped (just means "already exported") cnt := 0 @@ -85,14 +85,14 @@ func TestDigitalPin(t *testing.T) { return 0, nil } err = pin.Export() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) // assert write error on export writeFile = func(File, []byte) (int, error) { return 0, &os.PathError{Err: errors.New("write error")} } err = pin.Export() - gobottest.Assert(t, err.(*os.PathError).Err, errors.New("write error")) + assert.Errorf(t, err.(*os.PathError).Err, "write error") } func TestDigitalPinExportError(t *testing.T) { @@ -107,7 +107,7 @@ func TestDigitalPinExportError(t *testing.T) { } err := pin.Export() - gobottest.Assert(t, err.Error(), " : /sys/class/gpio/gpio10/direction: no such file") + assert.Errorf(t, err, " : /sys/class/gpio/gpio10/direction: no such file") } func TestDigitalPinUnexportError(t *testing.T) { @@ -121,5 +121,5 @@ func TestDigitalPinUnexportError(t *testing.T) { } err := pin.Unexport() - gobottest.Assert(t, err.Error(), " : device or resource busy") + assert.Errorf(t, err, " : device or resource busy") } diff --git a/system/fs_mock_test.go b/system/fs_mock_test.go index 78b974ad6..40202c980 100644 --- a/system/fs_mock_test.go +++ b/system/fs_mock_test.go @@ -4,42 +4,42 @@ import ( "sort" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestMockFilesystemOpen(t *testing.T) { fs := newMockFilesystem([]string{"foo"}) f1 := fs.Files["foo"] - gobottest.Assert(t, f1.Opened, false) + assert.False(t, f1.Opened) f2, err := fs.openFile("foo", 0, 0666) - gobottest.Assert(t, f1, f2) - gobottest.Assert(t, err, nil) + assert.Equal(t, f2, f1) + assert.Nil(t, err) err = f2.Sync() - gobottest.Assert(t, err, nil) + assert.Nil(t, err) _, err = fs.openFile("bar", 0, 0666) - gobottest.Assert(t, err.Error(), " : bar: no such file") + assert.Errorf(t, err, " : bar: no such file") fs.Add("bar") f4, _ := fs.openFile("bar", 0, 0666) - gobottest.Refute(t, f4.Fd(), f1.Fd()) + assert.NotEqual(t, f1.Fd(), f4.Fd()) } func TestMockFilesystemStat(t *testing.T) { fs := newMockFilesystem([]string{"foo", "bar/baz"}) fileStat, err := fs.stat("foo") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fileStat.IsDir(), false) + assert.Nil(t, err) + assert.False(t, fileStat.IsDir()) dirStat, err := fs.stat("bar") - gobottest.Assert(t, err, nil) - gobottest.Assert(t, dirStat.IsDir(), true) + assert.Nil(t, err) + assert.True(t, dirStat.IsDir()) _, err = fs.stat("plonk") - gobottest.Assert(t, err.Error(), " : plonk: no such file") + assert.Errorf(t, err, " : plonk: no such file") } func TestMockFilesystemFind(t *testing.T) { @@ -61,9 +61,9 @@ func TestMockFilesystemFind(t *testing.T) { // act dirs, err := fs.find(tt.baseDir, tt.pattern) // assert - gobottest.Assert(t, err, nil) + assert.Nil(t, err) sort.Strings(dirs) - gobottest.Assert(t, dirs, tt.want) + assert.Equal(t, tt.want, dirs) }) } } @@ -73,14 +73,14 @@ func TestMockFilesystemWrite(t *testing.T) { f1 := fs.Files["bar"] f2, err := fs.openFile("bar", 0, 0666) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) // Never been read or written. - gobottest.Assert(t, f1.Seq <= 0, true) + assert.True(t, f1.Seq <= 0) _, _ = f2.WriteString("testing") // Was written. - gobottest.Assert(t, f1.Seq > 0, true) - gobottest.Assert(t, f1.Contents, "testing") + assert.True(t, f1.Seq > 0) + assert.Equal(t, "testing", f1.Contents) } func TestMockFilesystemRead(t *testing.T) { @@ -89,18 +89,18 @@ func TestMockFilesystemRead(t *testing.T) { f1.Contents = "Yip" f2, err := fs.openFile("bar", 0, 0666) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) // Never been read or written. - gobottest.Assert(t, f1.Seq <= 0, true) + assert.True(t, f1.Seq <= 0) buffer := make([]byte, 20) n, _ := f2.Read(buffer) // Was read. - gobottest.Assert(t, f1.Seq > 0, true) - gobottest.Assert(t, n, 3) - gobottest.Assert(t, string(buffer[:3]), "Yip") + assert.True(t, f1.Seq > 0) + assert.Equal(t, 3, n) + assert.Equal(t, "Yip", string(buffer[:3])) n, _ = f2.ReadAt(buffer, 10) - gobottest.Assert(t, n, 3) + assert.Equal(t, 3, n) } diff --git a/system/fs_test.go b/system/fs_test.go index ebcbfd8bf..0f5e4e8ad 100644 --- a/system/fs_test.go +++ b/system/fs_test.go @@ -4,19 +4,19 @@ import ( "os" "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestFilesystemOpen(t *testing.T) { fs := &nativeFilesystem{} file, err := fs.openFile(os.DevNull, os.O_RDONLY, 0666) - gobottest.Assert(t, err, nil) + assert.Nil(t, err) var _ File = file } func TestFilesystemStat(t *testing.T) { fs := &nativeFilesystem{} fileInfo, err := fs.stat(os.DevNull) - gobottest.Assert(t, err, nil) - gobottest.Refute(t, fileInfo, nil) + assert.Nil(t, err) + assert.NotNil(t, fileInfo) } diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index f40124d03..1e5e666a1 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -1,13 +1,12 @@ package system import ( - "errors" "os" "testing" "unsafe" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) const dev = "/dev/i2c-1" @@ -80,11 +79,11 @@ func TestNewI2cDevice(t *testing.T) { d, err := a.NewI2cDevice(tc.dev) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) - gobottest.Assert(t, d, (*i2cDevice)(nil)) + assert.Errorf(t, err, tc.wantErr) + assert.Equal(t, (*i2cDevice)(nil), d) } else { var _ gobot.I2cSystemDevicer = d - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } }) } @@ -94,7 +93,7 @@ func TestClose(t *testing.T) { // arrange d, _ := initTestI2cDeviceWithMockedSys() // act & assert - gobottest.Assert(t, d.Close(), nil) + assert.Nil(t, d.Close()) } func TestWriteRead(t *testing.T) { @@ -106,11 +105,11 @@ func TestWriteRead(t *testing.T) { wn, werr := d.Write(1, wbuf) rn, rerr := d.Read(1, rbuf) // assert - gobottest.Assert(t, werr, nil) - gobottest.Assert(t, rerr, nil) - gobottest.Assert(t, wn, len(wbuf)) - gobottest.Assert(t, rn, len(wbuf)) // will read only the written values - gobottest.Assert(t, wbuf, rbuf[:len(wbuf)]) + assert.Nil(t, werr) + assert.Nil(t, rerr) + assert.Equal(t, len(wbuf), wn) + assert.Equal(t, len(wbuf), rn) // will read only the written values + assert.Equal(t, rbuf[:len(wbuf)], wbuf) } func TestReadByte(t *testing.T) { @@ -143,15 +142,15 @@ func TestReadByte(t *testing.T) { got, err := d.ReadByte(2) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, want) - gobottest.Assert(t, msc.lastFile, d.file) - gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS)) - gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ)) - gobottest.Assert(t, msc.smbus.command, byte(0)) // register is set to 0 in that case - gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_BYTE)) + assert.Nil(t, err) + assert.Equal(t, want, got) + assert.Equal(t, d.file, msc.lastFile) + assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) + assert.Equal(t, byte(I2C_SMBUS_READ), msc.smbus.readWrite) + assert.Equal(t, byte(0), msc.smbus.command) // register is set to 0 in that case + assert.Equal(t, uint32(I2C_SMBUS_BYTE), msc.smbus.protocol) } }) } @@ -190,15 +189,15 @@ func TestReadByteData(t *testing.T) { got, err := d.ReadByteData(3, reg) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, want) - gobottest.Assert(t, msc.lastFile, d.file) - gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS)) - gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ)) - gobottest.Assert(t, msc.smbus.command, reg) - gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_BYTE_DATA)) + assert.Nil(t, err) + assert.Equal(t, want, got) + assert.Equal(t, d.file, msc.lastFile) + assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) + assert.Equal(t, byte(I2C_SMBUS_READ), msc.smbus.readWrite) + assert.Equal(t, reg, msc.smbus.command) + assert.Equal(t, uint32(I2C_SMBUS_BYTE_DATA), msc.smbus.protocol) } }) } @@ -240,15 +239,15 @@ func TestReadWordData(t *testing.T) { got, err := d.ReadWordData(4, reg) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) - gobottest.Assert(t, got, want) - gobottest.Assert(t, msc.lastFile, d.file) - gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS)) - gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ)) - gobottest.Assert(t, msc.smbus.command, reg) - gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_WORD_DATA)) + assert.Nil(t, err) + assert.Equal(t, want, got) + assert.Equal(t, d.file, msc.lastFile) + assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) + assert.Equal(t, byte(I2C_SMBUS_READ), msc.smbus.readWrite) + assert.Equal(t, reg, msc.smbus.command) + assert.Equal(t, uint32(I2C_SMBUS_WORD_DATA), msc.smbus.protocol) } }) } @@ -298,16 +297,16 @@ func TestReadBlockData(t *testing.T) { err := d.ReadBlockData(5, reg, buf) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) - gobottest.Assert(t, buf, msc.dataSlice) - gobottest.Assert(t, msc.lastFile, d.file) - gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS)) - gobottest.Assert(t, msc.sliceSize, uint8(len(buf)+1)) - gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ)) - gobottest.Assert(t, msc.smbus.command, reg) - gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_I2C_BLOCK_DATA)) + assert.Nil(t, err) + assert.Equal(t, msc.dataSlice, buf) + assert.Equal(t, d.file, msc.lastFile) + assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) + assert.Equal(t, uint8(len(buf)+1), msc.sliceSize) + assert.Equal(t, byte(I2C_SMBUS_READ), msc.smbus.readWrite) + assert.Equal(t, reg, msc.smbus.command) + assert.Equal(t, uint32(I2C_SMBUS_I2C_BLOCK_DATA), msc.smbus.protocol) } }) } @@ -342,14 +341,14 @@ func TestWriteByte(t *testing.T) { err := d.WriteByte(6, val) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) - gobottest.Assert(t, msc.lastFile, d.file) - gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS)) - gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE)) - gobottest.Assert(t, msc.smbus.command, val) // in byte write, the register/command is used for the value - gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_BYTE)) + assert.Nil(t, err) + assert.Equal(t, d.file, msc.lastFile) + assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) + assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) + assert.Equal(t, val, msc.smbus.command) // in byte write, the register/command is used for the value + assert.Equal(t, uint32(I2C_SMBUS_BYTE), msc.smbus.protocol) } }) } @@ -387,16 +386,16 @@ func TestWriteByteData(t *testing.T) { err := d.WriteByteData(7, reg, val) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) - gobottest.Assert(t, msc.lastFile, d.file) - gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS)) - gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE)) - gobottest.Assert(t, msc.smbus.command, reg) - gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_BYTE_DATA)) - gobottest.Assert(t, len(msc.dataSlice), 1) - gobottest.Assert(t, msc.dataSlice[0], val) + assert.Nil(t, err) + assert.Equal(t, d.file, msc.lastFile) + assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) + assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) + assert.Equal(t, reg, msc.smbus.command) + assert.Equal(t, uint32(I2C_SMBUS_BYTE_DATA), msc.smbus.protocol) + assert.Equal(t, 1, len(msc.dataSlice)) + assert.Equal(t, val, msc.dataSlice[0]) } }) } @@ -436,18 +435,18 @@ func TestWriteWordData(t *testing.T) { err := d.WriteWordData(8, reg, val) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) - gobottest.Assert(t, msc.lastFile, d.file) - gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS)) - gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE)) - gobottest.Assert(t, msc.smbus.command, reg) - gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_WORD_DATA)) - gobottest.Assert(t, len(msc.dataSlice), 2) + assert.Nil(t, err) + assert.Equal(t, d.file, msc.lastFile) + assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) + assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) + assert.Equal(t, reg, msc.smbus.command) + assert.Equal(t, uint32(I2C_SMBUS_WORD_DATA), msc.smbus.protocol) + assert.Equal(t, 2, len(msc.dataSlice)) // all common drivers write LSByte first - gobottest.Assert(t, msc.dataSlice[0], wantLSByte) - gobottest.Assert(t, msc.dataSlice[1], wantMSByte) + assert.Equal(t, wantLSByte, msc.dataSlice[0]) + assert.Equal(t, wantMSByte, msc.dataSlice[1]) } }) } @@ -493,17 +492,17 @@ func TestWriteBlockData(t *testing.T) { err := d.WriteBlockData(9, reg, data) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) - gobottest.Assert(t, msc.lastFile, d.file) - gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS)) - gobottest.Assert(t, msc.sliceSize, uint8(len(data)+1)) // including size element - gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE)) - gobottest.Assert(t, msc.smbus.command, reg) - gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_I2C_BLOCK_DATA)) - gobottest.Assert(t, msc.dataSlice[0], uint8(len(data))) // data size - gobottest.Assert(t, msc.dataSlice[1:], data) + assert.Nil(t, err) + assert.Equal(t, d.file, msc.lastFile) + assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) + assert.Equal(t, uint8(len(data)+1), msc.sliceSize) // including size element + assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) + assert.Equal(t, reg, msc.smbus.command) + assert.Equal(t, uint32(I2C_SMBUS_I2C_BLOCK_DATA), msc.smbus.protocol) + assert.Equal(t, uint8(len(data)), msc.dataSlice[0]) // data size + assert.Equal(t, data, msc.dataSlice[1:]) } }) } @@ -515,7 +514,7 @@ func TestWriteBlockDataTooMuch(t *testing.T) { // act err := d.WriteBlockData(10, 0x01, make([]byte, 33)) // assert - gobottest.Assert(t, err, errors.New("Writing blocks larger than 32 bytes (33) not supported")) + assert.Errorf(t, err, "Writing blocks larger than 32 bytes (33) not supported") } func Test_setAddress(t *testing.T) { @@ -524,8 +523,8 @@ func Test_setAddress(t *testing.T) { // act err := d.setAddress(0xff) // assert - gobottest.Assert(t, err, nil) - gobottest.Assert(t, msc.devAddress, uintptr(0xff)) + assert.Nil(t, err) + assert.Equal(t, uintptr(0xff), msc.devAddress) } func Test_queryFunctionality(t *testing.T) { @@ -566,16 +565,16 @@ func Test_queryFunctionality(t *testing.T) { err := d.queryFunctionality(tc.requested, "test"+name) // assert if tc.wantErr != "" { - gobottest.Assert(t, err.Error(), tc.wantErr) + assert.Errorf(t, err, tc.wantErr) } else { - gobottest.Assert(t, err, nil) + assert.Nil(t, err) } if tc.wantFile { - gobottest.Refute(t, d.file, nil) + assert.NotNil(t, d.file) } else { - gobottest.Assert(t, d.file, (*MockFile)(nil)) + assert.Equal(t, (*MockFile)(nil), d.file) } - gobottest.Assert(t, d.funcs, tc.wantFuncs) + assert.Equal(t, tc.wantFuncs, d.funcs) }) } } diff --git a/system/pwmpin_sysfs_test.go b/system/pwmpin_sysfs_test.go index 44c224973..ba3a84c48 100644 --- a/system/pwmpin_sysfs_test.go +++ b/system/pwmpin_sysfs_test.go @@ -4,8 +4,8 @@ import ( "os" "testing" + "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.PWMPinner = (*pwmPinSysFs)(nil) @@ -32,45 +32,45 @@ func TestPwmPin(t *testing.T) { } pin, fs := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) - gobottest.Assert(t, pin.pin, "10") + assert.Equal(t, "10", pin.pin) err := pin.Unexport() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/unexport"].Contents, "10") + assert.Nil(t, err) + assert.Equal(t, "10", fs.Files["/sys/class/pwm/pwmchip0/unexport"].Contents) err = pin.Export() - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/export"].Contents, "10") + assert.Nil(t, err) + assert.Equal(t, "10", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) - gobottest.Assert(t, pin.SetPolarity(false), nil) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].Contents, inverted) + assert.Nil(t, pin.SetPolarity(false)) + assert.Equal(t, inverted, fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].Contents) pol, _ := pin.Polarity() - gobottest.Assert(t, pol, false) - gobottest.Assert(t, pin.SetPolarity(true), nil) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].Contents, normal) + assert.False(t, pol) + assert.Nil(t, pin.SetPolarity(true)) + assert.Equal(t, normal, fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].Contents) pol, _ = pin.Polarity() - gobottest.Assert(t, pol, true) + assert.True(t, pol) - gobottest.Refute(t, fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents, "1") + assert.NotEqual(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents) err = pin.SetEnabled(true) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents, "1") + assert.Nil(t, err) + assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents) err = pin.SetPolarity(true) - gobottest.Assert(t, err.Error(), "Cannot set PWM polarity when enabled") + assert.Errorf(t, err, "Cannot set PWM polarity when enabled") fs.Files["/sys/class/pwm/pwmchip0/pwm10/period"].Contents = "6" data, _ := pin.Period() - gobottest.Assert(t, data, uint32(6)) - gobottest.Assert(t, pin.SetPeriod(100000), nil) + assert.Equal(t, uint32(6), data) + assert.Nil(t, pin.SetPeriod(100000)) data, _ = pin.Period() - gobottest.Assert(t, data, uint32(100000)) + assert.Equal(t, uint32(100000), data) - gobottest.Refute(t, fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].Contents, "1") + assert.NotEqual(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].Contents) err = pin.SetDutyCycle(100) - gobottest.Assert(t, err, nil) - gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].Contents, "100") + assert.Nil(t, err) + assert.Equal(t, "100", fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].Contents) data, _ = pin.DutyCycle() - gobottest.Assert(t, data, uint32(100)) + assert.Equal(t, uint32(100), data) } func TestPwmPinAlreadyExported(t *testing.T) { @@ -88,7 +88,7 @@ func TestPwmPinAlreadyExported(t *testing.T) { } // no error indicates that the pin was already exported - gobottest.Assert(t, pin.Export(), nil) + assert.Nil(t, pin.Export()) } func TestPwmPinExportError(t *testing.T) { @@ -107,7 +107,7 @@ func TestPwmPinExportError(t *testing.T) { // no error indicates that the pin was already exported err := pin.Export() - gobottest.Assert(t, err.Error(), "Export() failed for id 10 with : bad address") + assert.Errorf(t, err, "Export() failed for id 10 with : bad address") } func TestPwmPinUnxportError(t *testing.T) { @@ -125,7 +125,7 @@ func TestPwmPinUnxportError(t *testing.T) { } err := pin.Unexport() - gobottest.Assert(t, err.Error(), "Unexport() failed for id 10 with : device or resource busy") + assert.Errorf(t, err, "Unexport() failed for id 10 with : device or resource busy") } func TestPwmPinPeriodError(t *testing.T) { @@ -143,7 +143,7 @@ func TestPwmPinPeriodError(t *testing.T) { } _, err := pin.Period() - gobottest.Assert(t, err.Error(), "Period() failed for id 10 with : device or resource busy") + assert.Errorf(t, err, "Period() failed for id 10 with : device or resource busy") } func TestPwmPinPolarityError(t *testing.T) { @@ -161,7 +161,7 @@ func TestPwmPinPolarityError(t *testing.T) { } _, err := pin.Polarity() - gobottest.Assert(t, err.Error(), "Polarity() failed for id 10 with : device or resource busy") + assert.Errorf(t, err, "Polarity() failed for id 10 with : device or resource busy") } func TestPwmPinDutyCycleError(t *testing.T) { @@ -179,5 +179,5 @@ func TestPwmPinDutyCycleError(t *testing.T) { } _, err := pin.DutyCycle() - gobottest.Assert(t, err.Error(), "DutyCycle() failed for id 10 with : device or resource busy") + assert.Errorf(t, err, "DutyCycle() failed for id 10 with : device or resource busy") } diff --git a/system/spi_access_test.go b/system/spi_access_test.go index 6f087ae4c..d70be2656 100644 --- a/system/spi_access_test.go +++ b/system/spi_access_test.go @@ -3,7 +3,7 @@ package system import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestGpioSpi_isSupported(t *testing.T) { @@ -12,7 +12,7 @@ func TestGpioSpi_isSupported(t *testing.T) { // act got := gsa.isSupported() // assert - gobottest.Assert(t, got, true) + assert.True(t, got) } func TestPeriphioSpi_isSupported(t *testing.T) { @@ -37,7 +37,7 @@ func TestPeriphioSpi_isSupported(t *testing.T) { // act got := psa.isSupported() // assert - gobottest.Assert(t, got, tc.want) + assert.Equal(t, tc.want, got) }) } } diff --git a/system/system_test.go b/system/system_test.go index 54eb87486..9f2c7243a 100644 --- a/system/system_test.go +++ b/system/system_test.go @@ -3,7 +3,7 @@ package system import ( "testing" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestNewAccesser(t *testing.T) { @@ -13,10 +13,10 @@ func TestNewAccesser(t *testing.T) { nativeSys := a.sys.(*nativeSyscall) nativeFsSys := a.fs.(*nativeFilesystem) perphioSpi := a.spiAccess.(*periphioSpiAccess) - gobottest.Refute(t, a, nil) - gobottest.Refute(t, nativeSys, nil) - gobottest.Refute(t, nativeFsSys, nil) - gobottest.Refute(t, perphioSpi, nil) + assert.NotNil(t, a) + assert.NotNil(t, nativeSys) + assert.NotNil(t, nativeFsSys) + assert.NotNil(t, perphioSpi) } func TestNewAccesser_NewSpiDevice(t *testing.T) { @@ -34,13 +34,13 @@ func TestNewAccesser_NewSpiDevice(t *testing.T) { // act con, err := a.NewSpiDevice(busNum, chipNum, mode, bits, maxSpeed) // assert - gobottest.Assert(t, err, nil) - gobottest.Refute(t, con, nil) - gobottest.Assert(t, spi.busNum, busNum) - gobottest.Assert(t, spi.chipNum, chipNum) - gobottest.Assert(t, spi.mode, mode) - gobottest.Assert(t, spi.bits, bits) - gobottest.Assert(t, spi.maxSpeed, maxSpeed) + assert.Nil(t, err) + assert.NotNil(t, con) + assert.Equal(t, busNum, spi.busNum) + assert.Equal(t, chipNum, spi.chipNum) + assert.Equal(t, mode, spi.mode) + assert.Equal(t, bits, spi.bits) + assert.Equal(t, maxSpeed, spi.maxSpeed) } func TestNewAccesser_IsSysfsDigitalPinAccess(t *testing.T) { @@ -75,17 +75,17 @@ func TestNewAccesser_IsSysfsDigitalPinAccess(t *testing.T) { // act got := a.IsSysfsDigitalPinAccess() // assert - gobottest.Refute(t, a, nil) + assert.NotNil(t, a) if tc.wantSys { - gobottest.Assert(t, got, true) + assert.True(t, got) dpaSys := a.digitalPinAccess.(*sysfsDigitalPinAccess) - gobottest.Refute(t, dpaSys, nil) - gobottest.Assert(t, dpaSys.fs, a.fs.(*nativeFilesystem)) + assert.NotNil(t, dpaSys) + assert.Equal(t, a.fs.(*nativeFilesystem), dpaSys.fs) } else { - gobottest.Assert(t, got, false) + assert.False(t, got) dpaGpiod := a.digitalPinAccess.(*gpiodDigitalPinAccess) - gobottest.Refute(t, dpaGpiod, nil) - gobottest.Assert(t, dpaGpiod.fs, a.fs.(*nativeFilesystem)) + assert.NotNil(t, dpaGpiod) + assert.Equal(t, a.fs.(*nativeFilesystem), dpaGpiod.fs) } }) } diff --git a/utils_test.go b/utils_test.go index 383baa578..e07e299e6 100644 --- a/utils_test.go +++ b/utils_test.go @@ -1,11 +1,10 @@ package gobot import ( - "strings" "testing" "time" - "gobot.io/x/gobot/v2/gobottest" + "github.com/stretchr/testify/assert" ) func TestEvery(t *testing.T) { @@ -61,22 +60,22 @@ func TestAfter(t *testing.T) { t.Errorf("After was not called") } - gobottest.Assert(t, i, 1) + assert.Equal(t, 1, i) } func TestFromScale(t *testing.T) { - gobottest.Assert(t, FromScale(5, 0, 10), 0.5) + assert.Equal(t, 0.5, FromScale(5, 0, 10)) } func TestToScale(t *testing.T) { - gobottest.Assert(t, ToScale(500, 0, 10), 10.0) - gobottest.Assert(t, ToScale(-1, 0, 10), 0.0) - gobottest.Assert(t, ToScale(0.5, 0, 10), 5.0) + assert.Equal(t, 10.0, ToScale(500, 0, 10)) + assert.Equal(t, 0.0, ToScale(-1, 0, 10)) + assert.Equal(t, 5.0, ToScale(0.5, 0, 10)) } func TestRescale(t *testing.T) { - gobottest.Assert(t, Rescale(500, 0, 1000, 0, 10), 5.0) - gobottest.Assert(t, Rescale(-1.0, -1, 0, 490, 350), 490.0) + assert.Equal(t, 5.0, Rescale(500, 0, 1000, 0, 10)) + assert.Equal(t, 490.0, Rescale(-1.0, -1, 0, 490, 350)) } func TestRand(t *testing.T) { @@ -89,5 +88,5 @@ func TestRand(t *testing.T) { func TestDefaultName(t *testing.T) { name := DefaultName("tester") - gobottest.Assert(t, strings.Contains(name, "tester"), true) + assert.Contains(t, name, "tester") } From 82745f48da89b10778b7d176f1285467058e9725 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Fri, 20 Oct 2023 11:41:16 +0200 Subject: [PATCH 08/57] build(go, deps): switch to Go 1.19 and update modules (#1008) --- .circleci/config.yml | 6 +++--- .github/workflows/golangci-lint.yml | 9 +++++---- go.mod | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e09013af6..c3b40f46b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ version: 2 jobs: "test_core_and_drivers_with_coverage": docker: - - image: cimg/go:1.18 + - image: cimg/go:1.19 steps: - checkout - run: @@ -31,7 +31,7 @@ jobs: "test_platforms": docker: - - image: cimg/go:1.18 + - image: cimg/go:1.19 steps: - checkout - run: @@ -45,7 +45,7 @@ jobs: "check_examples": docker: - - image: cimg/go:1.18 + - image: cimg/go:1.19 steps: - checkout - run: diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 6ead6dc19..8b9028ee6 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -15,23 +15,24 @@ jobs: name: lint runs-on: ubuntu-latest steps: + - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '1.18' + go-version: '1.19' cache: false - - uses: actions/checkout@v3 - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.53.3 + version: v1.54.2 # Optional: working directory, useful for monorepos # working-directory: v2 # Optional: golangci-lint command line arguments. # mostly there is no problem locally, but on server: "could not import C (cgo preprocessing failed) (typecheck)" - args: --skip-files platforms/digispark/littleWire.go + # and the digispark adaptor can not be build since switch to linter version 1.54.2 + args: --skip-files="platforms/digispark/littleWire.go,platforms/digispark/digispark_adaptor.go" # Optional: show only new issues if it's a pull request. The default value is `false`. # only-new-issues: true diff --git a/go.mod b/go.mod index 332e93d57..74e58fe23 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module gobot.io/x/gobot/v2 -go 1.18 +go 1.19 require ( github.com/0xcafed00d/joystick v1.0.1 From 06e8f78180d2c567e9ae4f958ea1bc8b3ee7d9b4 Mon Sep 17 00:00:00 2001 From: guangwu Date: Fri, 20 Oct 2023 21:45:15 +0800 Subject: [PATCH 09/57] beaglebone(doc): fix preceding typo (#985) Signed-off-by: guoguangwu Co-authored-by: Thomas Kohler --- platforms/beaglebone/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/beaglebone/README.md b/platforms/beaglebone/README.md index c07c1f4aa..ea871af24 100644 --- a/platforms/beaglebone/README.md +++ b/platforms/beaglebone/README.md @@ -110,7 +110,7 @@ scp beaglebone_blink debian@192.168.7.2:/home/debian/ ssh -t debian@192.168.7.2 "./beaglebone_blink" ``` -In order to run the preceeding commands, you must be running the official Debian Linux through the usb->ethernet connection, +In order to run the preceding commands, you must be running the official Debian Linux through the usb->ethernet connection, or be connected to the board using WiFi. You must also configure hardware settings as described below. From a4a8d1079ca93c468eef81b571b80e985ce5cd6c Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Fri, 20 Oct 2023 20:50:42 +0200 Subject: [PATCH 10/57] build(style): switch to gofumpt and add linters (#1009) --- .golangci.yml | 28 +-- CONTRIBUTING.md | 2 +- Makefile | 10 +- adaptor.go | 1 - api/api.go | 11 +- api/api_test.go | 1 - api/doc.go | 42 ++-- api/helpers_test.go | 6 +- api/robeaux/robeaux.go | 19 +- doc.go | 196 +++++++++--------- drivers/aio/aio.go | 12 +- drivers/aio/analog_actuator_driver_test.go | 2 +- drivers/aio/analog_sensor_driver.go | 4 +- drivers/aio/analog_sensor_driver_test.go | 2 +- .../aio/grove_temperature_sensor_driver.go | 4 +- .../grove_temperature_sensor_driver_test.go | 2 +- drivers/aio/temperature_sensor_driver.go | 2 +- drivers/aio/temperature_sensor_driver_test.go | 14 +- drivers/common/mfrc522/mfrc522_pcd.go | 9 +- .../common/mfrc522/mfrc522_pcd_register.go | 182 ++++++++-------- drivers/common/mfrc522/mfrc522_pcd_test.go | 2 +- drivers/common/mfrc522/mfrc522_picc.go | 14 +- drivers/gpio/buzzer_driver_test.go | 1 - drivers/gpio/grove_drivers.go | 11 +- drivers/gpio/helpers_test.go | 8 + drivers/gpio/led_driver_test.go | 1 - drivers/gpio/motor_driver_test.go | 2 +- drivers/gpio/servo_driver.go | 1 - drivers/gpio/stepper_driver.go | 14 +- drivers/gpio/tm1638_driver.go | 2 - drivers/i2c/adafruit1109_driver.go | 2 +- drivers/i2c/adafruit1109_driver_test.go | 12 +- drivers/i2c/adafruit_driver.go | 27 +-- drivers/i2c/ads1x15_driver.go | 3 +- drivers/i2c/ads1x15_driver_1015_test.go | 2 +- drivers/i2c/ads1x15_driver_1115_test.go | 2 +- drivers/i2c/ads1x15_driver_test.go | 2 +- drivers/i2c/adxl345_driver.go | 6 +- drivers/i2c/adxl345_driver_test.go | 4 +- drivers/i2c/bh1750_driver.go | 10 +- drivers/i2c/bh1750_driver_test.go | 3 +- drivers/i2c/blinkm_driver.go | 7 +- drivers/i2c/blinkm_driver_test.go | 3 - drivers/i2c/bme280_driver.go | 1 - drivers/i2c/bmp180_driver.go | 1 - drivers/i2c/bmp180_driver_test.go | 8 +- drivers/i2c/bmp280_driver.go | 10 +- drivers/i2c/bmp388_driver.go | 11 +- drivers/i2c/ccs811_driver.go | 60 +++--- drivers/i2c/ccs811_driver_test.go | 8 +- drivers/i2c/drv2605l_driver.go | 14 +- drivers/i2c/grove_drivers.go | 14 +- drivers/i2c/grove_drivers_test.go | 6 +- drivers/i2c/grovepi_driver.go | 10 +- drivers/i2c/grovepi_driver_test.go | 4 +- drivers/i2c/hmc5883l_driver.go | 15 +- drivers/i2c/hmc5883l_driver_test.go | 4 +- drivers/i2c/hmc6352_driver.go | 7 +- drivers/i2c/i2c_config_test.go | 4 +- drivers/i2c/i2c_connection_test.go | 1 - drivers/i2c/i2c_driver.go | 2 +- drivers/i2c/ina3221_driver.go | 2 +- drivers/i2c/ina3221_driver_test.go | 4 +- drivers/i2c/l3gd20h_driver_test.go | 6 +- drivers/i2c/lidarlite_driver.go | 7 +- drivers/i2c/mcp23017_driver.go | 12 +- drivers/i2c/mcp23017_driver_test.go | 2 +- drivers/i2c/mma7660_driver.go | 7 +- drivers/i2c/mpl115a2_driver.go | 4 +- drivers/i2c/mpu6050_driver.go | 12 +- drivers/i2c/pca9501_driver.go | 24 +-- drivers/i2c/pca9501_driver_test.go | 4 +- drivers/i2c/pca953x_driver.go | 18 +- drivers/i2c/pca953x_driver_test.go | 24 +-- drivers/i2c/pca9685_driver.go | 6 +- drivers/i2c/pca9685_driver_test.go | 6 +- drivers/i2c/pcf8583_driver.go | 21 +- drivers/i2c/pcf8583_driver_test.go | 8 +- drivers/i2c/pcf8591_driver.go | 26 +-- drivers/i2c/sht2x_driver.go | 14 +- drivers/i2c/ssd1306_driver.go | 22 +- drivers/i2c/ssd1306_driver_test.go | 8 +- drivers/i2c/th02_driver.go | 9 +- drivers/i2c/th02_driver_test.go | 18 +- drivers/i2c/tsl2561_driver.go | 21 +- drivers/i2c/tsl2561_driver_test.go | 2 +- drivers/i2c/wiichuck_driver.go | 2 +- drivers/i2c/wiichuck_driver_test.go | 1 - drivers/i2c/yl40_driver.go | 2 +- drivers/i2c/yl40_driver_test.go | 6 +- drivers/spi/apa102.go | 19 +- drivers/spi/helpers_test.go | 10 +- drivers/spi/mcp3002.go | 13 +- drivers/spi/mcp3002_test.go | 2 +- drivers/spi/mcp3004.go | 13 +- drivers/spi/mcp3004_test.go | 2 +- drivers/spi/mcp3008.go | 13 +- drivers/spi/mcp3008_test.go | 2 +- drivers/spi/mcp3202_test.go | 2 +- drivers/spi/mcp3204_test.go | 2 +- drivers/spi/mcp3208_test.go | 2 +- drivers/spi/mcp3304_test.go | 2 +- drivers/spi/spi_config.go | 3 +- drivers/spi/spi_driver_test.go | 2 +- drivers/spi/ssd1306_driver.go | 8 +- drivers/spi/ssd1306_driver_test.go | 4 + examples/bb8-collision.go | 2 - examples/edison_grove_button.go | 1 - examples/edison_grove_touch.go | 1 - examples/firmata_aip1640.go | 1 - examples/firmata_ssd1306.go | 1 - examples/firmata_temp36.go | 3 +- examples/firmata_travis.go | 2 +- examples/gopigo3_servo.go | 1 - examples/jetson-nano_blink.go | 1 - examples/jetson-nano_servo.go | 4 - examples/joystick_xboxone.go | 10 +- examples/nanopi_direct_pin_event.go | 1 - examples/nanopi_pca9533.go | 1 - examples/raspi_adafruit_dcmotor.go | 1 - examples/raspi_direct_pin_event.go | 1 - examples/raspi_generic.go | 1 - examples/raspi_hmc5883l.go | 1 - examples/raspi_ina3221.go | 2 - examples/raspi_pca9533.go | 1 - examples/raspi_ssd1306.go | 1 - examples/raspi_stepper_move.go | 6 +- examples/tinkerboard_adafruit1109_lcd_keys.go | 2 - examples/tinkerboard_direct_pin.go | 1 - examples/tinkerboard_generic.go | 1 - examples/tinkerboard_mfcrc522gpio.go | 2 - examples/tinkerboard_pca9533.go | 1 - examples/tinkerboard_pcf8583_clock.go | 1 - helpers_test.go | 14 +- platforms/adaptors/digitalpinsadaptor.go | 24 ++- platforms/adaptors/digitalpinsadaptor_test.go | 13 +- platforms/adaptors/pwmpinsadaptor.go | 12 +- platforms/adaptors/pwmpinsadaptor_test.go | 13 +- platforms/adaptors/spibusadaptor.go | 3 +- platforms/audio/audio_adaptor_test.go | 2 +- platforms/beaglebone/beaglebone_adaptor.go | 8 +- .../beaglebone/beaglebone_adaptor_test.go | 28 +-- platforms/ble/battery_driver.go | 2 +- platforms/ble/ble_client_adaptor.go | 8 +- platforms/chip/chip_adaptor_test.go | 22 +- platforms/dexter/gopigo3/driver.go | 12 +- platforms/dexter/gopigo3/driver_test.go | 9 +- platforms/digispark/digispark_adaptor.go | 1 - platforms/digispark/digispark_adaptor_test.go | 10 +- platforms/digispark/digispark_i2c.go | 2 +- platforms/digispark/digispark_i2c_test.go | 12 +- platforms/digispark/littleWire.go | 2 +- platforms/digispark/littleWire.h | 2 +- platforms/dji/tello/crc.go | 2 +- platforms/dji/tello/driver.go | 6 +- platforms/dji/tello/driver_test.go | 1 + .../dragonboard/dragonboard_adaptor_test.go | 24 ++- platforms/firmata/client/client.go | 22 +- platforms/firmata/client/client_test.go | 32 ++- platforms/firmata/firmata_adaptor_test.go | 28 ++- platforms/firmata/firmata_i2c_test.go | 1 + platforms/holystone/hs200/hs200_driver.go | 6 +- platforms/intel-iot/curie/imu_driver_test.go | 9 +- platforms/intel-iot/edison/edison_adaptor.go | 6 +- .../intel-iot/edison/edison_adaptor_test.go | 22 +- .../intel-iot/joule/joule_adaptor_test.go | 18 +- platforms/jetson/jetson_adaptor_test.go | 25 +-- platforms/jetson/pwm_pin.go | 2 +- platforms/joystick/bin/scanner.go | 11 +- platforms/keyboard/keyboard.go | 2 +- platforms/leap/leap_motion_driver_test.go | 2 + platforms/mavlink/common/common.go | 2 +- platforms/mavlink/common/mavlink.go | 2 +- platforms/mavlink/mavlink_driver.go | 3 +- platforms/microbit/accelerometer_driver.go | 5 +- platforms/microbit/button_driver.go | 2 +- platforms/microbit/io_pin_driver.go | 2 +- platforms/microbit/io_pin_driver_test.go | 8 +- platforms/microbit/led_driver.go | 2 +- platforms/microbit/magnetometer_driver.go | 5 +- platforms/microbit/temperature_driver.go | 2 +- platforms/mqtt/doc.go | 2 +- platforms/mqtt/mqtt_adaptor.go | 9 +- platforms/nanopi/nanopi_adaptor_test.go | 28 +-- platforms/nats/doc.go | 2 +- platforms/neurosky/neurosky_driver.go | 4 +- platforms/neurosky/neurosky_driver_test.go | 6 +- .../parrot/ardrone/ardrone_driver_test.go | 1 + platforms/parrot/bebop/client/client.go | 55 ++--- .../parrot/bebop/client/examples/video.go | 2 - .../parrot/minidrone/minidrone_driver.go | 7 +- platforms/particle/adaptor.go | 6 +- platforms/pebble/pebble_adaptor_test.go | 1 + platforms/raspi/pwm_pin.go | 2 +- platforms/raspi/raspi_adaptor.go | 3 +- platforms/raspi/raspi_adaptor_test.go | 35 ++-- platforms/rockpi/rockpi_adaptor_test.go | 6 +- platforms/sphero/ollie/ollie_driver.go | 33 ++- platforms/sphero/ollie/ollie_driver_test.go | 11 +- platforms/sphero/ollie/ollie_packets.go | 2 +- platforms/sphero/sphero_driver.go | 2 +- platforms/tinkerboard/adaptor_test.go | 28 +-- platforms/upboard/up2/adaptor.go | 3 +- platforms/upboard/up2/adaptor_test.go | 26 +-- robot.go | 11 +- robot_test.go | 4 +- robot_work.go | 7 +- robot_work_test.go | 1 - system/digitalpin_access.go | 6 +- system/digitalpin_access_test.go | 2 +- system/digitalpin_bench_test.go | 1 - system/digitalpin_config.go | 9 +- system/digitalpin_config_test.go | 24 +-- system/digitalpin_gpiod.go | 42 ++-- system/digitalpin_gpiod_test.go | 20 +- system/digitalpin_mock.go | 3 +- system/digitalpin_sysfs.go | 10 +- system/digitalpin_sysfs_test.go | 10 +- system/fs.go | 1 - system/fs_mock.go | 6 +- system/fs_mock_test.go | 12 +- system/fs_test.go | 2 +- system/i2c_device.go | 6 +- system/i2c_device_test.go | 20 +- system/pwmpin_sysfs.go | 8 +- system/spi_access_test.go | 2 +- system/syscall_mock.go | 8 +- system/system.go | 3 +- system/system_options.go | 1 - system/system_test.go | 2 +- 230 files changed, 1175 insertions(+), 1087 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index c1b5f1f2e..4466f95f4 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -31,9 +31,10 @@ run: linters: # currently active linters: # - #INFO [lintersdb] Active 35 linters: [asasalint asciicheck bidichk contextcheck decorder depguard durationcheck errcheck exportloopref - # gocheckcompilerdirectives gomoddirectives gomodguard goprintffuncname gosimple govet grouper ineffassign makezero mirror musttag - # nilerr nilnil nolintlint nosprintfhostport prealloc reassign revive staticcheck tagalign tenv testableexamples tparallel typecheck unused wastedassign] + #INFO [lintersdb] Active 42 linters: [asasalint asciicheck bidichk contextcheck decorder depguard dupword durationcheck errcheck exportloopref + # gocheckcompilerdirectives gofmt gofumpt goimports gomoddirectives gomodguard goprintffuncname gosec gosimple govet grouper ineffassign makezero mirror + # misspell musttag nilerr nilnil nolintlint nosprintfhostport prealloc reassign revive staticcheck tagalign tenv testableexamples tparallel unconvert unparam + # unused wastedassign] enable-all: true @@ -60,7 +61,6 @@ linters: - godot # not used (seems to be counting peas) - godox # not used (we have many TODOs, so not useful) - goerr113 # not used (we allow error creation at return statement) - - gofumpt # not used (we use "go fmt" or "gofmt" not gofumpt" - gosmopolitan # not needed (report i18n/l10n anti-patterns) - importas # not needed (there is no alias rule at the moment) - ireturn # not used (we allow return interfaces) @@ -73,23 +73,19 @@ linters: - wrapcheck # not needed (we allow errors from interface methods) - zerologlint # not needed (related to zerolog package) # important to have - - gofmt # important to prevent "format tsunami" ("gofmt -s -w" missed), disabled due to "https://github.com/golangci/golangci-lint-action/issues/535" + - errorlint # useful (reduce bugs), but suppress the "Use `%w` to format errors" check + - forcetypeassert # useful (reduce bugs) - nakedret # very useful together with "nonamedreturns" (reduce bugs) - nonamedreturns # very useful (reduce bugs) - - unconvert # very useful (reduce bugs, simplify code) - - unparam # very useful (reduce bugs, simplify code) # useful for the future - bodyclose # maybe useful (reduce bugs), exclusions for tests needed - containedctx # useful (structs are not for context wrapping) - cyclop # useful with some tweeks (better understandable code), see also gocyclo - dogsled # useful with some tweeks (e.g. exclude tests) - dupl # useful with some tweeks (reduce bugs and lines of code) - - dupword # useful with some tweeks, but not important - errchkjson # useful (reduce bugs) - errname # useful for common style - - errorlint # useful (reduce bugs), but suppress the "Use `%w` to format errors" check - exhaustruct # useful with some exclusions for existing code (e.g. mavlink/common/common.go) - - forcetypeassert # useful (reduce bugs) - funlen # useful with some tweeks (reduce bugs, simplify code, better understandable code) - gci # useful (improve readability) - gochecknoinits # useful (reduce bugs, simplify bug catching) @@ -98,13 +94,10 @@ linters: - gocritic # useful with some exclusions for existing code (e.g. mavlink/common/common.go) - gocyclo # useful with some tweeks (better understandable code) - goheader # useful, if we introduce a common header (e.g. for copyright) - - goimports # useful (common style), but not important - gomnd # useful with some exclusions for existing code (e.g. mavlink.go) - - gosec # useful (security) - interfacebloat # useful with some exclusions at usage of external packages - lll # useful with some exclusions for existing code (e.g. mavlink/common/common.go) - maintidx # useful with some tweeks (better understandable code), maybe use instead "gocyclo", "gocognit" , "cyclop" - - misspell # useful (better understandable code), but not important - nestif # useful (reduce bugs, simplify code, better understandable code) - nlreturn # more common style, but could become annoying - noctx # maybe good (show used context explicit) @@ -141,6 +134,15 @@ linters-settings: - pkg: "github.com/pkg/errors" desc: Should be replaced by standard lib errors package + dupword: + # Keywords for detecting duplicate words. + # If this list is not empty, only the words defined in this list will be detected. + # Default: [] + keywords: + - "the" + - "and" + - "a" + nolintlint: # Enable to require an explanation of nonzero length after each nolint directive. # Default: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ae735ac17..ea1f095ed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,7 +41,7 @@ Descriptions for each of these will eventually be provided below. from time to time but they can complicate merges and should be done separately. * Take care to maintain the existing coding style. * `golangci-lint` your code, see [instruction for local installation](https://golangci-lint.run/usage/install/#local-installation) -* `go fmt` your code (with the go version of go.mod) +* `gofumpt` your code (the go version will be automatically obtained from go.mod), see [instructions](https://github.com/mvdan/gofumpt/blob/master/README.md) * Add unit tests for any new or changed functionality. * All pull requests should be "fast forward" * If there are commits after yours use “git rebase -i ” diff --git a/Makefile b/Makefile index 7454c03ba..b83504e45 100644 --- a/Makefile +++ b/Makefile @@ -50,14 +50,14 @@ version_check: echo "go: $${gv}.*, go.mod: $${mv}" ; \ if [ "$${gv}" != "$${mv}" ]; then exit 50; fi ; \ -# Check for bad code style and other issues +# Check for bad code style and other issues (gofumpt and gofmt check is activated for the linter) fmt_check: - gofmt -l -s . golangci-lint run -v -# Fix bad code style (will only be executed, on version match) -fmt_fix: version_check - gofmt -l -s -w . +# Fix bad code style (the go version will be automatically obtained from go.mod) +fmt_fix: + $(MAKE) version_check || true + gofumpt -l -w . examples: $(EXAMPLES) diff --git a/adaptor.go b/adaptor.go index ef7d4e42c..596332642 100644 --- a/adaptor.go +++ b/adaptor.go @@ -109,7 +109,6 @@ type PWMPinnerProvider interface { // Data (8 bits): A plain data byte. DataLow and DataHigh represent the low and high byte of a 16 bit word. // Count (8 bits): A data byte containing the length of a block operation. // [..]: Data sent by I2C device, as opposed to data sent by the host adapter. -// type I2cSystemDevicer interface { // ReadByte must be implemented as the sequence: // "S Addr Rd [A] [Data] NA P" diff --git a/api/api.go b/api/api.go index 365d59e8f..448f2f8e2 100644 --- a/api/api.go +++ b/api/api.go @@ -8,6 +8,7 @@ import ( "net/http" "net/http/httptest" "strings" + "time" "github.com/bmizerany/pat" "gobot.io/x/gobot/v2" @@ -35,16 +36,20 @@ func NewAPI(m *gobot.Master) *API { start: func(a *API) { log.Println("Initializing API on " + a.Host + ":" + a.Port + "...") http.Handle("/", a) + server := &http.Server{ + Addr: a.Host + ":" + a.Port, + ReadHeaderTimeout: 30 * time.Second, + } go func() { if a.Cert != "" && a.Key != "" { - if err := http.ListenAndServeTLS(a.Host+":"+a.Port, a.Cert, a.Key, nil); err != nil { + if err := server.ListenAndServeTLS(a.Cert, a.Key); err != nil { panic(err) } } else { log.Println("WARNING: API using insecure connection. " + "We recommend using an SSL certificate with Gobot.") - if err := http.ListenAndServe(a.Host+":"+a.Port, nil); err != nil { + if err := server.ListenAndServe(); err != nil { panic(err) } } @@ -313,7 +318,6 @@ func (a *API) robotConnections(res http.ResponseWriter, req *http.Request) { } else { a.writeJSON(map[string]interface{}{"error": "No Robot found with the name " + req.URL.Query().Get(":robot")}, res) } - } // robotConnection returns connection route handler @@ -369,7 +373,6 @@ func (a *API) executeCommand(f func(map[string]interface{}) interface{}, res http.ResponseWriter, req *http.Request, ) { - body := make(map[string]interface{}) if err := json.NewDecoder(req.Body).Decode(&body); err != nil { panic(err) diff --git a/api/api_test.go b/api/api_test.go index e8f4ffa53..477bb298c 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -333,7 +333,6 @@ func TestExecuteRobotDeviceCommand(t *testing.T) { _ = json.NewDecoder(response.Body).Decode(&body) assert.Equal(t, "No Device found with the name UnknownDevice1", body.(map[string]interface{})["error"]) - } func TestRobotConnections(t *testing.T) { diff --git a/api/doc.go b/api/doc.go index afc267915..a8e04d3b1 100644 --- a/api/doc.go +++ b/api/doc.go @@ -3,35 +3,35 @@ Package api provides a webserver to interact with your Gobot program over the ne Example: - package main + package main - import ( - "fmt" + import ( + "fmt" - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/api" - ) + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/api" + ) - func main() { - gbot := gobot.NewMaster() + func main() { + gbot := gobot.NewMaster() - // Starts the API server on default port 3000 - api.NewAPI(gbot).Start() + // Starts the API server on default port 3000 + api.NewAPI(gbot).Start() - // Accessible via http://localhost:3000/api/commands/say_hello - gbot.AddCommand("say_hello", func(params map[string]interface{}) interface{} { - return "Master says hello!" - }) + // Accessible via http://localhost:3000/api/commands/say_hello + gbot.AddCommand("say_hello", func(params map[string]interface{}) interface{} { + return "Master says hello!" + }) - hello := gbot.AddRobot(gobot.NewRobot("Eve")) + hello := gbot.AddRobot(gobot.NewRobot("Eve")) - // Accessible via http://localhost:3000/api/robots/Eve/commands/say_hello - hello.AddCommand("say_hello", func(params map[string]interface{}) interface{} { - return fmt.Sprintf("%v says hello!", hello.Name) - }) + // Accessible via http://localhost:3000/api/robots/Eve/commands/say_hello + hello.AddCommand("say_hello", func(params map[string]interface{}) interface{} { + return fmt.Sprintf("%v says hello!", hello.Name) + }) - gbot.Start() - } + gbot.Start() + } It follows Common Protocol for Programming Physical Input and Output (CPPP-IO) spec: https://gobot.io/x/cppp-io diff --git a/api/helpers_test.go b/api/helpers_test.go index 0a3336870..7e77d10f6 100644 --- a/api/helpers_test.go +++ b/api/helpers_test.go @@ -64,8 +64,10 @@ type testAdaptor struct { port string } -var testAdaptorConnect = func() (err error) { return } -var testAdaptorFinalize = func() (err error) { return } +var ( + testAdaptorConnect = func() (err error) { return } + testAdaptorFinalize = func() (err error) { return } +) func (t *testAdaptor) Finalize() (err error) { return testAdaptorFinalize() } func (t *testAdaptor) Connect() (err error) { return testAdaptorConnect() } diff --git a/api/robeaux/robeaux.go b/api/robeaux/robeaux.go index 59b5242b1..aeff2c806 100644 --- a/api/robeaux/robeaux.go +++ b/api/robeaux/robeaux.go @@ -86,18 +86,23 @@ type bindataFileInfo struct { func (fi bindataFileInfo) Name() string { return fi.name } + func (fi bindataFileInfo) Size() int64 { return fi.size } + func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } + func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } + func (fi bindataFileInfo) IsDir() bool { return false } + func (fi bindataFileInfo) Sys() interface{} { return nil } @@ -916,11 +921,13 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error @@ -1009,7 +1016,7 @@ func RestoreAsset(dir, name string) error { if err != nil { return err } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0o755)) if err != nil { return err } diff --git a/doc.go b/doc.go index 0d3f92674..ada79dd42 100644 --- a/doc.go +++ b/doc.go @@ -9,124 +9,124 @@ It provides a simple, yet powerful way to create solutions that incorporate mult Here is a "Classic Gobot" program that blinks an LED using an Arduino: - package main + package main - import ( - "time" + import ( + "time" - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/firmata" - ) + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/firmata" + ) - func main() { - firmataAdaptor := firmata.NewAdaptor("/dev/ttyACM0") - led := gpio.NewLedDriver(firmataAdaptor, "13") + func main() { + firmataAdaptor := firmata.NewAdaptor("/dev/ttyACM0") + led := gpio.NewLedDriver(firmataAdaptor, "13") - work := func() { - gobot.Every(1*time.Second, func() { - led.Toggle() - }) - } + work := func() { + gobot.Every(1*time.Second, func() { + led.Toggle() + }) + } - robot := gobot.NewRobot("bot", - []gobot.Connection{firmataAdaptor}, - []gobot.Device{led}, - work, - ) + robot := gobot.NewRobot("bot", + []gobot.Connection{firmataAdaptor}, + []gobot.Device{led}, + work, + ) - robot.Start() - } + robot.Start() + } # Metal Gobot You can also use Metal Gobot and pick and choose from the various Gobot packages to control hardware with nothing but pure idiomatic Golang code. For example: - package main + package main - import ( - "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/intel-iot/edison" - "time" - ) + import ( + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/intel-iot/edison" + "time" + ) - func main() { - e := edison.NewAdaptor() - e.Connect() + func main() { + e := edison.NewAdaptor() + e.Connect() - led := gpio.NewLedDriver(e, "13") - led.Start() + led := gpio.NewLedDriver(e, "13") + led.Start() - for { - led.Toggle() - time.Sleep(1000 * time.Millisecond) - } - } + for { + led.Toggle() + time.Sleep(1000 * time.Millisecond) + } + } # Master Gobot Finally, you can use Master Gobot to add the complete Gobot API or control swarms of Robots: - package main - - import ( - "fmt" - "time" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/sphero" - ) - - func NewSwarmBot(port string) *gobot.Robot { - spheroAdaptor := sphero.NewAdaptor(port) - spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) - spheroDriver.SetName("Sphero" + port) - - work := func() { - spheroDriver.Stop() - - spheroDriver.On(sphero.Collision, func(data interface{}) { - fmt.Println("Collision Detected!") - }) - - gobot.Every(1*time.Second, func() { - spheroDriver.Roll(100, uint16(gobot.Rand(360))) - }) - gobot.Every(3*time.Second, func() { - spheroDriver.SetRGB(uint8(gobot.Rand(255)), - uint8(gobot.Rand(255)), - uint8(gobot.Rand(255)), - ) - }) - } - - robot := gobot.NewRobot("sphero", - []gobot.Connection{spheroAdaptor}, - []gobot.Device{spheroDriver}, - work, - ) - - return robot - } - - func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() - - spheros := []string{ - "/dev/rfcomm0", - "/dev/rfcomm1", - "/dev/rfcomm2", - "/dev/rfcomm3", - } - - for _, port := range spheros { - master.AddRobot(NewSwarmBot(port)) - } - - master.Start() - } + package main + + import ( + "fmt" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/api" + "gobot.io/x/gobot/v2/platforms/sphero" + ) + + func NewSwarmBot(port string) *gobot.Robot { + spheroAdaptor := sphero.NewAdaptor(port) + spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) + spheroDriver.SetName("Sphero" + port) + + work := func() { + spheroDriver.Stop() + + spheroDriver.On(sphero.Collision, func(data interface{}) { + fmt.Println("Collision Detected!") + }) + + gobot.Every(1*time.Second, func() { + spheroDriver.Roll(100, uint16(gobot.Rand(360))) + }) + gobot.Every(3*time.Second, func() { + spheroDriver.SetRGB(uint8(gobot.Rand(255)), + uint8(gobot.Rand(255)), + uint8(gobot.Rand(255)), + ) + }) + } + + robot := gobot.NewRobot("sphero", + []gobot.Connection{spheroAdaptor}, + []gobot.Device{spheroDriver}, + work, + ) + + return robot + } + + func main() { + master := gobot.NewMaster() + api.NewAPI(master).Start() + + spheros := []string{ + "/dev/rfcomm0", + "/dev/rfcomm1", + "/dev/rfcomm2", + "/dev/rfcomm3", + } + + for _, port := range spheros { + master.AddRobot(NewSwarmBot(port)) + } + + master.Start() + } Copyright (c) 2013-2018 The Hybrid Group. Licensed under the Apache 2.0 license. */ diff --git a/drivers/aio/aio.go b/drivers/aio/aio.go index 4b8bd9638..a8d5b339a 100644 --- a/drivers/aio/aio.go +++ b/drivers/aio/aio.go @@ -4,11 +4,9 @@ import ( "errors" ) -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") -) +// ErrAnalogReadUnsupported is error resulting when a driver attempts to use +// hardware capabilities which a connection does not support +var ErrAnalogReadUnsupported = errors.New("AnalogRead is not supported by this platform") const ( // Error event @@ -23,12 +21,12 @@ const ( // AnalogReader interface represents an Adaptor which has AnalogRead capabilities type AnalogReader interface { - //gobot.Adaptor + // gobot.Adaptor AnalogRead(pin string) (val int, err error) } // AnalogWriter interface represents an Adaptor which has AnalogWrite capabilities type AnalogWriter interface { - //gobot.Adaptor + // gobot.Adaptor AnalogWrite(pin string, val int) (err error) } diff --git a/drivers/aio/analog_actuator_driver_test.go b/drivers/aio/analog_actuator_driver_test.go index ced579586..3508fe720 100644 --- a/drivers/aio/analog_actuator_driver_test.go +++ b/drivers/aio/analog_actuator_driver_test.go @@ -45,7 +45,7 @@ func TestAnalogActuatorDriverWithScaler(t *testing.T) { } func TestAnalogActuatorDriverLinearScaler(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { fromMin float64 fromMax float64 input float64 diff --git a/drivers/aio/analog_sensor_driver.go b/drivers/aio/analog_sensor_driver.go index fb8aaf2ab..450265955 100644 --- a/drivers/aio/analog_sensor_driver.go +++ b/drivers/aio/analog_sensor_driver.go @@ -77,8 +77,8 @@ func (a *AnalogSensorDriver) Start() (err error) { // cyclic reading deactivated return } - var oldRawValue = 0 - var oldValue = 0.0 + oldRawValue := 0 + oldValue := 0.0 go func() { timer := time.NewTimer(a.interval) timer.Stop() diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index 12e94dc2f..1b6a048a7 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -56,7 +56,7 @@ func TestAnalogSensorDriver(t *testing.T) { func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { // the input scales per default from 0...255 - var tests = map[string]struct { + tests := map[string]struct { toMin float64 toMax float64 input int diff --git a/drivers/aio/grove_temperature_sensor_driver.go b/drivers/aio/grove_temperature_sensor_driver.go index 2998b9811..78304a110 100644 --- a/drivers/aio/grove_temperature_sensor_driver.go +++ b/drivers/aio/grove_temperature_sensor_driver.go @@ -27,8 +27,8 @@ type GroveTemperatureSensorDriver struct { // "ReadValue" - See AnalogDriverSensor.ReadValue func NewGroveTemperatureSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GroveTemperatureSensorDriver { t := NewTemperatureSensorDriver(a, pin, v...) - ntc := TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3975} //Ohm, R25=10k - t.SetNtcScaler(1023, 10000, false, ntc) //Ohm, reference value: 1023, series R: 10k + ntc := TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3975} // Ohm, R25=10k + t.SetNtcScaler(1023, 10000, false, ntc) // Ohm, reference value: 1023, series R: 10k d := &GroveTemperatureSensorDriver{ TemperatureSensorDriver: t, diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index 2fe8f75e3..c7a3a3070 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -21,7 +21,7 @@ func TestGroveTemperatureSensorDriver(t *testing.T) { } func TestGroveTemperatureSensorDriverScaling(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { input int want float64 }{ diff --git a/drivers/aio/temperature_sensor_driver.go b/drivers/aio/temperature_sensor_driver.go index f410e5c31..55c5484c0 100644 --- a/drivers/aio/temperature_sensor_driver.go +++ b/drivers/aio/temperature_sensor_driver.go @@ -126,7 +126,7 @@ func (n *TemperatureSensorNtcConf) getTemp(rntc float64) float64 { func (n *TemperatureSensorNtcConf) initialize() { n.t0 = float64(n.TC0) + kelvinOffset if n.B <= 0 { - //B=[ln(R0)-ln(R1)]/(1/T0-1/T1) + // B=[ln(R0)-ln(R1)]/(1/T0-1/T1) T1 := float64(n.TC1) + kelvinOffset n.B = (1/n.t0 - 1/T1) n.B = (math.Log(n.R0) - math.Log(n.R1)) / n.B // 2000K...5000K diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index 0610364e1..1ae246e8f 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -19,7 +19,7 @@ func TestTemperatureSensorDriver(t *testing.T) { } func TestTemperatureSensorDriverNtcScaling(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { input int want float64 }{ @@ -36,8 +36,8 @@ func TestTemperatureSensorDriverNtcScaling(t *testing.T) { } a := newAioTestAdaptor() d := NewTemperatureSensorDriver(a, "4") - ntc1 := TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3950} //Ohm, R25=10k, B=3950 - d.SetNtcScaler(255, 1000, true, ntc1) //Ohm, reference value: 3300, series R: 1k + ntc1 := TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3950} // Ohm, R25=10k, B=3950 + d.SetNtcScaler(255, 1000, true, ntc1) // Ohm, reference value: 3300, series R: 1k for name, tt := range tests { t.Run(name, func(t *testing.T) { // arrange @@ -55,7 +55,7 @@ func TestTemperatureSensorDriverNtcScaling(t *testing.T) { } func TestTemperatureSensorDriverLinearScaling(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { input int want float64 }{ @@ -93,8 +93,8 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.T) { sem := make(chan bool, 1) a := newAioTestAdaptor() d := NewTemperatureSensorDriver(a, "1") - 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 + 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 a.TestAdaptorAnalogRead(func() (val int, err error) { val = 585 @@ -168,7 +168,7 @@ func TestTempDriverSetName(t *testing.T) { } func TestTempDriver_initialize(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { input TemperatureSensorNtcConf want TemperatureSensorNtcConf }{ diff --git a/drivers/common/mfrc522/mfrc522_pcd.go b/drivers/common/mfrc522/mfrc522_pcd.go index 34ace2574..a6cad3495 100644 --- a/drivers/common/mfrc522/mfrc522_pcd.go +++ b/drivers/common/mfrc522/mfrc522_pcd.go @@ -20,8 +20,10 @@ type busConnection interface { WriteByteData(reg byte, data byte) error } -var versions = map[uint8]string{0x12: "Counterfeit", 0x88: "FM17522", 0x89: "FM17522E", - 0x90: "MFRC522 0.0", 0x91: "MFRC522 1.0", 0x92: "MFRC522 2.0", 0xB2: "FM17522 1"} +var versions = map[uint8]string{ + 0x12: "Counterfeit", 0x88: "FM17522", 0x89: "FM17522E", + 0x90: "MFRC522 0.0", 0x91: "MFRC522 1.0", 0x92: "MFRC522 2.0", 0xB2: "FM17522 1", +} // MFRC522Common is the Gobot Driver for MFRC522 RFID. // datasheet: @@ -155,7 +157,8 @@ func (d *MFRC522Common) stopCrypto1() error { } func (d *MFRC522Common) communicateWithPICC(command uint8, sendData []byte, backData []byte, txLastBits uint8, - checkCRC bool) error { + checkCRC bool, +) error { irqEn := 0x00 waitIRq := uint8(0x00) switch command { diff --git a/drivers/common/mfrc522/mfrc522_pcd_register.go b/drivers/common/mfrc522/mfrc522_pcd_register.go index 416f6ff3e..042e145aa 100644 --- a/drivers/common/mfrc522/mfrc522_pcd_register.go +++ b/drivers/common/mfrc522/mfrc522_pcd_register.go @@ -12,8 +12,8 @@ const ( commandRegCalcCRC = 0x03 // activates the CRC coprocessor or performs a self-test commandRegTransmit = 0x04 // transmits data from the FIFO buffer // 0x05, 0x06 not used - //commandRegNoCmdChange = 0x07 // no command change, can be used to modify the Command register bits without - //commandRegReceive = 0x08 // activates the receiver circuits + // commandRegNoCmdChange = 0x07 // no command change, can be used to modify the Command register bits without + // commandRegReceive = 0x08 // activates the receiver circuits // 0x09..0x0B not used commandRegTransceive = 0x0C // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission // 0x0D reserved @@ -57,10 +57,10 @@ const ( comIrqRegErrIRq1anyBit = 0x02 // bit 1: error bit in the Error register is set, if 1 // Status1 register’s LoAlert bit is set in opposition to the LoAlert bit, the LoAlertIRq bit stores this event and // can only be reset as indicated by the Set1 bit in this register - //comIrqRegLoAlertIRqBit = 0x04 // bit 2: if 1, see above + // comIrqRegLoAlertIRqBit = 0x04 // bit 2: if 1, see above // the Status1 register’s HiAlert bit is set in opposition to the HiAlert bit, the HiAlertIRq bit stores this event // and can only be reset as indicated by the Set1 bit in this register - //comIrqRegHiAlertIRqBit = 0x08 // bit 3: if 1, see above + // comIrqRegHiAlertIRqBit = 0x08 // bit 3: if 1, see above // If a command terminates, for example, when the Command register changes its value from any command to Idle command. // If an unknown command is started, the Command register Command[3:0] value changes to the idle state and the // IdleIRq bit is set. The microcontroller starting the Idle command does not set the IdleIRq bit. @@ -71,28 +71,28 @@ const ( comIrqRegTxIRqBit = 0x40 // bit 6: set to 1, immediately after the last bit of the transmitted data was sent out // 1: indicates that the marked bits in the register are set // 0: indicates that the marked bits in the register are cleared - //comIrqRegSet1Bit = 0x80 // bit 7: see above + // comIrqRegSet1Bit = 0x80 // bit 7: see above ) const ( regDivIrq = 0x05 // diverse interrupt request bits // ------------ values -------------------- - //divIrqRegReset = 0x00 // see table 31 of data sheet - //divIrqRegReserved01 = 0x03 + // divIrqRegReset = 0x00 // see table 31 of data sheet + // divIrqRegReserved01 = 0x03 divIrqRegCRCIRqBit = 0x04 // bit 2: the CalcCRC command is active and all data is processed - //divIrqRegReservedBit3 = 0x08 + // divIrqRegReservedBit3 = 0x08 // this interrupt is set when either a rising or falling signal edge is detected - //divIrqRegMfinActIRqBit = 0x10 // bit 4: MFIN is active; see above - //divIrqRegReserved56 = 0x60 + // divIrqRegMfinActIRqBit = 0x10 // bit 4: MFIN is active; see above + // divIrqRegReserved56 = 0x60 // 1: indicates that the marked bits in the register are set // 0: indicates that the marked bits in the register are cleared - //divIrqRegSet2Bit = 0x80 // bit 7: see above + // divIrqRegSet2Bit = 0x80 // bit 7: see above ) const ( regError = 0x06 // error bits showing the error status of the last command executed // ------------ values -------------------- - //errorRegReset = 0x00 // see table 33 of data sheet + // errorRegReset = 0x00 // see table 33 of data sheet // set to logic 1 if the SOF is incorrect automatically cleared during receiver start-up phase bit is only valid for // 106 kBd; during the MFAuthent command, the ProtocolErr bit is set to logic 1 if the number of bytes received in one // data stream is incorrect @@ -105,10 +105,10 @@ const ( // cleared automatically at receiver start-up phase; only valid during the bitwise anticollision at 106 kBd; always // set to logic 0 during communication protocols at 212 kBd, 424 kBd and 848 kBd errorRegCollErrBit = 0x08 // bit 3: a bit-collision is detected, see above - //the host or a MFRC522’s internal state machine (e.g. receiver) tries to write data to the FIFO buffer even though + // the host or a MFRC522’s internal state machine (e.g. receiver) tries to write data to the FIFO buffer even though // it is already full errorRegBufferOvflBit = 0x10 // bit 4: FIFO is full, see above - //errorRegReservedBit5 = 0x20 + // errorRegReservedBit5 = 0x20 // the antenna drivers are automatically switched off errorRegTempErrBit = 0x40 // bit 6: internal temperature sensor detects overheating, see above // data is written into the FIFO buffer by the host during the MFAuthent command or if data is written into the FIFO @@ -125,25 +125,25 @@ const ( const ( regStatus2 = 0x08 // receiver and transmitter status bits // ------------ values -------------------- - //status2RegReset = 0x00 // see table 37 of data sheet + // status2RegReset = 0x00 // see table 37 of data sheet // bit 0..2 shows the state of the transmitter and receiver state machines - //status2RegModemStateIdle = 0x00 // idle - //status2RegModemStateWait = 0x01 // wait for the BitFraming register’s StartSend bit + // status2RegModemStateIdle = 0x00 // idle + // status2RegModemStateWait = 0x01 // wait for the BitFraming register’s StartSend bit // the minimum time for TxWait is defined by the TxWait register - //status2RegModemStateTxWait = 0x02 // wait until RF field is present if the TMode register’s TxWaitRF bit is set to logic 1 - //status2RegModemStateTransmitting = 0x03 + // status2RegModemStateTxWait = 0x02 // wait until RF field is present if the TMode register’s TxWaitRF bit is set to logic 1 + // status2RegModemStateTransmitting = 0x03 // the minimum time for RxWait is defined by the RxWait register - //status2RegModemStateRxWait = 0x04 // wait until RF field is present if the TMode register’s TxWaitRF bit is set to logic 1 - //status2RegModemStateWaitForData = 0x05 - //status2RegModemStateReceiving = 0x06 + // status2RegModemStateRxWait = 0x04 // wait until RF field is present if the TMode register’s TxWaitRF bit is set to logic 1 + // status2RegModemStateWaitForData = 0x05 + // status2RegModemStateReceiving = 0x06 // all data communication with the card is encrypted; can only be set to logic 1 by a successful execution of the // MFAuthent command; only valid in Read/Write mode for MIFARE standard cards; this bit is cleared by software status2RegMFCrypto1OnBit = 0x08 // bit 3: indicates that the MIFARE Crypto1 unit is switched on and, see above - //status2RegReserved45 = 0x30 + // status2RegReserved45 = 0x30 // 1: the I2C-bus input filter is set to the High-speed mode independent of the I2C-bus protocol // 0: the I2C-bus input filter is set to the I2C-bus protocol used - //status2RegI2cForceHSBit = 0x40 // I2C-bus input filter settings, see above - //status2RegTempSensClear1Bit = 0x80 // clears the temperature error if the temperature is below the alarm limit of 125C + // status2RegI2cForceHSBit = 0x40 // I2C-bus input filter settings, see above + // status2RegTempSensClear1Bit = 0x80 // clears the temperature error if the temperature is below the alarm limit of 125C ) const ( @@ -153,10 +153,10 @@ const ( const ( regFIFOLevel = 0x0A // number of bytes stored in the FIFO buffer // ------------ values -------------------- - //fifoLevelRegReset = 0x00 // see table 41 of data sheet + // fifoLevelRegReset = 0x00 // see table 41 of data sheet // indicates the number of bytes stored in the FIFO buffer writing to the FIFOData register increments and reading // decrements the FIFOLevel value - //fifoLevelRegValue = 0x7F // bit 0..6: see above + // fifoLevelRegValue = 0x7F // bit 0..6: see above // immediately clears the internal FIFO buffer’s read and write pointer and Error register’s BufferOvfl bit reading // this bit always returns 0 fifoLevelRegFlushBufferBit = 0x80 // bit 7: see above @@ -170,13 +170,13 @@ const ( const ( regControl = 0x0C // miscellaneous control registers // ------------ values -------------------- - //controlRegReset = 0x10 // see table 45 of data sheet + // controlRegReset = 0x10 // see table 45 of data sheet // indicates the number of valid bits in the last received byte // if this value is 000b, the whole byte is valid controlRegRxLastBits = 0x07 // bit 0..2: see above - //controlRegReserved3to5 = 0x38 - //controlRegTStartNowBit = 0x40 // bit 6: timer starts immediately, if 1; reading always returns logic 0 - //controlRegTStopNow = 0x80 // bit 7: timer stops immediately, if 1; reading always returns logic 0 + // controlRegReserved3to5 = 0x38 + // controlRegTStartNowBit = 0x40 // bit 6: timer starts immediately, if 1; reading always returns logic 0 + // controlRegTStopNow = 0x80 // bit 7: timer stops immediately, if 1; reading always returns logic 0 ) const ( @@ -186,7 +186,7 @@ const ( // used for transmission of bit oriented frames: defines the number of bits of the last byte that will be transmitted // 000b indicates that all bits of the last byte will be transmitted bitFramingRegTxLastBits = 0x07 // bit 0..2: see above - //bitFramingRegReservedBit3 = 0x08 + // bitFramingRegReservedBit3 = 0x08 // used for reception of bit-oriented frames: defines the bit position for the first bit received to be stored in the // FIFO buffer, example: // 0: LSB of the received bit is stored at bit position 0, the second received bit is stored at bit position 1 @@ -194,8 +194,8 @@ const ( // 7: LSB of the received bit is stored at bit position 7, the second received bit is stored in the next byte that // follows at bit position 0 // These bits are only to be used for bitwise anticollision at 106 kBd, for all other modes they are set to 0 - //bitFramingRegRxAlign = 0x70 // bit 4..6: see above - //starts the transmission of data, only valid in combination with the Transceive command + // bitFramingRegRxAlign = 0x70 // bit 4..6: see above + // starts the transmission of data, only valid in combination with the Transceive command bitFramingRegStartSendBit = 0x80 // bit 7: see above ) @@ -207,10 +207,10 @@ const ( // 01: indicates a bit-collision in the 1st bit // 08: indicates a bit-collision in the 8th bit // These bits will only be interpreted if the CollPosNotValid bit is set to logic 0 - //collRegCollPos = 0x1F // bit 0..4: read-only, see above + // collRegCollPos = 0x1F // bit 0..4: read-only, see above // no collision detected or the position of the collision is out of the range of CollPos[4:0], if set to 1 - //collRegCollPosNotValidBit = 0x20 // bit 5: read-only, see above - //collRegReservedBit6 = 0x40 + // collRegCollPosNotValidBit = 0x20 // bit 5: read-only, see above + // collRegReservedBit6 = 0x40 // all received bits will be cleared after a collision only used during bitwise anticollision at 106 kBd, otherwise it // is set to logic 1 collRegValuesAfterCollBit = 0x80 // bit 7: see above @@ -223,7 +223,7 @@ const ( const ( regMode = 0x11 // defines general modes for transmitting and receiving // ------------ values -------------------- - //modeRegReset = 0x3F // see table 55 of data sheet + // modeRegReset = 0x3F // see table 55 of data sheet // bit 0..1: defines the preset value for the CRC coprocessor for the CalcCRC command; Remark: during any // communication, the preset values are selected automatically according to the definition of bits in the rxModeReg // and TxMode registers @@ -231,16 +231,16 @@ const ( modeRegCRCPreset6363 = 0x01 // 0x6363 modeRegCRCPresetA671 = 0x10 // 0xA671 modeRegCRCPresetFFFF = 0x11 // 0xFFFF - //modeRegReservedBit2 = 0x04 + // modeRegReservedBit2 = 0x04 // defines the polarity of pin MFIN; Remark: the internal envelope signal is encoded active LOW, changing this bit // generates a MFinActIRq event modeRegPolMFinBit = 0x08 // bit 3: polarity of pin MFIN is active HIGH, is set to 1 - //modeRegReservedBit4 = 0x10 + // modeRegReservedBit4 = 0x10 modeRegTxWaitRFBit = 0x20 // bit 5: transmitter can only be started if an RF field is generated, if set to 1 - //modeRegReservedBit6 = 0x40 + // modeRegReservedBit6 = 0x40 // CRC coprocessor calculates the CRC with MSB first 0 in the CRCResult register the values for the CRCResultMSB[7:0] // bits and the CRCResultLSB[7:0] bits are bit reversed; Remark: during RF communication this bit is ignored - //modeRegMSBFirstBit = 0x80 // bit 7: see above, if set to 1 + // modeRegMSBFirstBit = 0x80 // bit 7: see above, if set to 1 ) const ( @@ -248,8 +248,8 @@ const ( regRxMode = 0x13 // defines reception data rate and framing // ------------ values -------------------- rxtxModeRegReset = 0x00 - //txModeRegReserved = 0x07 // bit 0..2 reserved for TX - //rxModeRegReserved = 0x03 // bit 0,1 reserved for RX + // txModeRegReserved = 0x07 // bit 0..2 reserved for TX + // rxModeRegReserved = 0x03 // bit 0,1 reserved for RX // 0: receiver is deactivated after receiving a data frame // 1: able to receive more than one data frame; only valid for data rates above 106 kBd in order to handle the // polling command; after setting this bit the Receive and Transceive commands will not terminate automatically. @@ -260,60 +260,60 @@ const ( // version 1.0 the CRC status is reflected in the signal CRCErr. // rxModeRegRxMultipleBit = 0x04 // an invalid received data stream (less than 4 bits received) will be ignored and the receiver remains active -//rxModeRegRxNoErrBit = 0x08 // bit 3 -//txModeRegInvModBit = 0x08 // bit 3: modulation of transmitted data is inverted, if 1 +// rxModeRegRxNoErrBit = 0x08 // bit 3 +// txModeRegInvModBit = 0x08 // bit 3: modulation of transmitted data is inverted, if 1 // bit 4..6: defines the bit rate during data transmission; the handles transfer speeds up to 848 kBd -//rxtxModeRegSpeed106kBd = 0x00 //106 kBd -//rxtxModeRegSpeed212kBd = 0x10 //212 kBd -//rxtxModeRegSpeed424kBd = 0x20 //424 kBd -//rxtxModeRegSpeed848kBd = 0x30 //848 kBd -//rxtxModeRegSpeedRes1 = 0x40 //reserved -//rxtxModeRegSpeedRes2 = 0x50 //reserved -//rxtxModeRegSpeedRes3 = 0x60 //reserved -//rxtxModeRegSpeedRes4 = 0x70 //reserved +// rxtxModeRegSpeed106kBd = 0x00 //106 kBd +// rxtxModeRegSpeed212kBd = 0x10 //212 kBd +// rxtxModeRegSpeed424kBd = 0x20 //424 kBd +// rxtxModeRegSpeed848kBd = 0x30 //848 kBd +// rxtxModeRegSpeedRes1 = 0x40 //reserved +// rxtxModeRegSpeedRes2 = 0x50 //reserved +// rxtxModeRegSpeedRes3 = 0x60 //reserved +// rxtxModeRegSpeedRes4 = 0x70 //reserved // RX: enables the CRC calculation during reception // TX: enables CRC generation during data transmission -//rxtxModeRegTxCRCEnBit = 0x80 // bit 7: can only be set to logic 0 at 106 kBd +// rxtxModeRegTxCRCEnBit = 0x80 // bit 7: can only be set to logic 0 at 106 kBd ) const ( regTxControl = 0x14 // controls the logical behavior of the antenna driver pins TX1 and TX2 // ------------ values -------------------- - //regtxControlRegReset = 0x80 // see table 61 of data sheet + // regtxControlRegReset = 0x80 // see table 61 of data sheet // signal on pin TX1 delivers the 13.56 MHz energy carrier modulated by the transmission data txControlRegTx1RFEn1outputBit = 0x01 // bit 0: see above // signal on pin TX2 delivers the 13.56 MHz energy carrier modulated by the transmission data txControlRegTx2RFEn1outputBit = 0x02 // bit 1: see above - //txControlRegReservedBit2 = 0x04 + // txControlRegReservedBit2 = 0x04 // signal on pin TX2 continuously delivers the unmodulated 13.56 MHz energy carrier0Tx2CW bit is enabled to modulate // the 13.56 MHz energy carrier - //txControlRegTx2CW1outputBit = 0x08 // bit 3: see above - //txControlRegInvTx1RFOffBit = 0x10 // bit 4: output signal on pin TX1 inverted if driver TX1 is disabled, if 1 - //txControlRegInvTx2RFOffBit = 0x20 // bit 5: output signal on pin TX2 inverted if driver TX2 is disabled, if 1 - //txControlRegInvTx1RFOnBit = 0x40 // bit 6: output signal on pin TX1 inverted if driver TX1 is enabled, if 1 - //txControlRegInvTx2RFOnBit = 0x80 // bit 7: output signal on pin TX2 inverted if driver TX2 is enabled, if 1 + // txControlRegTx2CW1outputBit = 0x08 // bit 3: see above + // txControlRegInvTx1RFOffBit = 0x10 // bit 4: output signal on pin TX1 inverted if driver TX1 is disabled, if 1 + // txControlRegInvTx2RFOffBit = 0x20 // bit 5: output signal on pin TX2 inverted if driver TX2 is disabled, if 1 + // txControlRegInvTx1RFOnBit = 0x40 // bit 6: output signal on pin TX1 inverted if driver TX1 is enabled, if 1 + // txControlRegInvTx2RFOnBit = 0x80 // bit 7: output signal on pin TX2 inverted if driver TX2 is enabled, if 1 ) const ( regTxASK = 0x15 // controls the setting of the transmission modulation // ------------ values -------------------- - //txASKRegReset = 0x00 // see table 63 of data sheet - //txASKRegReserved = 0x3F // bit 0..5 + // txASKRegReset = 0x00 // see table 63 of data sheet + // txASKRegReserved = 0x3F // bit 0..5 txASKRegForce100ASKBit = 0x40 // bit 6: forces a 100 % ASK modulation independent of the ModGsP register - //txASKRegReservedBit7 = 0x80 + // txASKRegReservedBit7 = 0x80 ) const ( - //regTxSel = 0x16 // selects the internal sources for the antenna driver - //regRxSel = 0x17 // selects internal receiver settings - //regRxThreshold = 0x18 // selects thresholds for the bit decoder - //regDemod = 0x19 // defines demodulator settings + // regTxSel = 0x16 // selects the internal sources for the antenna driver + // regRxSel = 0x17 // selects internal receiver settings + // regRxThreshold = 0x18 // selects thresholds for the bit decoder + // regDemod = 0x19 // defines demodulator settings // 0x1A // reserved for future use // 0x1B // reserved for future use - //regMfTx = 0x1C // controls some MIFARE communication transmit parameters - //regMfRx = 0x1D // controls some MIFARE communication receive parameters + // regMfTx = 0x1C // controls some MIFARE communication transmit parameters + // regMfRx = 0x1D // controls some MIFARE communication receive parameters // 0x1E // reserved for future use - //regSerialSpeed = 0x1F // selects the speed of the serial UART interface + // regSerialSpeed = 0x1F // selects the speed of the serial UART interface // Page 2: Configuration // 0x20 // reserved for future use @@ -333,8 +333,8 @@ const ( const ( regRFCfg = 0x26 // configures the receiver gain // ------------ values -------------------- - //rfcCfgRegReset = 0x48 // see table 97 of data sheet - //rfcCfgRegReserved03 = 0x07 + // rfcCfgRegReset = 0x48 // see table 97 of data sheet + // rfcCfgRegReserved03 = 0x07 // bit 4..6: defines the receiver’s signal voltage gain factor rfcCfgRegRxGain18dB = 0x00 rfcCfgRegRxGain23dB = 0x10 @@ -344,22 +344,22 @@ const ( rfcCfgRegRxGain38dB = 0x50 rfcCfgRegRxGain43dB = 0x60 rfcCfgRegRxGain48dB = 0x70 - //rfcCfgRegReserved7 = 0x80 + // rfcCfgRegReserved7 = 0x80 ) const ( // ------------ unused commands -------------------- -//regGsN = 0x27 // selects the conductance of the antenna driver pins TX1 and TX2 for modulation -//regCWGsP = 0x28 // defines the conductance of the p-driver output during periods of no modulation -//regModGsP = 0x29 // defines the conductance of the p-driver output during periods of modulation - +// regGsN = 0x27 // selects the conductance of the antenna driver pins TX1 and TX2 for modulation +// regCWGsP = 0x28 // defines the conductance of the p-driver output during periods of no modulation +// regModGsP = 0x29 // defines the conductance of the p-driver output during periods of modulation ) + const ( regTMode = 0x2A // defines settings for the internal timer regTPrescaler = 0x2B // the lower 8 bits of the TPrescaler value. The 4 high bits are in tModeReg. // ------------ values -------------------- - //tModeRegReset = 0x00 // see table 105 of data sheet - //tPrescalerRegReset = 0x00 // see table 107 of data sheet + // tModeRegReset = 0x00 // see table 105 of data sheet + // tPrescalerRegReset = 0x00 // see table 107 of data sheet // timer starts automatically at the end of the transmission in all communication modes at all speeds; if the // RxMode register’s RxMultiple bit is not set, the timer stops immediately after receiving the 5th bit (1 start // bit, 4 data bits); if the RxMultiple bit is set to logic 1 the timer never stops, in which case the timer can be @@ -368,22 +368,22 @@ const ( // bit 6,5: indicates that the timer is not influenced by the protocol; internal timer is running in // gated mode; Remark: in gated mode, the Status1 register’s TRunning bit is logic 1 when the timer is enabled by // the TMode register’s TGated bits; this bit does not influence the gating signal - //tModeRegTGatedNon = 0x00 // non-gated mode - //tModeRegTGatedMFIN = 0x20 // gated by pin MFIN - //tModeRegTGatedAUX1 = 0x40 // gated by pin AUX1 + // tModeRegTGatedNon = 0x00 // non-gated mode + // tModeRegTGatedMFIN = 0x20 // gated by pin MFIN + // tModeRegTGatedAUX1 = 0x40 // gated by pin AUX1 // 1: timer automatically restarts its count-down from the 16-bit timer reload value instead of counting down to zero // 0: timer decrements to 0 and the ComIrq register’s TimerIRq bit is set to logic 1 - //tModeRegTAutoRestartBit = 0x10 // bit 4, see above + // tModeRegTAutoRestartBit = 0x10 // bit 4, see above // defines the higher 4 bits of the TPrescaler value; The following formula is used to calculate the timer // frequency if the Demod register’s TPrescalEven bit in Demot register’s set to logic 0: // ftimer = 13.56 MHz / (2*TPreScaler+1); TPreScaler = [tPrescalerRegHi:tPrescalerRegLo] // TPrescaler value on 12 bits) (Default TPrescalEven bit is logic 0) // The following formula is used to calculate the timer frequency if the Demod register’s TPrescalEven bit is set // to logic 1: ftimer = 13.56 MHz / (2*TPreScaler+2). - //tModeRegtPrescalerRegValue25us = 0x0A9 // 169 => fRegtimer=40kHz, timer period of 25μs. - //tModeRegtPrescalerRegValue38us = 0x0FF // 255 => fRegtimer=26kHz, timer period of 38μs. - //tModeRegtPrescalerRegValue500us = 0xD3E // 3390 => fRegtimer= 2kHz, timer period of 500us. - //tModeRegtPrescalerRegValue604us = 0xFFF // 4095 => fRegtimer=1.65kHz, timer period of 604us. + // tModeRegtPrescalerRegValue25us = 0x0A9 // 169 => fRegtimer=40kHz, timer period of 25μs. + // tModeRegtPrescalerRegValue38us = 0x0FF // 255 => fRegtimer=26kHz, timer period of 38μs. + // tModeRegtPrescalerRegValue500us = 0xD3E // 3390 => fRegtimer= 2kHz, timer period of 500us. + // tModeRegtPrescalerRegValue604us = 0xFFF // 4095 => fRegtimer=1.65kHz, timer period of 604us. ) const ( @@ -399,8 +399,8 @@ const ( const ( // ------------ unused commands -------------------- - //regTCounterValueH = 0x2E // shows the 16-bit timer value - //regTCounterValueL = 0x2F + // regTCounterValueH = 0x2E // shows the 16-bit timer value + // regTCounterValueL = 0x2F // Page 3: Test Registers // 0x30 // reserved for future use diff --git a/drivers/common/mfrc522/mfrc522_pcd_test.go b/drivers/common/mfrc522/mfrc522_pcd_test.go index bf217a859..045c0e4f4 100644 --- a/drivers/common/mfrc522/mfrc522_pcd_test.go +++ b/drivers/common/mfrc522/mfrc522_pcd_test.go @@ -86,7 +86,7 @@ func Test_getVersion(t *testing.T) { } func Test_switchAntenna(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { target bool simRead byte wantWritten []byte diff --git a/drivers/common/mfrc522/mfrc522_picc.go b/drivers/common/mfrc522/mfrc522_picc.go index 3723181dc..32d2bae2f 100644 --- a/drivers/common/mfrc522/mfrc522_picc.go +++ b/drivers/common/mfrc522/mfrc522_picc.go @@ -36,16 +36,20 @@ const ( piccCommandMFRegTRANSFER = 0xB0 // Writes the contents of the internal data register to a block. // The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/dataRegsheet/MF0ICU1.pdf, Section 8.6) // The piccCommandMFRegREAD and piccCommandMFRegWRITE can also be used for MIFARE Ultralight. - //piccCommandULRegWRITE = 0xA2 // Writes one 4 byte page to the PICC. + // piccCommandULRegWRITE = 0xA2 // Writes one 4 byte page to the PICC. ) const piccReadWriteAuthBlock = uint8(11) -var piccKey = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} -var piccUserBlockAddresses = []byte{8, 9, 10} +var ( + piccKey = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + piccUserBlockAddresses = []byte{8, 9, 10} +) -var piccCardFromSak = map[uint8]string{0x08: "Classic 1K, Plus 2K-SE-1K(SL1)", 0x18: "Classic 4K, Plus 4K(SL1)", - 0x10: "Plus 2K(SL2)", 0x11: "Plus 4K(SL2)", 0x20: "Plus 2K-SE-1K(SL3), Plus 4K(SL3)"} +var piccCardFromSak = map[uint8]string{ + 0x08: "Classic 1K, Plus 2K-SE-1K(SL1)", 0x18: "Classic 4K, Plus 4K(SL1)", + 0x10: "Plus 2K(SL2)", 0x11: "Plus 4K(SL2)", 0x20: "Plus 2K-SE-1K(SL3), Plus 4K(SL3)", +} // IsCardPresent is used to poll for a card in range. After an successful request, the card is halted. func (d *MFRC522Common) IsCardPresent() error { diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index 94af0cc8f..4b16758fd 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -57,7 +57,6 @@ func TestBuzzerDriverOnError(t *testing.T) { return errors.New("write error") }) - //assert.Errorf(t, d.On(), "write error") assert.Errorf(t, d.On(), "write error") } diff --git a/drivers/gpio/grove_drivers.go b/drivers/gpio/grove_drivers.go index 80f1ab377..017fa7338 100644 --- a/drivers/gpio/grove_drivers.go +++ b/drivers/gpio/grove_drivers.go @@ -12,6 +12,7 @@ type GroveRelayDriver struct { // NewGroveRelayDriver return a new GroveRelayDriver given a DigitalWriter and pin. // // Adds the following API Commands: +// // "Toggle" - See RelayDriver.Toggle // "On" - See RelayDriver.On // "Off" - See RelayDriver.Off @@ -29,6 +30,7 @@ type GroveLedDriver struct { // NewGroveLedDriver return a new GroveLedDriver given a DigitalWriter and pin. // // Adds the following API Commands: +// // "Brightness" - See LedDriver.Brightness // "Toggle" - See LedDriver.Toggle // "On" - See LedDriver.On @@ -62,7 +64,8 @@ type GroveButtonDriver struct { // 10 Milliseconds given a DigitalReader and pin. // // Optionally accepts: -// time.Duration: Interval at which the ButtonDriver is polled for new information +// +// time.Duration: Interval at which the ButtonDriver is polled for new information func NewGroveButtonDriver(a DigitalReader, pin string, v ...time.Duration) *GroveButtonDriver { return &GroveButtonDriver{ ButtonDriver: NewButtonDriver(a, pin, v...), @@ -79,7 +82,8 @@ type GroveTouchDriver struct { // 10 Milliseconds given a DigitalReader and pin. // // Optionally accepts: -// time.Duration: Interval at which the ButtonDriver is polled for new information +// +// time.Duration: Interval at which the ButtonDriver is polled for new information func NewGroveTouchDriver(a DigitalReader, pin string, v ...time.Duration) *GroveTouchDriver { return &GroveTouchDriver{ ButtonDriver: NewButtonDriver(a, pin, v...), @@ -96,7 +100,8 @@ type GroveMagneticSwitchDriver struct { // 10 Milliseconds given a DigitalReader, name and pin. // // Optionally accepts: -// time.Duration: Interval at which the ButtonDriver is polled for new information +// +// time.Duration: Interval at which the ButtonDriver is polled for new information func NewGroveMagneticSwitchDriver(a DigitalReader, pin string, v ...time.Duration) *GroveMagneticSwitchDriver { return &GroveMagneticSwitchDriver{ ButtonDriver: NewButtonDriver(a, pin, v...), diff --git a/drivers/gpio/helpers_test.go b/drivers/gpio/helpers_test.go index 959ba7c65..b7031cab8 100644 --- a/drivers/gpio/helpers_test.go +++ b/drivers/gpio/helpers_test.go @@ -25,21 +25,25 @@ func (t *gpioTestAdaptor) TestAdaptorDigitalWrite(f func(pin string, val byte) ( defer t.mtx.Unlock() t.testAdaptorDigitalWrite = f } + func (t *gpioTestAdaptor) TestAdaptorServoWrite(f func(pin string, val byte) (err error)) { t.mtx.Lock() defer t.mtx.Unlock() t.testAdaptorServoWrite = f } + func (t *gpioTestAdaptor) TestAdaptorPwmWrite(f func(pin string, val byte) (err error)) { t.mtx.Lock() defer t.mtx.Unlock() t.testAdaptorPwmWrite = f } + func (t *gpioTestAdaptor) TestAdaptorAnalogRead(f func(pin string) (val int, err error)) { t.mtx.Lock() defer t.mtx.Unlock() t.testAdaptorAnalogRead = f } + func (t *gpioTestAdaptor) TestAdaptorDigitalRead(f func(pin string) (val int, err error)) { t.mtx.Lock() defer t.mtx.Unlock() @@ -51,21 +55,25 @@ func (t *gpioTestAdaptor) ServoWrite(pin string, val byte) (err error) { defer t.mtx.Unlock() return t.testAdaptorServoWrite(pin, val) } + func (t *gpioTestAdaptor) PwmWrite(pin string, val byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testAdaptorPwmWrite(pin, val) } + func (t *gpioTestAdaptor) AnalogRead(pin string) (val int, err error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testAdaptorAnalogRead(pin) } + func (t *gpioTestAdaptor) DigitalRead(pin string) (val int, err error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testAdaptorDigitalRead(pin) } + func (t *gpioTestAdaptor) DigitalWrite(pin string, val byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index 9e02e5a9b..4cbeef303 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -48,7 +48,6 @@ func TestLedDriver(t *testing.T) { err = d.Command("Brightness")(map[string]interface{}{"level": 100.0}) assert.Errorf(t, err.(error), "pwm error") - } func TestLedDriverStart(t *testing.T) { diff --git a/drivers/gpio/motor_driver_test.go b/drivers/gpio/motor_driver_test.go index b81ad5742..749cba7b8 100644 --- a/drivers/gpio/motor_driver_test.go +++ b/drivers/gpio/motor_driver_test.go @@ -17,8 +17,8 @@ func initTestMotorDriver() *MotorDriver { func TestMotorDriver(t *testing.T) { d := NewMotorDriver(newGpioTestAdaptor(), "1") assert.NotNil(t, d.Connection()) - } + func TestMotorDriverStart(t *testing.T) { d := initTestMotorDriver() assert.Nil(t, d.Start()) diff --git a/drivers/gpio/servo_driver.go b/drivers/gpio/servo_driver.go index 53a560bf8..461b842f7 100644 --- a/drivers/gpio/servo_driver.go +++ b/drivers/gpio/servo_driver.go @@ -43,7 +43,6 @@ func NewServoDriver(a ServoWriter, pin string) *ServoDriver { }) return s - } // Name returns the ServoDrivers name diff --git a/drivers/gpio/stepper_driver.go b/drivers/gpio/stepper_driver.go index 25a3d2c20..1a9469a33 100644 --- a/drivers/gpio/stepper_driver.go +++ b/drivers/gpio/stepper_driver.go @@ -19,21 +19,21 @@ var StepperModes = struct { DualPhaseStepping [][4]byte HalfStepping [][4]byte }{ - //1 cycle = 4 steps with lesser torque + // 1 cycle = 4 steps with lesser torque SinglePhaseStepping: [][4]byte{ {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, }, - //1 cycle = 4 steps with higher torque and current + // 1 cycle = 4 steps with higher torque and current DualPhaseStepping: [][4]byte{ {1, 0, 0, 1}, {1, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 1}, }, - //1 cycle = 8 steps with lesser torque than full stepping + // 1 cycle = 8 steps with lesser torque than full stepping HalfStepping: [][4]byte{ {1, 0, 0, 1}, {1, 0, 0, 0}, @@ -110,7 +110,7 @@ func (s *StepperDriver) Start() error { return nil } // Run continuously runs the stepper func (s *StepperDriver) Run() error { - //halt if already moving + // halt if already moving if s.moving { if err := s.Halt(); err != nil { return err @@ -196,7 +196,7 @@ func (s *StepperDriver) Move(stepsToMove int) error { } if s.moving { - //stop previous motion + // stop previous motion if err := s.Halt(); err != nil { return err } @@ -228,7 +228,7 @@ func (s *StepperDriver) Move(stepsToMove int) error { // getDelayPerStep gives the delay per step func (s *StepperDriver) getDelayPerStep() time.Duration { - //Do not remove *1000 and change duration to time.Millisecond. It has been done for a reason + // Do not remove *1000 and change duration to time.Millisecond. It has been done for a reason return time.Duration(60000*1000/(s.stepsPerRev*s.speed)) * time.Microsecond } @@ -239,7 +239,7 @@ func (s *StepperDriver) GetCurrentStep() int { // GetMaxSpeed gives the max RPM of motor func (s *StepperDriver) GetMaxSpeed() uint { - //considering time for 1 rev as no of steps per rev * 1.5 (min time req between each step) + // considering time for 1 rev as no of steps per rev * 1.5 (min time req between each step) return uint(60000 / (float64(s.stepsPerRev) * 1.5)) } diff --git a/drivers/gpio/tm1638_driver.go b/drivers/gpio/tm1638_driver.go index 4b23bb360..588671433 100644 --- a/drivers/gpio/tm1638_driver.go +++ b/drivers/gpio/tm1638_driver.go @@ -2,7 +2,6 @@ package gpio import ( "math" - "strings" "gobot.io/x/gobot/v2" @@ -62,7 +61,6 @@ func NewTM1638Driver(a gobot.Connection, clockPin string, dataPin string, strobe // Start initializes the tm1638, it uses a SPI-like communication protocol func (t *TM1638Driver) Start() error { - if err := t.pinStrobe.On(); err != nil { return err } diff --git a/drivers/i2c/adafruit1109_driver.go b/drivers/i2c/adafruit1109_driver.go index 7bd4afa7c..feae2530f 100644 --- a/drivers/i2c/adafruit1109_driver.go +++ b/drivers/i2c/adafruit1109_driver.go @@ -79,7 +79,7 @@ func NewAdafruit1109Driver(a Connector, options ...func(Config)) *Adafruit1109Dr D7: d.dataPinD7.String(), } - //rwPin := "B_6" not mapped in HD44780 driver + // rwPin := "B_6" not mapped in HD44780 driver // at test initialization, there seems rows and columns be switched // but inside the driver the row is used as row and col as column rows := 2 diff --git a/drivers/i2c/adafruit1109_driver_test.go b/drivers/i2c/adafruit1109_driver_test.go index f2c901374..ae7cb92de 100644 --- a/drivers/i2c/adafruit1109_driver_test.go +++ b/drivers/i2c/adafruit1109_driver_test.go @@ -91,7 +91,7 @@ func TestAdafruit1109Halt(t *testing.T) { } func TestAdafruit1109DigitalRead(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { read uint8 wantReg uint8 }{ @@ -138,7 +138,7 @@ func TestAdafruit1109DigitalRead(t *testing.T) { } func TestAdafruit1109SelectButton(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { read uint8 want uint8 }{ @@ -168,7 +168,7 @@ func TestAdafruit1109SelectButton(t *testing.T) { } func TestAdafruit1109UpButton(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { read uint8 want uint8 }{ @@ -198,7 +198,7 @@ func TestAdafruit1109UpButton(t *testing.T) { } func TestAdafruit1109DownButton(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { read uint8 want uint8 }{ @@ -228,7 +228,7 @@ func TestAdafruit1109DownButton(t *testing.T) { } func TestAdafruit1109LeftButton(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { read uint8 want uint8 }{ @@ -258,7 +258,7 @@ func TestAdafruit1109LeftButton(t *testing.T) { } func TestAdafruit1109RightButton(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { read uint8 want uint8 }{ diff --git a/drivers/i2c/adafruit_driver.go b/drivers/i2c/adafruit_driver.go index 1d534ebfd..3db354005 100644 --- a/drivers/i2c/adafruit_driver.go +++ b/drivers/i2c/adafruit_driver.go @@ -111,12 +111,16 @@ func NewAdafruitMotorHatDriver(conn Connector, options ...func(Config)) *Adafrui switch { case i == 0: dc = append(dc, adaFruitDCMotor{pwmPin: 8, in1Pin: 10, in2Pin: 9}) - st = append(st, adaFruitStepperMotor{pwmPinA: 8, pwmPinB: 13, - ain1: 10, ain2: 9, bin1: 11, bin2: 12, revSteps: 200, secPerStep: 0.1}) + st = append(st, adaFruitStepperMotor{ + pwmPinA: 8, pwmPinB: 13, + ain1: 10, ain2: 9, bin1: 11, bin2: 12, revSteps: 200, secPerStep: 0.1, + }) case i == 1: dc = append(dc, adaFruitDCMotor{pwmPin: 13, in1Pin: 11, in2Pin: 12}) - st = append(st, adaFruitStepperMotor{pwmPinA: 2, pwmPinB: 7, - ain1: 4, ain2: 3, bin1: 5, bin2: 6, revSteps: 200, secPerStep: 0.1}) + st = append(st, adaFruitStepperMotor{ + pwmPinA: 2, pwmPinB: 7, + ain1: 4, ain2: 3, bin1: 5, bin2: 6, revSteps: 200, secPerStep: 0.1, + }) case i == 2: dc = append(dc, adaFruitDCMotor{pwmPin: 2, in1Pin: 4, in2Pin: 3}) case i == 3: @@ -249,10 +253,10 @@ func (a *AdafruitMotorHatDriver) Halt() (err error) { return } func (a *AdafruitMotorHatDriver) setPWM(conn Connection, pin byte, on, off int32) (err error) { // register and values to be written to that register regVals := make(map[int][]byte) - regVals[0] = []byte{byte(_LedZeroOnL + 4*pin), byte(on & 0xff)} - regVals[1] = []byte{byte(_LedZeroOnH + 4*pin), byte(on >> 8)} - regVals[2] = []byte{byte(_LedZeroOffL + 4*pin), byte(off & 0xff)} - regVals[3] = []byte{byte(_LedZeroOffH + 4*pin), byte(off >> 8)} + regVals[0] = []byte{_LedZeroOnL + 4*pin, byte(on & 0xff)} + regVals[1] = []byte{_LedZeroOnH + 4*pin, byte(on >> 8)} + regVals[2] = []byte{_LedZeroOffL + 4*pin, byte(off & 0xff)} + regVals[3] = []byte{_LedZeroOffH + 4*pin, byte(off >> 8)} for i := 0; i < len(regVals); i++ { if _, err = conn.Write(regVals[i]); err != nil { return @@ -363,7 +367,6 @@ func (a *AdafruitMotorHatDriver) SetDCMotorSpeed(dcMotor int, speed int32) (err // RunDCMotor will set the appropriate pins to run the specified DC motor for // the given direction func (a *AdafruitMotorHatDriver) RunDCMotor(dcMotor int, dir AdafruitDirection) (err error) { - switch { case dir == AdafruitForward: if err = a.setPin(a.motorHatConnection, a.dcMotors[dcMotor].in2Pin, 0); err != nil { @@ -460,13 +463,13 @@ func (a *AdafruitMotorHatDriver) oneStep(motor int, dir AdafruitDirection, style pwmA = stepperMicrostepCurve[currStep-stepperMicrosteps*3] pwmB = stepperMicrostepCurve[stepperMicrosteps*4-currStep] } - } //switch + } // switch - //go to next 'step' and wrap around + // go to next 'step' and wrap around a.stepperMotors[motor].currentStep += stepperMicrosteps * 4 a.stepperMotors[motor].currentStep %= stepperMicrosteps * 4 - //only really used for microstepping, otherwise always on! + // only really used for microstepping, otherwise always on! if err = a.setPWM(a.motorHatConnection, a.stepperMotors[motor].pwmPinA, 0, int32(pwmA*16)); err != nil { return } diff --git a/drivers/i2c/ads1x15_driver.go b/drivers/i2c/ads1x15_driver.go index 1645f20ec..487dcb16e 100644 --- a/drivers/i2c/ads1x15_driver.go +++ b/drivers/i2c/ads1x15_driver.go @@ -1,13 +1,12 @@ package i2c import ( + "fmt" "log" "math" "sort" "strconv" "time" - - "fmt" ) const ads1x15DefaultAddress = 0x48 diff --git a/drivers/i2c/ads1x15_driver_1015_test.go b/drivers/i2c/ads1x15_driver_1015_test.go index ef882fa39..2e23bce0f 100644 --- a/drivers/i2c/ads1x15_driver_1015_test.go +++ b/drivers/i2c/ads1x15_driver_1015_test.go @@ -177,7 +177,7 @@ func TestADS1015_rawRead(t *testing.T) { // * read config register (16 bit, MSByte first) and wait for bit 15 is set // * read conversion register (16 bit, MSByte first) for the value // * apply two's complement converter, relates to one digit resolution (1/2^15), voltage multiplier - var tests = map[string]struct { + tests := map[string]struct { input []uint8 gain int dataRate int diff --git a/drivers/i2c/ads1x15_driver_1115_test.go b/drivers/i2c/ads1x15_driver_1115_test.go index 5b3e5559c..c1fd7d0e3 100644 --- a/drivers/i2c/ads1x15_driver_1115_test.go +++ b/drivers/i2c/ads1x15_driver_1115_test.go @@ -177,7 +177,7 @@ func TestADS1115_rawRead(t *testing.T) { // * read config register (16 bit, MSByte first) and wait for bit 15 is set // * read conversion register (16 bit, MSByte first) for the value // * apply two's complement converter, relates to one digit resolution (1/2^15), voltage multiplier - var tests = map[string]struct { + tests := map[string]struct { input []uint8 gain int dataRate int diff --git a/drivers/i2c/ads1x15_driver_test.go b/drivers/i2c/ads1x15_driver_test.go index d842367f9..9d93f770f 100644 --- a/drivers/i2c/ads1x15_driver_test.go +++ b/drivers/i2c/ads1x15_driver_test.go @@ -15,7 +15,7 @@ var _ gobot.Driver = (*ADS1x15Driver)(nil) // that supports the AnalogReader interface var _ aio.AnalogReader = (*ADS1x15Driver)(nil) -func initTestADS1x15DriverWithStubbedAdaptor() (*ADS1x15Driver, *i2cTestAdaptor) { +func initTestADS1x15DriverWithStubbedAdaptor() (*ADS1x15Driver, *i2cTestAdaptor) { //nolint:unparam // keep for tests a := newI2cTestAdaptor() const defaultDataRate = 3 dataRates := map[int]uint16{defaultDataRate: 0x0003} diff --git a/drivers/i2c/adxl345_driver.go b/drivers/i2c/adxl345_driver.go index 61df38e0b..5084bd2a6 100644 --- a/drivers/i2c/adxl345_driver.go +++ b/drivers/i2c/adxl345_driver.go @@ -15,8 +15,10 @@ const ( adxl345DefaultAddress = 0x53 ) -type ADXL345RateConfig uint8 -type ADXL345FsRangeConfig uint8 +type ( + ADXL345RateConfig uint8 + ADXL345FsRangeConfig uint8 +) const ( // registers are named according to the datasheet diff --git a/drivers/i2c/adxl345_driver_test.go b/drivers/i2c/adxl345_driver_test.go index c74f8104e..eb2bc7333 100644 --- a/drivers/i2c/adxl345_driver_test.go +++ b/drivers/i2c/adxl345_driver_test.go @@ -143,7 +143,7 @@ func TestADXL345RawXYZ(t *testing.T) { // * apply two's complement converter // // arrange - var tests = map[string]struct { + tests := map[string]struct { inputX []uint8 inputY []uint8 inputZ []uint8 @@ -210,7 +210,7 @@ func TestADXL345RawXYZError(t *testing.T) { func TestADXL345XYZ(t *testing.T) { // arrange - var tests = map[string]struct { + tests := map[string]struct { inputX []uint8 inputY []uint8 inputZ []uint8 diff --git a/drivers/i2c/bh1750_driver.go b/drivers/i2c/bh1750_driver.go index 0eee86c03..a2bbe9c2b 100644 --- a/drivers/i2c/bh1750_driver.go +++ b/drivers/i2c/bh1750_driver.go @@ -20,7 +20,6 @@ const ( ) // BH1750Driver is a driver for the BH1750 digital Ambient Light Sensor IC for I²C bus interface. -// type BH1750Driver struct { *Driver mode byte @@ -28,12 +27,13 @@ type BH1750Driver struct { // NewBH1750Driver creates a new driver with specified i2c interface // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewBH1750Driver(c Connector, options ...func(Config)) *BH1750Driver { h := &BH1750Driver{ Driver: NewDriver(c, "BH1750", bh1750DefaultAddress), @@ -51,7 +51,6 @@ func NewBH1750Driver(c Connector, options ...func(Config)) *BH1750Driver { // RawSensorData returns the raw value from the bh1750 func (h *BH1750Driver) RawSensorData() (level int, err error) { - buf := []byte{0, 0} bytesRead, err := h.connection.Read(buf) if bytesRead != 2 { @@ -68,7 +67,6 @@ func (h *BH1750Driver) RawSensorData() (level int, err error) { // Lux returns the adjusted value from the bh1750 func (h *BH1750Driver) Lux() (lux int, err error) { - lux, err = h.RawSensorData() lux = int(float64(lux) / 1.2) diff --git a/drivers/i2c/bh1750_driver_test.go b/drivers/i2c/bh1750_driver_test.go index a914d4407..c2cbf9745 100644 --- a/drivers/i2c/bh1750_driver_test.go +++ b/drivers/i2c/bh1750_driver_test.go @@ -1,12 +1,11 @@ package i2c import ( + "bytes" "errors" "strings" "testing" - "bytes" - "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/blinkm_driver.go b/drivers/i2c/blinkm_driver.go index 525331343..ef8711639 100644 --- a/drivers/i2c/blinkm_driver.go +++ b/drivers/i2c/blinkm_driver.go @@ -14,12 +14,13 @@ type BlinkMDriver struct { // NewBlinkMDriver creates a new BlinkMDriver. // // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewBlinkMDriver(c Connector, options ...func(Config)) *BlinkMDriver { b := &BlinkMDriver{ Driver: NewDriver(c, "BlinkM", blinkmDefaultAddress), diff --git a/drivers/i2c/blinkm_driver_test.go b/drivers/i2c/blinkm_driver_test.go index 519931a25..e3a00e73b 100644 --- a/drivers/i2c/blinkm_driver_test.go +++ b/drivers/i2c/blinkm_driver_test.go @@ -154,7 +154,6 @@ func TestBlinkMColor(t *testing.T) { _, err := d.Color() assert.Errorf(t, err, "write error") - } func TestBlinkMFade(t *testing.T) { @@ -165,7 +164,6 @@ func TestBlinkMFade(t *testing.T) { err := d.Fade(100, 100, 100) assert.Errorf(t, err, "write error") - } func TestBlinkMRGB(t *testing.T) { @@ -176,5 +174,4 @@ func TestBlinkMRGB(t *testing.T) { err := d.Rgb(100, 100, 100) assert.Errorf(t, err, "write error") - } diff --git a/drivers/i2c/bme280_driver.go b/drivers/i2c/bme280_driver.go index a42a1851c..d3767cdc1 100644 --- a/drivers/i2c/bme280_driver.go +++ b/drivers/i2c/bme280_driver.go @@ -213,7 +213,6 @@ func (d *BME280Driver) initHumidity() error { } return d.connection.WriteByteData(bmp280RegCtrl, cmr) - } func (d *BME280Driver) rawHumidity() (uint32, error) { diff --git a/drivers/i2c/bmp180_driver.go b/drivers/i2c/bmp180_driver.go index 2d52a063e..a4cd1c085 100644 --- a/drivers/i2c/bmp180_driver.go +++ b/drivers/i2c/bmp180_driver.go @@ -160,7 +160,6 @@ func (d *BMP180Driver) initialization() error { return err } return binary.Read(buf, binary.BigEndian, &d.calCoeffs.md) - } func (d *BMP180Driver) rawTemp() (int16, error) { diff --git a/drivers/i2c/bmp180_driver_test.go b/drivers/i2c/bmp180_driver_test.go index 35056977b..de26fdfaa 100644 --- a/drivers/i2c/bmp180_driver_test.go +++ b/drivers/i2c/bmp180_driver_test.go @@ -201,8 +201,8 @@ func TestBMP180_initialization(t *testing.T) { } func TestBMP180_bmp180PauseForReading(t *testing.T) { - assert.Equal(t, time.Duration(5*time.Millisecond), bmp180PauseForReading(BMP180UltraLowPower)) - assert.Equal(t, time.Duration(8*time.Millisecond), bmp180PauseForReading(BMP180Standard)) - assert.Equal(t, time.Duration(14*time.Millisecond), bmp180PauseForReading(BMP180HighResolution)) - assert.Equal(t, time.Duration(26*time.Millisecond), bmp180PauseForReading(BMP180UltraHighResolution)) + assert.Equal(t, 5*time.Millisecond, bmp180PauseForReading(BMP180UltraLowPower)) + assert.Equal(t, 8*time.Millisecond, bmp180PauseForReading(BMP180Standard)) + assert.Equal(t, 14*time.Millisecond, bmp180PauseForReading(BMP180HighResolution)) + assert.Equal(t, 26*time.Millisecond, bmp180PauseForReading(BMP180UltraHighResolution)) } diff --git a/drivers/i2c/bmp280_driver.go b/drivers/i2c/bmp280_driver.go index cea919de4..ebf5207d0 100644 --- a/drivers/i2c/bmp280_driver.go +++ b/drivers/i2c/bmp280_driver.go @@ -13,9 +13,11 @@ const bmp280Debug = true // this is also true for bme280 (which using this address as well) const bmp280DefaultAddress = 0x77 -type BMP280PressureOversampling uint8 -type BMP280TemperatureOversampling uint8 -type BMP280IIRFilter uint8 +type ( + BMP280PressureOversampling uint8 + BMP280TemperatureOversampling uint8 + BMP280IIRFilter uint8 +) const ( bmp280RegCalib00 = 0x88 // 12 x 16 bit calibration data (T1..T3, P1..P9) @@ -245,7 +247,7 @@ func (d *BMP280Driver) initialization() error { return err } - ctrlReg := uint8(d.ctrlPwrMode) | uint8(d.ctrlPressOversamp)<<2 | uint8(d.ctrlTempOversamp)<<5 + ctrlReg := d.ctrlPwrMode | uint8(d.ctrlPressOversamp)<<2 | uint8(d.ctrlTempOversamp)<<5 if err := d.connection.WriteByteData(bmp280RegCtrl, ctrlReg); err != nil { return err } diff --git a/drivers/i2c/bmp388_driver.go b/drivers/i2c/bmp388_driver.go index d7bf2f30b..a5dda145a 100644 --- a/drivers/i2c/bmp388_driver.go +++ b/drivers/i2c/bmp388_driver.go @@ -14,8 +14,10 @@ const bmp388Debug = false const bmp388DefaultAddress = 0x77 // BMP388Accuracy accuracy type -type BMP388Accuracy uint8 -type BMP388IIRFilter uint8 +type ( + BMP388Accuracy uint8 + BMP388IIRFilter uint8 +) const ( bmp388ChipID = 0x50 @@ -136,7 +138,7 @@ func (d *BMP388Driver) Temperature(accuracy BMP388Accuracy) (temp float32, err e var rawT int32 - mode := uint8(d.ctrlPwrMode)<<4 | bmp388PWRCTRLPressEnableBit | bmp388PWRCTRLTempEnableBit + mode := d.ctrlPwrMode<<4 | bmp388PWRCTRLPressEnableBit | bmp388PWRCTRLTempEnableBit if err = d.connection.WriteByteData(bmp388RegPWRCTRL, mode); err != nil { return 0, err } @@ -160,7 +162,7 @@ func (d *BMP388Driver) Pressure(accuracy BMP388Accuracy) (press float32, err err var rawT, rawP int32 - mode := uint8(d.ctrlPwrMode)<<4 | bmp388PWRCTRLPressEnableBit | bmp388PWRCTRLTempEnableBit + mode := d.ctrlPwrMode<<4 | bmp388PWRCTRLPressEnableBit | bmp388PWRCTRLTempEnableBit if err = d.connection.WriteByteData(bmp388RegPWRCTRL, mode); err != nil { return 0, err } @@ -194,7 +196,6 @@ func (d *BMP388Driver) Altitude(accuracy BMP388Accuracy) (alt float32, err error // initialization reads the calibration coefficients. func (d *BMP388Driver) initialization() error { - chipID, err := d.connection.ReadByteData(bmp388RegChipID) if err != nil { return err diff --git a/drivers/i2c/ccs811_driver.go b/drivers/i2c/ccs811_driver.go index 1d50e6b4f..8434d770d 100644 --- a/drivers/i2c/ccs811_driver.go +++ b/drivers/i2c/ccs811_driver.go @@ -20,33 +20,33 @@ const ( const ( - //the default I2C address for the ccs811 applies for ADDR to GND, for ADDR to VDD it will be 0x5B + // the default I2C address for the ccs811 applies for ADDR to GND, for ADDR to VDD it will be 0x5B ccs811DefaultAddress = 0x5A - //Registers, all definitions have been taken from the datasheet - //Single byte read only register which indicates if a device is active, if new data is available or if an error occurred. + // Registers, all definitions have been taken from the datasheet + // Single byte read only register which indicates if a device is active, if new data is available or if an error occurred. ccs811RegStatus = 0x00 - //This is Single byte register, which is used to enable sensor drive mode and interrupts. + // This is Single byte register, which is used to enable sensor drive mode and interrupts. ccs811RegMeasMode = 0x01 - //This multi-byte read only register contains the calculated eCO2 (ppm) and eTVOC (ppb) values followed by the STATUS register, ERROR_ID register and the RAW_DATA register. + // This multi-byte read only register contains the calculated eCO2 (ppm) and eTVOC (ppb) values followed by the STATUS register, ERROR_ID register and the RAW_DATA register. ccs811RegAlgResultData = 0x02 - //Two byte read only register which contains the latest readings from the sensor. - //ccs811RegRawData = 0x03 - //A multi-byte register that can be written with the current Humidity and Temperature values if known. - //ccs811RegEnvData = 0x05 - //Register that holds the NTC value used for temperature calcualtions + // Two byte read only register which contains the latest readings from the sensor. + // ccs811RegRawData = 0x03 + // A multi-byte register that can be written with the current Humidity and Temperature values if known. + // ccs811RegEnvData = 0x05 + // Register that holds the NTC value used for temperature calculations ccs811RegNtc = 0x06 - //Asserting the SW_RESET will restart the CCS811 in Boot mode to enable new application firmware to be downloaded. + // Asserting the SW_RESET will restart the CCS811 in Boot mode to enable new application firmware to be downloaded. ccs811RegSwReset = 0xFF - //Single byte read only register which holds the HW ID which is 0x81 for this family of CCS81x devices. + // Single byte read only register which holds the HW ID which is 0x81 for this family of CCS81x devices. ccs811RegHwID = 0x20 - //Single byte read only register that contains the hardware version. The value is 0x1X + // Single byte read only register that contains the hardware version. The value is 0x1X ccs811RegHwVersion = 0x21 - //Two byte read only register which contain the version of the firmware bootloader stored in the CCS811 in the format Major.Minor.Trivial + // Two byte read only register which contain the version of the firmware bootloader stored in the CCS811 in the format Major.Minor.Trivial ccs811RegFwBootVersion = 0x23 - //Two byte read only register which contain the version of the firmware application stored in the CCS811 in the format Major.Minor.Trivial + // Two byte read only register which contain the version of the firmware application stored in the CCS811 in the format Major.Minor.Trivial ccs811RegFwAppVersion = 0x24 - //To change the mode of the CCS811 from Boot mode to running the application, a single byte write of 0xF4 is required. + // To change the mode of the CCS811 from Boot mode to running the application, a single byte write of 0xF4 is required. ccs811RegAppStart = 0xF4 // Constants @@ -54,21 +54,19 @@ const ( ccs811HwIDCode = 0x81 ) -var ( - // The sequence of bytes needed to do a software reset - ccs811SwResetSequence = []byte{0x11, 0xE5, 0x72, 0x8A} -) +// The sequence of bytes needed to do a software reset +var ccs811SwResetSequence = []byte{0x11, 0xE5, 0x72, 0x8A} // CCS811Status represents the current status of the device defined by the ccs811RegStatus. // The following definitions were taken from https://ams.com/documents/20143/36005/CCS811_DS000459_6-00.pdf/c7091525-c7e5-37ac-eedb-b6c6828b0dcf#page=15 type CCS811Status struct { - //There is some sort of error on the i2c bus or there is an error with the internal sensor + // There is some sort of error on the i2c bus or there is an error with the internal sensor HasError byte - //A new data sample is ready in ccs811RegAlgResultData + // A new data sample is ready in ccs811RegAlgResultData DataReady byte - //Valid application firmware loaded + // Valid application firmware loaded AppValid byte - //Firmware is in application mode. CCS811 is ready to take sensor measurements + // Firmware is in application mode. CCS811 is ready to take sensor measurements FwMode byte } @@ -86,12 +84,12 @@ func NewCCS811Status(data uint8) *CCS811Status { // The following definitions were taken from the bit fields of the ccs811RegMeasMode defined in // https://ams.com/documents/20143/36005/CCS811_DS000459_6-00.pdf/c7091525-c7e5-37ac-eedb-b6c6828b0dcf#page=16 type CCS811MeasMode struct { - //If intThresh is 1 a data measurement will only be taken when the sensor value meets the threshold constraint. - //The threshold value is set in the threshold register (0x10) + // If intThresh is 1 a data measurement will only be taken when the sensor value meets the threshold constraint. + // The threshold value is set in the threshold register (0x10) intThresh uint8 - //If intDataRdy is 1, the nINT signal (pin 3 of the device) will be driven low when new data is available. + // If intDataRdy is 1, the nINT signal (pin 3 of the device) will be driven low when new data is available. intDataRdy uint8 - //driveMode represents the sampling rate of the sensor. If the value is 0, the measurement process is idle. + // driveMode represents the sampling rate of the sensor. If the value is 0, the measurement process is idle. driveMode CCS811DriveMode } @@ -123,7 +121,7 @@ func NewCCS811Driver(c Connector, options ...func(Config)) *CCS811Driver { d := &CCS811Driver{ Driver: NewDriver(c, "CCS811", ccs811DefaultAddress), measMode: NewCCS811MeasMode(), - //Recommended resistance value is 100,000 + // Recommended resistance value is 100,000 ntcResistanceValue: 100000, } d.afterStart = d.initialize @@ -205,7 +203,7 @@ func (d *CCS811Driver) GetStatus() (*CCS811Status, error) { return cs, nil } -// GetTemperature returns the device temperature in celcius. +// GetTemperature returns the device temperature in celsius. // If you do not have an NTC resistor installed, this function should not be called func (d *CCS811Driver) GetTemperature() (float32, error) { d.mutex.Lock() @@ -319,7 +317,7 @@ func (d *CCS811Driver) resetDevice() error { // startApp starts the app code in the device. This operation has to be done after a // software reset to start taking sensor measurements. func (d *CCS811Driver) startApp() error { - //Write without data is needed to start the app code + // Write without data is needed to start the app code _, err := d.connection.Write([]byte{ccs811RegAppStart}) return err } diff --git a/drivers/i2c/ccs811_driver_test.go b/drivers/i2c/ccs811_driver_test.go index 956821443..8ac004940 100644 --- a/drivers/i2c/ccs811_driver_test.go +++ b/drivers/i2c/ccs811_driver_test.go @@ -42,11 +42,11 @@ func TestCCS811Options(t *testing.T) { func TestCCS811WithCCS811MeasMode(t *testing.T) { d := NewCCS811Driver(newI2cTestAdaptor(), WithCCS811MeasMode(CCS811DriveMode10Sec)) - assert.Equal(t, CCS811DriveMode(CCS811DriveMode10Sec), d.measMode.driveMode) + assert.Equal(t, CCS811DriveMode10Sec, d.measMode.driveMode) } func TestCCS811GetGasData(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { readReturn func([]byte) (int, error) eco2 uint16 tvoc uint16 @@ -99,7 +99,7 @@ func TestCCS811GetGasData(t *testing.T) { } func TestCCS811GetTemperature(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { readReturn func([]byte) (int, error) temp float32 err error @@ -155,7 +155,7 @@ func TestCCS811GetTemperature(t *testing.T) { } func TestCCS811HasData(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { readReturn func([]byte) (int, error) result bool err error diff --git a/drivers/i2c/drv2605l_driver.go b/drivers/i2c/drv2605l_driver.go index 24877a5ad..5adbbaf17 100644 --- a/drivers/i2c/drv2605l_driver.go +++ b/drivers/i2c/drv2605l_driver.go @@ -65,10 +65,9 @@ const ( // // Basic use: // -// haptic := i2c.NewDRV2605Driver(adaptor) -// haptic.SetSequence([]byte{1, 13}) -// haptic.Go() -// +// haptic := i2c.NewDRV2605Driver(adaptor) +// haptic.SetSequence([]byte{1, 13}) +// haptic.Go() type DRV2605LDriver struct { *Driver } @@ -76,12 +75,13 @@ type DRV2605LDriver struct { // NewDRV2605LDriver creates a new driver for the DRV2605L device. // // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewDRV2605LDriver(c Connector, options ...func(Config)) *DRV2605LDriver { d := &DRV2605LDriver{ Driver: NewDriver(c, "DRV2605L", drv2605DefaultAddress), diff --git a/drivers/i2c/grove_drivers.go b/drivers/i2c/grove_drivers.go index a5459951e..f54ff16fb 100644 --- a/drivers/i2c/grove_drivers.go +++ b/drivers/i2c/grove_drivers.go @@ -15,12 +15,13 @@ type GroveAccelerometerDriver struct { // NewGroveLcdDriver creates a new driver with specified i2c interface. // Params: -// conn Connector - the Adaptor to use with this Driver +// +// conn Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewGroveLcdDriver(a Connector, options ...func(Config)) *GroveLcdDriver { lcd := &GroveLcdDriver{ JHD1313M1Driver: NewJHD1313M1Driver(a), @@ -35,12 +36,13 @@ func NewGroveLcdDriver(a Connector, options ...func(Config)) *GroveLcdDriver { // NewGroveAccelerometerDriver creates a new driver with specified i2c interface // Params: -// conn Connector - the Adaptor to use with this Driver +// +// conn Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewGroveAccelerometerDriver(a Connector, options ...func(Config)) *GroveAccelerometerDriver { mma := &GroveAccelerometerDriver{ MMA7660Driver: NewMMA7660Driver(a), diff --git a/drivers/i2c/grove_drivers_test.go b/drivers/i2c/grove_drivers_test.go index eff163972..19f755897 100644 --- a/drivers/i2c/grove_drivers_test.go +++ b/drivers/i2c/grove_drivers_test.go @@ -8,8 +8,10 @@ import ( "gobot.io/x/gobot/v2" ) -var _ gobot.Driver = (*GroveLcdDriver)(nil) -var _ gobot.Driver = (*GroveAccelerometerDriver)(nil) +var ( + _ gobot.Driver = (*GroveLcdDriver)(nil) + _ gobot.Driver = (*GroveAccelerometerDriver)(nil) +) func initTestGroveLcdDriver() (driver *GroveLcdDriver) { driver, _ = initGroveLcdDriverWithStubbedAdaptor() diff --git a/drivers/i2c/grovepi_driver.go b/drivers/i2c/grovepi_driver.go index fea0dcbbd..bc5a799a4 100644 --- a/drivers/i2c/grovepi_driver.go +++ b/drivers/i2c/grovepi_driver.go @@ -29,9 +29,8 @@ const ( // GrovePiDriver is a driver for the GrovePi+ for I²C bus interface. // https://www.dexterindustries.com/grovepi/ // -// To use this driver with the GrovePi, it must be running the firmware >= 1.4.0 and and the system version >=3. +// To use this driver with the GrovePi, it must be running the firmware >= 1.4.0 and the system version >=3. // https://github.com/DexterInd/GrovePi/blob/master/README.md -// type GrovePiDriver struct { *Driver pins map[int]string @@ -39,12 +38,13 @@ type GrovePiDriver struct { // NewGrovePiDriver creates a new driver with specified i2c interface // Params: -// conn Connector - the Adaptor to use with this Driver +// +// conn Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewGrovePiDriver(c Connector, options ...func(Config)) *GrovePiDriver { d := &GrovePiDriver{ Driver: NewDriver(c, "GrovePi", grovePiDefaultAddress), diff --git a/drivers/i2c/grovepi_driver_test.go b/drivers/i2c/grovepi_driver_test.go index 23b16db5f..db6fd83e9 100644 --- a/drivers/i2c/grovepi_driver_test.go +++ b/drivers/i2c/grovepi_driver_test.go @@ -56,7 +56,7 @@ func TestGrovePiOptions(t *testing.T) { func TestGrovePiSomeRead(t *testing.T) { // arrange - var tests = map[string]struct { + tests := map[string]struct { usedPin int wantWritten []uint8 simResponse [][]uint8 @@ -179,7 +179,7 @@ func TestGrovePiSomeRead(t *testing.T) { func TestGrovePiSomeWrite(t *testing.T) { // arrange - var tests = map[string]struct { + tests := map[string]struct { usedPin int usedValue int wantWritten []uint8 diff --git a/drivers/i2c/hmc5883l_driver.go b/drivers/i2c/hmc5883l_driver.go index f2acbd34a..395ab8431 100644 --- a/drivers/i2c/hmc5883l_driver.go +++ b/drivers/i2c/hmc5883l_driver.go @@ -109,16 +109,17 @@ var hmc5883lGainBits = map[float64]int{ // NewHMC5883LDriver creates a new driver with specified i2c interface // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver -// i2c.WithHMC5883LSamplesAveraged(int) -// i2c.WithHMC5883LDataOutputRate(int) -// i2c.WithHMC5883LMeasurementFlow(int) -// i2c.WithHMC5883LGain(int) // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver +// i2c.WithHMC5883LSamplesAveraged(int) +// i2c.WithHMC5883LDataOutputRate(int) +// i2c.WithHMC5883LMeasurementFlow(int) +// i2c.WithHMC5883LGain(int) func NewHMC5883LDriver(c Connector, options ...func(Config)) *HMC5883LDriver { h := &HMC5883LDriver{ Driver: NewDriver(c, "HMC5883L", hmc5883lDefaultAddress), diff --git a/drivers/i2c/hmc5883l_driver_test.go b/drivers/i2c/hmc5883l_driver_test.go index c7b9b2dff..890ccefe1 100644 --- a/drivers/i2c/hmc5883l_driver_test.go +++ b/drivers/i2c/hmc5883l_driver_test.go @@ -61,7 +61,7 @@ func TestHMC5883LWithHMC5883LGain(t *testing.T) { func TestHMC5883LRead(t *testing.T) { // arrange - var tests = map[string]struct { + tests := map[string]struct { inputX []uint8 inputY []uint8 inputZ []uint8 @@ -136,7 +136,7 @@ func TestHMC5883L_readRawData(t *testing.T) { // * apply two's complement converter // // arrange - var tests = map[string]struct { + tests := map[string]struct { inputX []uint8 inputY []uint8 inputZ []uint8 diff --git a/drivers/i2c/hmc6352_driver.go b/drivers/i2c/hmc6352_driver.go index 6c9d8544c..8dd8c43f3 100644 --- a/drivers/i2c/hmc6352_driver.go +++ b/drivers/i2c/hmc6352_driver.go @@ -9,12 +9,13 @@ type HMC6352Driver struct { // NewHMC6352Driver creates a new driver with specified i2c interface // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewHMC6352Driver(c Connector, options ...func(Config)) *HMC6352Driver { h := &HMC6352Driver{ Driver: NewDriver(c, "HMC6352", hmc6352DefaultAddress), diff --git a/drivers/i2c/i2c_config_test.go b/drivers/i2c/i2c_config_test.go index 522e506bb..7c9a2fbb2 100644 --- a/drivers/i2c/i2c_config_test.go +++ b/drivers/i2c/i2c_config_test.go @@ -37,7 +37,7 @@ func TestWithAddress(t *testing.T) { } func TestGetBusOrDefaultWithBusOption(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { init int bus int want int @@ -59,7 +59,7 @@ func TestGetBusOrDefaultWithBusOption(t *testing.T) { } func TestGetAddressOrDefaultWithAddressOption(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { init int address int want int diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index a243dd013..6be0e6237 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -5,7 +5,6 @@ package i2c import ( "testing" - "unsafe" "github.com/stretchr/testify/assert" diff --git a/drivers/i2c/i2c_driver.go b/drivers/i2c/i2c_driver.go index 238e7ac45..88c26ab79 100644 --- a/drivers/i2c/i2c_driver.go +++ b/drivers/i2c/i2c_driver.go @@ -91,7 +91,7 @@ func (d *Driver) Start() error { var err error bus := d.GetBusOrDefault(d.connector.DefaultI2cBus()) - address := d.GetAddressOrDefault(int(d.defaultAddress)) + address := d.GetAddressOrDefault(d.defaultAddress) if d.connection, err = d.connector.GetI2cConnection(address, bus); err != nil { return err diff --git a/drivers/i2c/ina3221_driver.go b/drivers/i2c/ina3221_driver.go index 1624325fd..6ff5ab7a2 100644 --- a/drivers/i2c/ina3221_driver.go +++ b/drivers/i2c/ina3221_driver.go @@ -149,7 +149,7 @@ func (i *INA3221Driver) readWordFromRegister(reg uint8) (uint16, error) { return 0, err } - return uint16(((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8)), nil + return ((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8), nil } // initialize initializes the INA3221 device diff --git a/drivers/i2c/ina3221_driver_test.go b/drivers/i2c/ina3221_driver_test.go index 2e490830e..784306c5c 100644 --- a/drivers/i2c/ina3221_driver_test.go +++ b/drivers/i2c/ina3221_driver_test.go @@ -1,11 +1,9 @@ package i2c import ( - "testing" - "errors" - "strings" + "testing" "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" diff --git a/drivers/i2c/l3gd20h_driver_test.go b/drivers/i2c/l3gd20h_driver_test.go index 01a3cf728..b59337ed2 100644 --- a/drivers/i2c/l3gd20h_driver_test.go +++ b/drivers/i2c/l3gd20h_driver_test.go @@ -47,7 +47,7 @@ func TestL3GD20HOptions(t *testing.T) { } func TestL3GD20HWithL3GD20HFullScaleRange(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { scale L3GD20HScale want uint8 }{ @@ -81,7 +81,7 @@ func TestL3GD20HWithL3GD20HFullScaleRange(t *testing.T) { } func TestL3GD20HScale(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { scale L3GD20HScale want uint8 }{ @@ -146,7 +146,7 @@ func TestL3GD20HMeasurement(t *testing.T) { // // data table according to data sheet AN4506 example in table 7, supplemented with FS limit values sensitivity := float32(0.00875) // FS=245 dps - var tests = map[string]struct { + tests := map[string]struct { gyroData []byte wantX float32 wantY float32 diff --git a/drivers/i2c/lidarlite_driver.go b/drivers/i2c/lidarlite_driver.go index 698fb9dc6..79f7d7d40 100644 --- a/drivers/i2c/lidarlite_driver.go +++ b/drivers/i2c/lidarlite_driver.go @@ -14,12 +14,13 @@ type LIDARLiteDriver struct { // NewLIDARLiteDriver creates a new driver for the LIDARLite I2C LIDAR device. // // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewLIDARLiteDriver(c Connector, options ...func(Config)) *LIDARLiteDriver { l := &LIDARLiteDriver{ Driver: NewDriver(c, "LIDARLite", lidarliteDefaultAddress), diff --git a/drivers/i2c/mcp23017_driver.go b/drivers/i2c/mcp23017_driver.go index 0746f5766..4b8697859 100644 --- a/drivers/i2c/mcp23017_driver.go +++ b/drivers/i2c/mcp23017_driver.go @@ -192,7 +192,7 @@ func WithMCP23017Intpol(val uint8) func(Config) { } } -// WithMCP23017ForceWrite option modifies the MCP23017Driver forceRefresh option +// WithMCP23017ForceRefresh option modifies the MCP23017Driver forceRefresh option // Setting to true (1) will force refresh operation to register, although there is no change. // Normally this is not needed, so default is off (0). // When there is something flaky, there is a small chance to stabilize by setting this flag to true. @@ -209,7 +209,7 @@ func WithMCP23017ForceRefresh(val uint8) func(Config) { } // WithMCP23017AutoIODirOff option modifies the MCP23017Driver autoIODirOff option -// Set IO direction at each read or write operation ensures the correct direction, which is the the default setting. +// Set IO direction at each read or write operation ensures the correct direction, which is the default setting. // Most hardware is configured statically, so this can avoided by setting the direction using SetPinMode(), // e.g. in the start up sequence. If this way is taken, the automatic set of direction at each call can // be safely deactivated with this flag (set to true, 1). @@ -234,7 +234,7 @@ func (m *MCP23017Driver) SetPinMode(pin uint8, portStr string, val uint8) (err e selectedPort := m.getPort(portStr) // Set IODIR register bit for given pin to an output/input. - if err = m.write(selectedPort.IODIR, uint8(pin), bitState(val)); err != nil { + if err = m.write(selectedPort.IODIR, pin, bitState(val)); err != nil { return } return @@ -271,7 +271,7 @@ func (m *MCP23017Driver) WriteGPIO(pin uint8, portStr string, val uint8) (err er if !m.mcpBehav.autoIODirOff { // Set IODIR register bit for given pin to an output by clearing bit. // can't call SetPinMode() because mutex will cause deadlock - if err = m.write(selectedPort.IODIR, uint8(pin), clear); err != nil { + if err = m.write(selectedPort.IODIR, pin, clear); err != nil { return err } } @@ -292,7 +292,7 @@ func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (val uint8, err err if !m.mcpBehav.autoIODirOff { // Set IODIR register bit for given pin to an input by set bit. // can't call SetPinMode() because mutex will cause deadlock - if err = m.write(selectedPort.IODIR, uint8(pin), set); err != nil { + if err = m.write(selectedPort.IODIR, pin, set); err != nil { return 0, err } } @@ -300,7 +300,7 @@ func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (val uint8, err err if err != nil { return val, err } - val = 1 << uint8(pin) & val + val = 1 << pin & val if val > 1 { val = 1 } diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index 220df3272..8fff18697 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -31,7 +31,7 @@ func initTestMCP23017(b uint8) (driver *MCP23017Driver) { return d } -func initTestMCP23017WithStubbedAdaptor(b uint8) (*MCP23017Driver, *i2cTestAdaptor) { +func initTestMCP23017WithStubbedAdaptor(b uint8) (*MCP23017Driver, *i2cTestAdaptor) { //nolint:unparam // keep for tests // create the driver, ready to use for tests a := newI2cTestAdaptor() d := NewMCP23017Driver(a, WithMCP23017Bank(b)) diff --git a/drivers/i2c/mma7660_driver.go b/drivers/i2c/mma7660_driver.go index 007cc8b97..8e9f5acd5 100644 --- a/drivers/i2c/mma7660_driver.go +++ b/drivers/i2c/mma7660_driver.go @@ -32,12 +32,13 @@ type MMA7660Driver struct { // NewMMA7660Driver creates a new driver with specified i2c interface // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewMMA7660Driver(c Connector, options ...func(Config)) *MMA7660Driver { d := &MMA7660Driver{ Driver: NewDriver(c, "MMA7660", mma7660DefaultAddress), diff --git a/drivers/i2c/mpl115a2_driver.go b/drivers/i2c/mpl115a2_driver.go index 0791a55ae..cbe32206f 100644 --- a/drivers/i2c/mpl115a2_driver.go +++ b/drivers/i2c/mpl115a2_driver.go @@ -1,11 +1,11 @@ package i2c import ( - "gobot.io/x/gobot/v2" - "bytes" "encoding/binary" "time" + + "gobot.io/x/gobot/v2" ) const mpl115a2DefaultAddress = 0x60 diff --git a/drivers/i2c/mpu6050_driver.go b/drivers/i2c/mpu6050_driver.go index 38b294945..778e9a5c0 100644 --- a/drivers/i2c/mpu6050_driver.go +++ b/drivers/i2c/mpu6050_driver.go @@ -14,11 +14,13 @@ const ( mpu6050EarthStandardGravity = 9.80665 // [m/s²] standard gravity (pole: 9.834, equator: 9.764) ) -type MPU6050DlpfConfig uint8 -type MPU6050FrameSyncConfig uint8 -type MPU6050GyroFsConfig uint8 -type MPU6050AccelFsConfig uint8 -type MPU6050Pwr1ClockConfig uint8 +type ( + MPU6050DlpfConfig uint8 + MPU6050FrameSyncConfig uint8 + MPU6050GyroFsConfig uint8 + MPU6050AccelFsConfig uint8 + MPU6050Pwr1ClockConfig uint8 +) const ( mpu6050Reg_GeneralConfig = 0x1A // external frame synchronization and digital low pass filter diff --git a/drivers/i2c/pca9501_driver.go b/drivers/i2c/pca9501_driver.go index dd38474d4..05677886b 100644 --- a/drivers/i2c/pca9501_driver.go +++ b/drivers/i2c/pca9501_driver.go @@ -16,7 +16,6 @@ const pca9501DefaultAddress = 0x3F // this applies, if all 6 address pins left o // please refer to data sheet: https://www.nxp.com/docs/en/data-sheet/PCA9501.pdf // // PCA9501 is the replacement for PCF8574, so this driver should also work for PCF8574 except EEPROM calls -// type PCA9501Driver struct { connectionMem Connection *Driver @@ -24,12 +23,13 @@ type PCA9501Driver struct { // NewPCA9501Driver creates a new driver with specified i2c interface // Params: -// a Connector - the Adaptor to use with this Driver +// +// a Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver func NewPCA9501Driver(a Connector, options ...func(Config)) *PCA9501Driver { p := &PCA9501Driver{ Driver: NewDriver(a, "PCA9501", pca9501DefaultAddress, options...), @@ -76,9 +76,9 @@ func (p *PCA9501Driver) WriteGPIO(pin uint8, val uint8) error { return err } // set pin as output by clearing bit - iodirVal := clearBit(iodir, uint8(pin)) + iodirVal := clearBit(iodir, pin) // write CTRL register - err = p.connection.WriteByte(uint8(iodirVal)) + err = p.connection.WriteByte(iodirVal) if err != nil { return err } @@ -90,12 +90,12 @@ func (p *PCA9501Driver) WriteGPIO(pin uint8, val uint8) error { // set or reset the bit in value var nVal uint8 if val == 0 { - nVal = clearBit(cVal, uint8(pin)) + nVal = clearBit(cVal, pin) } else { - nVal = setBit(cVal, uint8(pin)) + nVal = setBit(cVal, pin) } // write new value to port - err = p.connection.WriteByte(uint8(nVal)) + err = p.connection.WriteByte(nVal) if err != nil { return err } @@ -113,9 +113,9 @@ func (p *PCA9501Driver) ReadGPIO(pin uint8) (uint8, error) { return 0, err } // set pin as input by setting bit - iodirVal := setBit(iodir, uint8(pin)) + iodirVal := setBit(iodir, pin) // write CTRL register - err = p.connection.WriteByte(uint8(iodirVal)) + err = p.connection.WriteByte(iodirVal) if err != nil { return 0, err } @@ -124,7 +124,7 @@ func (p *PCA9501Driver) ReadGPIO(pin uint8) (uint8, error) { if err != nil { return val, err } - val = 1 << uint8(pin) & val + val = 1 << pin & val if val > 1 { val = 1 } diff --git a/drivers/i2c/pca9501_driver_test.go b/drivers/i2c/pca9501_driver_test.go index 33ecb93d7..30e34315b 100644 --- a/drivers/i2c/pca9501_driver_test.go +++ b/drivers/i2c/pca9501_driver_test.go @@ -114,7 +114,7 @@ func TestPCA9501CommandsReadEEPROM(t *testing.T) { } func TestPCA9501WriteGPIO(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { setVal uint8 ioDirAllInput uint8 ioStateAllInput uint8 @@ -223,7 +223,7 @@ func TestPCA9501WriteGPIOErrorAtWriteValue(t *testing.T) { } func TestPCA9501ReadGPIO(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { ctrlState uint8 want uint8 }{ diff --git a/drivers/i2c/pca953x_driver.go b/drivers/i2c/pca953x_driver.go index 94151fba0..fd193441a 100644 --- a/drivers/i2c/pca953x_driver.go +++ b/drivers/i2c/pca953x_driver.go @@ -36,10 +36,12 @@ const ( PCA953xModePwm1 PCA953xGPIOMode = 0x03 ) -var errToSmallPeriod = fmt.Errorf("Given Period to small, must be at least 1/152s (~6.58ms) or 152Hz") -var errToBigPeriod = fmt.Errorf("Given Period to high, must be max. 256/152s (~1.68s) or 152/256Hz (~0.6Hz)") -var errToSmallDutyCycle = fmt.Errorf("Given Duty Cycle to small, must be at least 0%%") -var errToBigDutyCycle = fmt.Errorf("Given Duty Cycle to high, must be max. 100%%") +var ( + errToSmallPeriod = fmt.Errorf("Given Period to small, must be at least 1/152s (~6.58ms) or 152Hz") + errToBigPeriod = fmt.Errorf("Given Period to high, must be max. 256/152s (~1.68s) or 152/256Hz (~0.6Hz)") + errToSmallDutyCycle = fmt.Errorf("Given Duty Cycle to small, must be at least 0%%") + errToBigDutyCycle = fmt.Errorf("Given Duty Cycle to high, must be max. 100%%") +) // PCA953xDriver is a Gobot Driver for LED Dimmer PCA9530 (2-bit), PCA9533 (4-bit), PCA9531 (8-bit), PCA9532 (16-bit) // Although this is designed for LED's it can be used as a GPIO (read, write, pwm). @@ -118,7 +120,7 @@ func (d *PCA953xDriver) ReadGPIO(idx uint8) (uint8, error) { if err != nil { return val, err } - val = 1 << uint8(idx) & val + val = 1 << idx & val if val > 1 { val = 1 } @@ -133,7 +135,7 @@ func (d *PCA953xDriver) WritePeriod(idx uint8, valSec float32) error { // period is valid in range ~6.58ms..1.68s val, err := pca953xCalcPsc(valSec) if err != nil && pca953xDebug { - fmt.Println(err, "value shrinked!") + fmt.Println(err, "value limited!") } var regPsc pca953xRegister = pca953xRegPsc0 if idx > 0 { @@ -166,7 +168,7 @@ func (d *PCA953xDriver) WriteFrequency(idx uint8, valHz float32) error { // frequency is valid in range ~0.6..152Hz val, err := pca953xCalcPsc(1 / valHz) if err != nil && pca953xDebug { - fmt.Println(err, "value shrinked!") + fmt.Println(err, "value limited!") } regPsc := pca953xRegPsc0 if idx > 0 { @@ -199,7 +201,7 @@ func (d *PCA953xDriver) WriteDutyCyclePercent(idx uint8, valPercent float32) err val, err := pca953xCalcPwm(valPercent) if err != nil && pca953xDebug { - fmt.Println(err, "value shrinked!") + fmt.Println(err, "value limited!") } regPwm := pca953xRegPwm0 if idx > 0 { diff --git a/drivers/i2c/pca953x_driver_test.go b/drivers/i2c/pca953x_driver_test.go index 20e944b78..ab35b8e2f 100644 --- a/drivers/i2c/pca953x_driver_test.go +++ b/drivers/i2c/pca953x_driver_test.go @@ -40,7 +40,7 @@ func TestPCA953xWriteGPIO(t *testing.T) { // * read current state of LED select register (write reg, read val) // * modify 2 bits according to given index of GPIO // * write the new state to the LED select register (write reg, write val) - var tests = map[string]struct { + tests := map[string]struct { idx uint8 ls0State uint8 ls1State uint8 @@ -109,7 +109,7 @@ func TestPCA953xReadGPIO(t *testing.T) { // sequence to read: // * read current state of INPUT register (write reg 0x00, read val) // * convert bit position to output value - var tests = map[string]struct { + tests := map[string]struct { idx uint8 want uint8 wantErr error @@ -171,7 +171,7 @@ func TestPCA953xWritePeriod(t *testing.T) { // * calculate PSC value (0..255) from given value in seconds, valid values are 0.00658 ... 1.68 [s] // * choose PSC0 (0x01) or PSC1 (0x03) frequency prescaler register by the given index // * write the value to the register (write reg, write val) - var tests = map[string]struct { + tests := map[string]struct { idx uint8 val float32 wantWritten []uint8 @@ -186,7 +186,7 @@ func TestPCA953xWritePeriod(t *testing.T) { val: 0.5, wantWritten: []byte{0x03, 75}, }, - "write_shrinked_noerror": { + "write_limited_noerror": { idx: 0, val: 2, wantWritten: []byte{0x01, 255}, @@ -211,7 +211,7 @@ func TestPCA953xReadPeriod(t *testing.T) { // * choose PSC0 (0x01) or PSC1 (0x03) frequency prescaler register by the given index // * read the value from the register (write reg, write val) // * calculate value in seconds from PSC value - var tests = map[string]struct { + tests := map[string]struct { idx uint8 val uint8 want float32 @@ -262,7 +262,7 @@ func TestPCA953xWriteFrequency(t *testing.T) { // * calculate PSC value (0..255) from given value in Hz, valid values are 0.6 ... 152 [Hz] // * choose PSC0 (0x01) or PSC1 (0x03) frequency prescaler register by the given index // * write the value to the register (write reg, write val) - var tests = map[string]struct { + tests := map[string]struct { idx uint8 val float32 wantWritten []uint8 @@ -277,7 +277,7 @@ func TestPCA953xWriteFrequency(t *testing.T) { val: 2, wantWritten: []byte{0x03, 75}, }, - "write_shrinked_noerror": { + "write_limited_noerror": { idx: 0, val: 153, wantWritten: []byte{0x01, 0}, @@ -302,7 +302,7 @@ func TestPCA953xReadFrequency(t *testing.T) { // * choose PSC0 (0x01) or PSC1 (0x03) frequency prescaler register by the given index // * read the value from the register (write reg, write val) // * calculate value in Hz from PSC value - var tests = map[string]struct { + tests := map[string]struct { idx uint8 val uint8 want float32 @@ -353,7 +353,7 @@ func TestPCA953xWriteDutyCyclePercent(t *testing.T) { // * calculate PWM value (0..255) from given value in percent, valid values are 0 ... 100 [%] // * choose PWM0 (0x02) or PWM1 (0x04) pwm register by the given index // * write the value to the register (write reg, write val) - var tests = map[string]struct { + tests := map[string]struct { idx uint8 val float32 wantWritten []uint8 @@ -368,7 +368,7 @@ func TestPCA953xWriteDutyCyclePercent(t *testing.T) { val: 50, wantWritten: []byte{0x04, 128}, }, - "write_shrinked_noerror": { + "write_limited_noerror": { idx: 1, val: 101, wantWritten: []byte{0x04, 255}, @@ -393,7 +393,7 @@ func TestPCA953xReadDutyCyclePercent(t *testing.T) { // * choose PWM0 (0x02) or PWM1 (0x04) pwm register by the given index // * read the value from the register (write reg, write val) // * calculate value percent from PWM value - var tests = map[string]struct { + tests := map[string]struct { idx uint8 val uint8 want float32 @@ -496,7 +496,7 @@ func TestPCA953x_writeRegister(t *testing.T) { assert.Equal(t, 1, numCallsWrite) assert.Equal(t, wantByteCount, len(a.written)) assert.Equal(t, uint8(wantRegAddress), a.written[0]) - assert.Equal(t, uint8(wantRegVal), a.written[1]) + assert.Equal(t, wantRegVal, a.written[1]) } func TestPCA953x_pca953xCalcPsc(t *testing.T) { diff --git a/drivers/i2c/pca9685_driver.go b/drivers/i2c/pca9685_driver.go index 34ea629cf..74df04fed 100644 --- a/drivers/i2c/pca9685_driver.go +++ b/drivers/i2c/pca9685_driver.go @@ -162,7 +162,7 @@ func (p *PCA9685Driver) SetPWMFreq(freq float32) error { // Put oscillator in sleep mode, clear bit 7 here to avoid overwriting // previous setting newmode := (oldmode & 0x7F) | 0x10 - if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), byte(newmode)}); err != nil { + if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), newmode}); err != nil { return err } // Write prescaler value @@ -170,14 +170,14 @@ func (p *PCA9685Driver) SetPWMFreq(freq float32) error { return err } // Put back to old settings - if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), byte(oldmode)}); err != nil { + if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), oldmode}); err != nil { return err } time.Sleep(5 * time.Millisecond) // Enable response to All Call address, enable auto-increment, clear restart - if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), byte(oldmode | 0x80)}); err != nil { + if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), oldmode | 0x80}); err != nil { return err } diff --git a/drivers/i2c/pca9685_driver_test.go b/drivers/i2c/pca9685_driver_test.go index ca448d447..0c0b97852 100644 --- a/drivers/i2c/pca9685_driver_test.go +++ b/drivers/i2c/pca9685_driver_test.go @@ -15,8 +15,10 @@ import ( var _ gobot.Driver = (*PCA9685Driver)(nil) // and also the PwmWriter and ServoWriter interfaces -var _ gpio.PwmWriter = (*PCA9685Driver)(nil) -var _ gpio.ServoWriter = (*PCA9685Driver)(nil) +var ( + _ gpio.PwmWriter = (*PCA9685Driver)(nil) + _ gpio.ServoWriter = (*PCA9685Driver)(nil) +) func initTestPCA9685DriverWithStubbedAdaptor() (*PCA9685Driver, *i2cTestAdaptor) { a := newI2cTestAdaptor() diff --git a/drivers/i2c/pcf8583_driver.go b/drivers/i2c/pcf8583_driver.go index 89e6be711..2db6821b2 100644 --- a/drivers/i2c/pcf8583_driver.go +++ b/drivers/i2c/pcf8583_driver.go @@ -49,7 +49,7 @@ const ( // 0 1 0 1 0 0 0 A0|rd // Lowest bit (rd) is mapped to switch between write(0)/read(1), it is not part of the "real" address. // -// PCF8583 is mainly compatible to PCF8593, so this driver should also work for PCF8593 except RAM calls +// # PCF8583 is mainly compatible to PCF8593, so this driver should also work for PCF8593 except RAM calls // // This driver was tested with Tinkerboard. type PCF8583Driver struct { @@ -61,13 +61,14 @@ type PCF8583Driver struct { // NewPCF8583Driver creates a new driver with specified i2c interface // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver -// i2c.WithPCF8583Mode(PCF8583Control): mode of this driver // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver +// i2c.WithPCF8583Mode(PCF8583Control): mode of this driver func NewPCF8583Driver(c Connector, options ...func(Config)) *PCF8583Driver { d := &PCF8583Driver{ Driver: NewDriver(c, "PCF8583", pcf8583DefaultAddress), @@ -149,7 +150,8 @@ func (d *PCF8583Driver) WriteTime(val time.Time) error { } year, month, day := val.Date() err = d.connection.WriteBlockData(uint8(pcf8583Reg_CTRL), - []byte{ctrlRegVal | uint8(pcf8583CtrlStopCounting), + []byte{ + ctrlRegVal | uint8(pcf8583CtrlStopCounting), pcf8583encodeBcd(uint8(val.Nanosecond() / 1000000 / 10)), // sub seconds in 1/10th seconds pcf8583encodeBcd(uint8(val.Second())), pcf8583encodeBcd(uint8(val.Minute())), @@ -216,7 +218,8 @@ func (d *PCF8583Driver) WriteCounter(val int32) error { return fmt.Errorf("%s: can't write counter because the device is in wrong mode 0x%02x", d.name, ctrlRegVal) } err = d.connection.WriteBlockData(uint8(pcf8583Reg_CTRL), - []byte{ctrlRegVal | uint8(pcf8583CtrlStopCounting), // stop + []byte{ + ctrlRegVal | uint8(pcf8583CtrlStopCounting), // stop pcf8583encodeBcd(uint8(val % 100)), // 2 lowest digits pcf8583encodeBcd(uint8((val / 100) % 100)), // 2 middle digits pcf8583encodeBcd(uint8((val / 10000) % 100)), // 2 highest digits @@ -329,13 +332,13 @@ func pcf8583encodeBcd(val byte) byte { log.Printf("PCF8583 BCD value (%d) exceeds limit of 99, now limited.", val) } } - hi, lo := byte(val/10), byte(val%10) + hi, lo := val/10, val%10 return hi<<4 | lo } func pcf8583decodeBcd(bcd byte) byte { // 0x12 => decimal 12 - hi, lo := byte(bcd>>4), byte(bcd&0x0f) + hi, lo := bcd>>4, bcd&0x0f if hi > 9 { hi = 9 if pcf8583Debug { diff --git a/drivers/i2c/pcf8583_driver_test.go b/drivers/i2c/pcf8583_driver_test.go index a772b1192..a2a4a93ea 100644 --- a/drivers/i2c/pcf8583_driver_test.go +++ b/drivers/i2c/pcf8583_driver_test.go @@ -68,7 +68,7 @@ func TestPCF8583CommandsReadTime(t *testing.T) { d, a := initTestPCF8583WithStubbedAdaptor() d.yearOffset = 2019 milliSec := 550 * time.Millisecond // 0.55 sec = 550 ms - want := time.Date(2021, time.December, 24, 18, 00, 00, int(milliSec), time.UTC) + want := time.Date(2021, time.December, 24, 18, 0, 0, int(milliSec), time.UTC) reg0Val := uint8(0x00) // clock mode 32.768 kHz reg1Val := uint8(0x55) // BCD: 1/10 and 1/100 sec (55) reg2Val := uint8(0x00) // BCD: 10 and 1 sec (00) @@ -152,7 +152,7 @@ func TestPCF8583CommandsReadCounter(t *testing.T) { func TestPCF8583CommandsWriteRAM(t *testing.T) { // arrange d, _ := initTestPCF8583WithStubbedAdaptor() - var addressValue = map[string]interface{}{ + addressValue := map[string]interface{}{ "address": uint8(0x12), "val": uint8(0x45), } @@ -165,7 +165,7 @@ func TestPCF8583CommandsWriteRAM(t *testing.T) { func TestPCF8583CommandsReadRAM(t *testing.T) { // arrange d, _ := initTestPCF8583WithStubbedAdaptor() - var address = map[string]interface{}{ + address := map[string]interface{}{ "address": uint8(0x34), } // act @@ -609,5 +609,5 @@ func TestPCF8583_initializeWithModeSwitch(t *testing.T) { assert.Equal(t, 3, len(a.written)) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[1]) - assert.Equal(t, uint8(wantReg0Val), a.written[2]) + assert.Equal(t, wantReg0Val, a.written[2]) } diff --git a/drivers/i2c/pcf8591_driver.go b/drivers/i2c/pcf8591_driver.go index b62942734..e686429ad 100644 --- a/drivers/i2c/pcf8591_driver.go +++ b/drivers/i2c/pcf8591_driver.go @@ -15,8 +15,10 @@ const ( pcf8591Debug = false ) -type pcf8591Mode uint8 -type PCF8591Channel uint8 +type ( + pcf8591Mode uint8 + PCF8591Channel uint8 +) const ( pcf8591_CHAN0 PCF8591Channel = 0x00 @@ -96,7 +98,6 @@ var pcf8591ModeMap = map[string]pcf8591ModeChan{ // https://www.adafruit.com/product/4648 // // This driver was tested with Tinkerboard and the YL-40 driver. -// type PCF8591Driver struct { *Driver lastCtrlByte byte @@ -109,13 +110,14 @@ type PCF8591Driver struct { // NewPCF8591Driver creates a new driver with specified i2c interface // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver -// i2c.WithPCF8591With400kbitStabilization(uint8, uint8): stabilize read in 400 kbit mode // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver +// i2c.WithPCF8591With400kbitStabilization(uint8, uint8): stabilize read in 400 kbit mode func NewPCF8591Driver(c Connector, options ...func(Config)) *PCF8591Driver { p := &PCF8591Driver{ Driver: NewDriver(c, "PCF8591", pcf8591DefaultAddress), @@ -182,11 +184,11 @@ func WithPCF8591ForceRefresh(val uint8) func(Config) { // An i2c bus extender (LTC4311) don't fix it (it seems rather the opposite). // // This leads to following behavior: -// * the control byte is not written correctly -// * the transition process takes an additional cycle, very often -// * some circuits takes one cycle longer transition time in addition -// * reading more than one byte by Read([]byte), e.g. to calculate an average, is not sufficient, -// because some missing integration steps in each conversion (each byte value is a little bit lower than expected) +// - the control byte is not written correctly +// - the transition process takes an additional cycle, very often +// - some circuits takes one cycle longer transition time in addition +// - reading more than one byte by Read([]byte), e.g. to calculate an average, is not sufficient, +// because some missing integration steps in each conversion (each byte value is a little bit lower than expected) // // So, for default, we drop the first three bytes to get the right value. func (p *PCF8591Driver) AnalogRead(description string) (value int, err error) { diff --git a/drivers/i2c/sht2x_driver.go b/drivers/i2c/sht2x_driver.go index 3c1e36e1e..abbf376b6 100644 --- a/drivers/i2c/sht2x_driver.go +++ b/drivers/i2c/sht2x_driver.go @@ -165,10 +165,10 @@ func (d *SHT2xDriver) readSensor(cmd byte) (read uint16, err error) { return } - //Hang out while measurement is taken. 85ms max, page 9 of datasheet. + // Hang out while measurement is taken. 85ms max, page 9 of datasheet. time.Sleep(85 * time.Millisecond) - //Comes back in three bytes, data(MSB) / data(LSB) / Checksum + // Comes back in three bytes, data(MSB) / data(LSB) / Checksum buf := make([]byte, 3) counter := 0 for { @@ -188,7 +188,7 @@ func (d *SHT2xDriver) readSensor(cmd byte) (read uint16, err error) { time.Sleep(1 * time.Millisecond) } - //Store the result + // Store the result crc := crc8.Checksum(buf[0:2], d.crcTable) if buf[2] != crc { err = errors.New("Invalid crc") @@ -221,12 +221,12 @@ func (d *SHT2xDriver) sendAccuracy() error { return err } - userRegister &= 0x7e //Turn off the resolution bits + userRegister &= 0x7e // Turn off the resolution bits acc := d.accuracy - acc &= 0x81 //Turn off all other bits but resolution bits - userRegister |= acc //Mask in the requested resolution bits + acc &= 0x81 // Turn off all other bits but resolution bits + userRegister |= acc // Mask in the requested resolution bits - //Request a write to user register + // Request a write to user register if _, err := d.connection.Write([]byte{SHT2xWriteUserReg, userRegister}); err != nil { return err } diff --git a/drivers/i2c/ssd1306_driver.go b/drivers/i2c/ssd1306_driver.go index 157d21536..9a8e92944 100644 --- a/drivers/i2c/ssd1306_driver.go +++ b/drivers/i2c/ssd1306_driver.go @@ -26,13 +26,13 @@ const ( ssd1306SetComOutput8 = 0xC8 ssd1306SetContrast = 0x81 // scrolling commands - //ssd1306ContinuousHScrollRight = 0x26 - //ssd1306ContinuousHScrollLeft = 0x27 - //ssd1306ContinuousVHScrollRight = 0x29 - //ssd1306ContinuousVHScrollLeft = 0x2A - //ssd1306StopScroll = 0x2E - //ssd1306StartScroll = 0x2F - // adressing settings commands + // ssd1306ContinuousHScrollRight = 0x26 + // ssd1306ContinuousHScrollLeft = 0x27 + // ssd1306ContinuousVHScrollRight = 0x29 + // ssd1306ContinuousVHScrollLeft = 0x2A + // ssd1306StopScroll = 0x2E + // ssd1306StartScroll = 0x2F + // addressing settings commands ssd1306SetMemoryAddressingMode = 0x20 ssd1306ColumnAddr = 0x21 ssd1306PageAddr = 0x22 @@ -235,14 +235,14 @@ func NewSSD1306Driver(c Connector, options ...func(Config)) *SSD1306Driver { return map[string]interface{}{} }) s.AddCommand("SetContrast", func(params map[string]interface{}) interface{} { - contrast := byte(params["contrast"].(byte)) + contrast := params["contrast"].(byte) err := s.SetContrast(contrast) return map[string]interface{}{"err": err} }) s.AddCommand("Set", func(params map[string]interface{}) interface{} { - x := int(params["x"].(int)) - y := int(params["y"].(int)) - c := int(params["c"].(int)) + x := params["x"].(int) + y := params["y"].(int) + c := params["c"].(int) s.Set(x, y, c) return nil }) diff --git a/drivers/i2c/ssd1306_driver_test.go b/drivers/i2c/ssd1306_driver_test.go index b140a9e5a..ef6ae5590 100644 --- a/drivers/i2c/ssd1306_driver_test.go +++ b/drivers/i2c/ssd1306_driver_test.go @@ -15,9 +15,13 @@ import ( // and tests all implementations, so no further tests needed here for gobot.Driver interface var _ gobot.Driver = (*SSD1306Driver)(nil) -func initTestSSD1306DriverWithStubbedAdaptor(width, height int, externalVCC bool) (*SSD1306Driver, *i2cTestAdaptor) { +func initTestSSD1306DriverWithStubbedAdaptor( + width, height int, + externalVCC bool, //nolint:unparam // keep for tests +) (*SSD1306Driver, *i2cTestAdaptor) { a := newI2cTestAdaptor() - d := NewSSD1306Driver(a, WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) + d := NewSSD1306Driver(a, WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), + WithSSD1306ExternalVCC(externalVCC)) if err := d.Start(); err != nil { panic(err) } diff --git a/drivers/i2c/th02_driver.go b/drivers/i2c/th02_driver.go index 4edee7900..bf29309e7 100644 --- a/drivers/i2c/th02_driver.go +++ b/drivers/i2c/th02_driver.go @@ -40,7 +40,7 @@ const ( th02Reg_Config = 0x03 th02Reg_ID = 0x11 - //th02Status_ReadyBit = 0x01 // D0 is /RDY + // th02Status_ReadyBit = 0x01 // D0 is /RDY th02Config_StartBit = 0x01 // D0 is START th02Config_HeatBit = 0x02 // D1 is HEAT @@ -50,8 +50,8 @@ const ( // Accuracy constants for the TH02 devices (deprecated, use WithFastMode() instead) const ( - TH02HighAccuracy = 0 //High Accuracy (T: 14 bit, H: 12 bit), normal (35 ms) - TH02LowAccuracy = 1 //Lower Accuracy (T: 13 bit, H: 11 bit), fast (18 ms) + TH02HighAccuracy = 0 // High Accuracy (T: 14 bit, H: 12 bit), normal (35 ms) + TH02LowAccuracy = 1 // Lower Accuracy (T: 13 bit, H: 11 bit), fast (18 ms) ) // TH02Driver is a Driver for a TH02 humidity and temperature sensor @@ -123,7 +123,7 @@ func (s *TH02Driver) SerialNumber() (uint8, error) { defer s.mutex.Unlock() ret, err := s.connection.ReadByteData(th02Reg_ID) - return uint8(ret) >> 4, err + return ret >> 4, err } // FastMode returns true if the fast mode is enabled in the device @@ -185,7 +185,6 @@ func (s *TH02Driver) Sample() (temperature float32, relhumidity float32, _ error } return temperature, relhumidity, nil - } func (s *TH02Driver) createConfig(measurement bool, readTemp bool) byte { diff --git a/drivers/i2c/th02_driver_test.go b/drivers/i2c/th02_driver_test.go index 51a46c66e..44501e82e 100644 --- a/drivers/i2c/th02_driver_test.go +++ b/drivers/i2c/th02_driver_test.go @@ -59,7 +59,7 @@ func TestTH02SetAccuracy(t *testing.T) { } func TestTH02WithFastMode(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { value int want bool }{ @@ -84,7 +84,7 @@ func TestTH02FastMode(t *testing.T) { // * write config register address (0x03) // * read register content // * if sixth bit (D5) is set, the fast mode is configured on, otherwise off - var tests = map[string]struct { + tests := map[string]struct { read uint8 want bool }{ @@ -116,7 +116,7 @@ func TestTH02SetHeater(t *testing.T) { // * write config register address (0x03) // * prepare config value by set/reset the heater bit (0x02, D1) // * write the config value - var tests = map[string]struct { + tests := map[string]struct { heater bool want uint8 }{ @@ -144,7 +144,7 @@ func TestTH02Heater(t *testing.T) { // * write config register address (0x03) // * read register content // * if second bit (D1) is set, the heater is configured on, otherwise off - var tests = map[string]struct { + tests := map[string]struct { read uint8 want bool }{ @@ -207,7 +207,7 @@ func TestTH02Sample(t *testing.T) { // test table according to data sheet page 15, 17 // operating range of the temperature sensor is -40..85 °C (F-grade 0..70 °C) - var tests = map[string]struct { + tests := map[string]struct { hData uint16 tData uint16 wantRH float32 @@ -298,8 +298,8 @@ func TestTH02Sample(t *testing.T) { temp, rh, err := d.Sample() // assert assert.Nil(t, err) - assert.Equal(t, float32(tc.wantRH), rh) - assert.Equal(t, float32(tc.wantT), temp) + assert.Equal(t, tc.wantRH, rh) + assert.Equal(t, tc.wantT, temp) }) } } @@ -309,7 +309,7 @@ func TestTH02_readData(t *testing.T) { var callCounter int - var tests = map[string]struct { + tests := map[string]struct { rd func([]byte) (int, error) wr func([]byte) (int, error) rtn uint16 @@ -455,7 +455,7 @@ func TestTH02_waitForReadyFailOnReadError(t *testing.T) { func TestTH02_createConfig(t *testing.T) { d := &TH02Driver{} - var tests = map[string]struct { + tests := map[string]struct { meas bool fast bool readTemp bool diff --git a/drivers/i2c/tsl2561_driver.go b/drivers/i2c/tsl2561_driver.go index 7bc4fa8b6..cc3ff7160 100644 --- a/drivers/i2c/tsl2561_driver.go +++ b/drivers/i2c/tsl2561_driver.go @@ -121,18 +121,19 @@ type TSL2561Driver struct { // NewTSL2561Driver creates a new driver for the TSL2561 device. // // Params: -// c Connector - the Adaptor to use with this Driver +// +// c Connector - the Adaptor to use with this Driver // // Optional params: -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver -// i2c.WithTSL2561Gain1X: sets the gain to 1X -// i2c.WithTSL2561Gain16X: sets the gain to 16X -// i2c.WithTSL2561AutoGain: turns on auto gain -// i2c.WithTSL2561IntegrationTime13MS: sets integration time to 13ms -// i2c.WithTSL2561IntegrationTime101MS: sets integration time to 101ms -// i2c.WithTSL2561IntegrationTime402MS: sets integration time to 402ms // +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver +// i2c.WithTSL2561Gain1X: sets the gain to 1X +// i2c.WithTSL2561Gain16X: sets the gain to 16X +// i2c.WithTSL2561AutoGain: turns on auto gain +// i2c.WithTSL2561IntegrationTime13MS: sets integration time to 13ms +// i2c.WithTSL2561IntegrationTime101MS: sets integration time to 101ms +// i2c.WithTSL2561IntegrationTime402MS: sets integration time to 402ms func NewTSL2561Driver(c Connector, options ...func(Config)) *TSL2561Driver { d := &TSL2561Driver{ Driver: NewDriver(c, "TSL2561", TSL2561AddressFloat), @@ -282,7 +283,7 @@ func (d *TSL2561Driver) GetLuminocity() (broadband uint16, ir uint16, err error) } else { // If we've already adjusted the gain once, just return the new results. // This avoids endless loops where a value is at one extreme pre-gain, - // and the the other extreme post-gain + // and the other extreme post-gain valid = true } diff --git a/drivers/i2c/tsl2561_driver_test.go b/drivers/i2c/tsl2561_driver_test.go index 2c363b997..7b60391a7 100644 --- a/drivers/i2c/tsl2561_driver_test.go +++ b/drivers/i2c/tsl2561_driver_test.go @@ -133,7 +133,7 @@ func TestTSL2561DriverEvenMoreOptions(t *testing.T) { assert.NotNil(t, d) assert.False(t, d.autoGain) - assert.Equal(t, TSL2561Gain(TSL2561Gain1X), d.gain) + assert.Equal(t, TSL2561Gain1X, d.gain) assert.Equal(t, TSL2561IntegrationTime13MS, d.integrationTime) } diff --git a/drivers/i2c/wiichuck_driver.go b/drivers/i2c/wiichuck_driver.go index 45b6c7eda..fc2d305bd 100644 --- a/drivers/i2c/wiichuck_driver.go +++ b/drivers/i2c/wiichuck_driver.go @@ -108,7 +108,7 @@ func (w *WiichuckDriver) setJoystickDefaultValue(joystickAxis string, defaultVal // calculateJoystickValue returns distance between axis and origin func (w *WiichuckDriver) calculateJoystickValue(axis float64, origin float64) float64 { - return float64(axis - origin) + return axis - origin } // isEncrypted returns true if value is encrypted diff --git a/drivers/i2c/wiichuck_driver_test.go b/drivers/i2c/wiichuck_driver_test.go index f6da53d98..161dcd9d9 100644 --- a/drivers/i2c/wiichuck_driver_test.go +++ b/drivers/i2c/wiichuck_driver_test.go @@ -63,7 +63,6 @@ func TestWiichuckDriverStart(t *testing.T) { case <-time.After(100 * time.Millisecond): t.Errorf("origin not read correctly") } - } func TestWiichuckDriverHalt(t *testing.T) { diff --git a/drivers/i2c/yl40_driver.go b/drivers/i2c/yl40_driver.go index bc3d2a8b2..4509ddfeb 100644 --- a/drivers/i2c/yl40_driver.go +++ b/drivers/i2c/yl40_driver.go @@ -90,7 +90,7 @@ func NewYL40Driver(a Connector, options ...func(Config)) *YL40Driver { options = append(options, WithAddress(yl40DefaultAddress)) pcf := NewPCF8591Driver(a, options...) - ntc := aio.TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3950} //Ohm, R25=10k, B=3950 + ntc := aio.TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3950} // Ohm, R25=10k, B=3950 defTempScaler := aio.TemperatureSensorNtcScaler(255, 1000, true, ntc) defConf := yl40Config{ diff --git a/drivers/i2c/yl40_driver_test.go b/drivers/i2c/yl40_driver_test.go index 0ad398a0f..a3e604403 100644 --- a/drivers/i2c/yl40_driver_test.go +++ b/drivers/i2c/yl40_driver_test.go @@ -19,7 +19,7 @@ func initTestYL40DriverWithStubbedAdaptor() (*YL40Driver, *i2cTestAdaptor) { func TestYL40Driver(t *testing.T) { // arrange, act yl := NewYL40Driver(newI2cTestAdaptor()) - //assert + // assert assert.NotNil(t, yl.PCF8591Driver) assert.Equal(t, time.Duration(0), yl.conf.sensors[YL40Bri].interval) assert.NotNil(t, yl.conf.sensors[YL40Bri].scaler) @@ -59,7 +59,7 @@ func TestYL40DriverWithYL40InputScaler(t *testing.T) { f2 := func(input int) (value float64) { return 0.2 } f3 := func(input int) (value float64) { return 0.3 } f4 := func(input int) (value float64) { return 0.4 } - //act + // act WithYL40InputScaler(YL40Bri, f1)(yl) WithYL40InputScaler(YL40Temp, f2)(yl) WithYL40InputScaler(YL40AIN2, f3)(yl) @@ -75,7 +75,7 @@ func TestYL40DriverWithYL40WithYL40OutputScaler(t *testing.T) { // arrange yl := NewYL40Driver(newI2cTestAdaptor()) fo := func(input float64) (value int) { return 123 } - //act + // act WithYL40OutputScaler(fo)(yl) // assert assert.True(t, fEqual(yl.conf.aOutScaler, fo)) diff --git a/drivers/spi/apa102.go b/drivers/spi/apa102.go index a56baf48d..5e12ddfb1 100644 --- a/drivers/spi/apa102.go +++ b/drivers/spi/apa102.go @@ -15,17 +15,18 @@ type APA102Driver struct { // NewAPA102Driver creates a new Gobot Driver for APA102 RGB LEDs. // // Params: -// a *Adaptor - the Adaptor to use with this Driver. -// count int - how many LEDs are in the array controlled by this driver. -// bright - the default brightness to apply for all LEDs (must be between 0 and 31). +// +// a *Adaptor - the Adaptor to use with this Driver. +// count int - how many LEDs are in the array controlled by this driver. +// bright - the default brightness to apply for all LEDs (must be between 0 and 31). // // Optional params: -// spi.WithBusNumber(int): bus to use with this driver. -// spi.WithChipNumber(int): chip to use with this driver. -// spi.WithMode(int): mode to use with this driver. -// spi.WithBitCount(int): number of bits to use with this driver. -// spi.WithSpeed(int64): speed in Hz to use with this driver. // +// spi.WithBusNumber(int): bus to use with this driver. +// spi.WithChipNumber(int): chip to use with this driver. +// spi.WithMode(int): mode to use with this driver. +// spi.WithBitCount(int): number of bits to use with this driver. +// spi.WithSpeed(int64): speed in Hz to use with this driver. func NewAPA102Driver(a Connector, count int, bright uint8, options ...func(Config)) *APA102Driver { d := &APA102Driver{ Driver: NewDriver(a, "APA102"), @@ -72,7 +73,7 @@ func (d *APA102Driver) Draw() error { if c.A != 0 { tx[j] = 0xe0 + byte(math.Min(float64(c.A), 31)) } else { - tx[j] = 0xe0 + byte(d.brightness) + tx[j] = 0xe0 + d.brightness } tx[j+1] = c.B tx[j+2] = c.G diff --git a/drivers/spi/helpers_test.go b/drivers/spi/helpers_test.go index c66c310c0..66d1d2301 100644 --- a/drivers/spi/helpers_test.go +++ b/drivers/spi/helpers_test.go @@ -8,12 +8,14 @@ import ( ) // make sure that this SpiBusAdaptor fulfills all the required interfaces -var _ Connector = (*spiTestAdaptor)(nil) -var _ gobot.Connection = (*spiTestAdaptor)(nil) +var ( + _ Connector = (*spiTestAdaptor)(nil) + _ gobot.Connection = (*spiTestAdaptor)(nil) +) type spiTestAdaptor struct { sys *system.Accesser - //busNum int + // busNum int spiConnectErr bool spi *system.MockSpiAccess connection Connection @@ -34,7 +36,7 @@ func (a *spiTestAdaptor) GetSpiConnection(busNum, chipNum, mode, bits int, maxSp if a.spiConnectErr { return nil, fmt.Errorf("Invalid SPI connection in helper") } - //a.busNum = busNum + // a.busNum = busNum sysdev, err := a.sys.NewSpiDevice(busNum, chipNum, mode, bits, maxSpeed) a.connection = NewConnection(sysdev) return a.connection, err diff --git a/drivers/spi/mcp3002.go b/drivers/spi/mcp3002.go index 4d1d2a9f9..5358f67e6 100644 --- a/drivers/spi/mcp3002.go +++ b/drivers/spi/mcp3002.go @@ -16,15 +16,16 @@ type MCP3002Driver struct { // NewMCP3002Driver creates a new Gobot Driver for MCP3002 A/D converter // // Params: -// a *Adaptor - the Adaptor to use with this Driver +// +// a *Adaptor - the Adaptor to use with this Driver // // Optional params: -// spi.WithBusNumber(int): bus to use with this driver -// spi.WithChipNumber(int): chip to use with this driver -// spi.WithMode(int): mode to use with this driver -// spi.WithBitCount(int): number of bits to use with this driver -// spi.WithSpeed(int64): speed in Hz to use with this driver // +// spi.WithBusNumber(int): bus to use with this driver +// spi.WithChipNumber(int): chip to use with this driver +// spi.WithMode(int): mode to use with this driver +// spi.WithBitCount(int): number of bits to use with this driver +// spi.WithSpeed(int64): speed in Hz to use with this driver func NewMCP3002Driver(a Connector, options ...func(Config)) *MCP3002Driver { d := &MCP3002Driver{ Driver: NewDriver(a, "MCP3002"), diff --git a/drivers/spi/mcp3002_test.go b/drivers/spi/mcp3002_test.go index c1a53a751..abbe0129f 100644 --- a/drivers/spi/mcp3002_test.go +++ b/drivers/spi/mcp3002_test.go @@ -37,7 +37,7 @@ func TestNewMCP3002Driver(t *testing.T) { } func TestMCP3002Read(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { chanNum int simRead []byte want int diff --git a/drivers/spi/mcp3004.go b/drivers/spi/mcp3004.go index 8c262b12f..eb5d77ee8 100644 --- a/drivers/spi/mcp3004.go +++ b/drivers/spi/mcp3004.go @@ -16,15 +16,16 @@ type MCP3004Driver struct { // NewMCP3004Driver creates a new Gobot Driver for MCP3004 A/D converter // // Params: -// a *Adaptor - the Adaptor to use with this Driver +// +// a *Adaptor - the Adaptor to use with this Driver // // Optional params: -// spi.WithBusNumber(int): bus to use with this driver -// spi.WithChipNumber(int): chip to use with this driver -// spi.WithMode(int): mode to use with this driver -// spi.WithBitCount(int): number of bits to use with this driver -// spi.WithSpeed(int64): speed in Hz to use with this driver // +// spi.WithBusNumber(int): bus to use with this driver +// spi.WithChipNumber(int): chip to use with this driver +// spi.WithMode(int): mode to use with this driver +// spi.WithBitCount(int): number of bits to use with this driver +// spi.WithSpeed(int64): speed in Hz to use with this driver func NewMCP3004Driver(a Connector, options ...func(Config)) *MCP3004Driver { d := &MCP3004Driver{ Driver: NewDriver(a, "MCP3004"), diff --git a/drivers/spi/mcp3004_test.go b/drivers/spi/mcp3004_test.go index 49f0f797b..6cc1e82f6 100644 --- a/drivers/spi/mcp3004_test.go +++ b/drivers/spi/mcp3004_test.go @@ -37,7 +37,7 @@ func TestNewMCP3004Driver(t *testing.T) { } func TestMCP3004Read(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { chanNum int simRead []byte want int diff --git a/drivers/spi/mcp3008.go b/drivers/spi/mcp3008.go index c5e037662..15a1f1622 100644 --- a/drivers/spi/mcp3008.go +++ b/drivers/spi/mcp3008.go @@ -16,15 +16,16 @@ type MCP3008Driver struct { // NewMCP3008Driver creates a new Gobot Driver for MCP3008Driver A/D converter // // Params: -// a *Adaptor - the Adaptor to use with this Driver +// +// a *Adaptor - the Adaptor to use with this Driver // // Optional params: -// spi.WithBusNumber(int): bus to use with this driver -// spi.WithChipNumber(int): chip to use with this driver -// spi.WithMode(int): mode to use with this driver -// spi.WithBitCount(int): number of bits to use with this driver -// spi.WithSpeed(int64): speed in Hz to use with this driver // +// spi.WithBusNumber(int): bus to use with this driver +// spi.WithChipNumber(int): chip to use with this driver +// spi.WithMode(int): mode to use with this driver +// spi.WithBitCount(int): number of bits to use with this driver +// spi.WithSpeed(int64): speed in Hz to use with this driver func NewMCP3008Driver(a Connector, options ...func(Config)) *MCP3008Driver { d := &MCP3008Driver{ Driver: NewDriver(a, "MCP3008"), diff --git a/drivers/spi/mcp3008_test.go b/drivers/spi/mcp3008_test.go index 1e7ad1958..e16230adc 100644 --- a/drivers/spi/mcp3008_test.go +++ b/drivers/spi/mcp3008_test.go @@ -37,7 +37,7 @@ func TestNewMCP3008Driver(t *testing.T) { } func TestMCP3008Read(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { chanNum int simRead []byte want int diff --git a/drivers/spi/mcp3202_test.go b/drivers/spi/mcp3202_test.go index 787e496fb..c5fa0ba92 100644 --- a/drivers/spi/mcp3202_test.go +++ b/drivers/spi/mcp3202_test.go @@ -37,7 +37,7 @@ func TestNewMCP3202Driver(t *testing.T) { } func TestMCP3202Read(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { chanNum int simRead []byte want int diff --git a/drivers/spi/mcp3204_test.go b/drivers/spi/mcp3204_test.go index 6f37dbbed..e2bcc2e92 100644 --- a/drivers/spi/mcp3204_test.go +++ b/drivers/spi/mcp3204_test.go @@ -37,7 +37,7 @@ func TestNewMCP3204Driver(t *testing.T) { } func TestMCP3204Read(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { chanNum int simRead []byte want int diff --git a/drivers/spi/mcp3208_test.go b/drivers/spi/mcp3208_test.go index 62c49ccb4..64d3a6395 100644 --- a/drivers/spi/mcp3208_test.go +++ b/drivers/spi/mcp3208_test.go @@ -37,7 +37,7 @@ func TestNewMCP3208Driver(t *testing.T) { } func TestMCP3208Read(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { chanNum int simRead []byte want int diff --git a/drivers/spi/mcp3304_test.go b/drivers/spi/mcp3304_test.go index 71dce0381..0740ddd45 100644 --- a/drivers/spi/mcp3304_test.go +++ b/drivers/spi/mcp3304_test.go @@ -37,7 +37,7 @@ func TestNewMCP3304Driver(t *testing.T) { } func TestMCP3304Read(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { chanNum int simRead []byte want int diff --git a/drivers/spi/spi_config.go b/drivers/spi/spi_config.go index 1e5f344d7..25142145b 100644 --- a/drivers/spi/spi_config.go +++ b/drivers/spi/spi_config.go @@ -15,7 +15,8 @@ func NewConfig() Config { chip: NotInitialized, mode: NotInitialized, bits: NotInitialized, - speed: NotInitialized} + speed: NotInitialized, + } } // WithBusNumber sets which bus to use as a optional param. diff --git a/drivers/spi/spi_driver_test.go b/drivers/spi/spi_driver_test.go index 7f96e487e..a91fefcf5 100644 --- a/drivers/spi/spi_driver_test.go +++ b/drivers/spi/spi_driver_test.go @@ -10,7 +10,7 @@ import ( var _ gobot.Driver = (*Driver)(nil) -func initTestDriverWithStubbedAdaptor() (*Driver, *spiTestAdaptor) { +func initTestDriverWithStubbedAdaptor() (*Driver, *spiTestAdaptor) { //nolint:unparam // keep for further tests a := newSpiTestAdaptor() d := NewDriver(a, "SPI_BASIC") if err := d.Start(); err != nil { diff --git a/drivers/spi/ssd1306_driver.go b/drivers/spi/ssd1306_driver.go index 377a0a5be..e57ac28a5 100644 --- a/drivers/spi/ssd1306_driver.go +++ b/drivers/spi/ssd1306_driver.go @@ -170,14 +170,14 @@ func NewSSD1306Driver(a gobot.Adaptor, options ...func(Config)) *SSD1306Driver { return map[string]interface{}{"err": err} }) s.AddCommand("SetContrast", func(params map[string]interface{}) interface{} { - contrast := byte(params["contrast"].(byte)) + contrast := params["contrast"].(byte) err := s.SetContrast(contrast) return map[string]interface{}{"err": err} }) s.AddCommand("Set", func(params map[string]interface{}) interface{} { - x := int(params["x"].(int)) - y := int(params["y"].(int)) - c := int(params["c"].(int)) + x := params["x"].(int) + y := params["y"].(int) + c := params["c"].(int) s.Set(x, y, c) return nil }) diff --git a/drivers/spi/ssd1306_driver_test.go b/drivers/spi/ssd1306_driver_test.go index a8b2caf87..7f01b1502 100644 --- a/drivers/spi/ssd1306_driver_test.go +++ b/drivers/spi/ssd1306_driver_test.go @@ -61,21 +61,25 @@ func (t *gpioTestAdaptor) ServoWrite(string, byte) (err error) { defer t.mtx.Unlock() return t.testAdaptorServoWrite() } + func (t *gpioTestAdaptor) PwmWrite(string, byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testAdaptorPwmWrite() } + func (t *gpioTestAdaptor) AnalogRead(string) (val int, err error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testAdaptorAnalogRead() } + func (t *gpioTestAdaptor) DigitalRead(string) (val int, err error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testAdaptorDigitalRead() } + func (t *gpioTestAdaptor) DigitalWrite(string, byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() diff --git a/examples/bb8-collision.go b/examples/bb8-collision.go index 63eb6b865..0b4df325d 100644 --- a/examples/bb8-collision.go +++ b/examples/bb8-collision.go @@ -29,7 +29,6 @@ func main() { bb := bb8.NewDriver(bleAdaptor) work := func() { - bb.On("collision", func(data interface{}) { fmt.Printf("collision detected = %+v \n", data) bb.SetRGB(255, 0, 0) @@ -46,5 +45,4 @@ func main() { ) robot.Start() - } diff --git a/examples/edison_grove_button.go b/examples/edison_grove_button.go index a58270460..cd47cc570 100644 --- a/examples/edison_grove_button.go +++ b/examples/edison_grove_button.go @@ -26,7 +26,6 @@ func main() { button.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("Off!") }) - } robot := gobot.NewRobot("bot", diff --git a/examples/edison_grove_touch.go b/examples/edison_grove_touch.go index 96d63d30a..c44281fe2 100644 --- a/examples/edison_grove_touch.go +++ b/examples/edison_grove_touch.go @@ -26,7 +26,6 @@ func main() { touch.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("Off!") }) - } robot := gobot.NewRobot("blinkBot", diff --git a/examples/firmata_aip1640.go b/examples/firmata_aip1640.go index 2faad221a..a2e4527f6 100644 --- a/examples/firmata_aip1640.go +++ b/examples/firmata_aip1640.go @@ -23,7 +23,6 @@ import ( ) func main() { - firmataAdaptor := firmata.NewAdaptor(os.Args[1]) // In the WEMOS D1 Mini LED Matrix Shield clockPin = 14, dataPin = 13 aip1640 := gpio.NewAIP1640Driver(firmataAdaptor, "14", "13") diff --git a/examples/firmata_ssd1306.go b/examples/firmata_ssd1306.go index a65dcf233..14ad349db 100644 --- a/examples/firmata_ssd1306.go +++ b/examples/firmata_ssd1306.go @@ -26,7 +26,6 @@ func main() { stage := false work := func() { - gobot.Every(1*time.Second, func() { fmt.Println("displaying") oled.Clear() diff --git a/examples/firmata_temp36.go b/examples/firmata_temp36.go index abc95fa14..94fca35a4 100644 --- a/examples/firmata_temp36.go +++ b/examples/firmata_temp36.go @@ -14,11 +14,10 @@ package main import ( + "fmt" "os" "time" - "fmt" - "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/firmata" ) diff --git a/examples/firmata_travis.go b/examples/firmata_travis.go index 970f9c8aa..f1e863b27 100644 --- a/examples/firmata_travis.go +++ b/examples/firmata_travis.go @@ -55,7 +55,7 @@ func checkTravis(robot *gobot.Robot) { resetLeds(robot) user := "hybridgroup" name := "gobot" - //name := "broken-arrow" + // name := "broken-arrow" fmt.Printf("Checking repo %s/%s\n", user, name) turnOn(robot, "blue") resp, err := http.Get(fmt.Sprintf("https://api.travis-ci.org/repos/%s/%s.json", user, name)) diff --git a/examples/gopigo3_servo.go b/examples/gopigo3_servo.go index 0cd08e18b..dbb943cb8 100644 --- a/examples/gopigo3_servo.go +++ b/examples/gopigo3_servo.go @@ -27,7 +27,6 @@ func main() { fmt.Println("Turning", i) servo.Move(i) }) - } robot := gobot.NewRobot("gopigo3servo", diff --git a/examples/jetson-nano_blink.go b/examples/jetson-nano_blink.go index 9174565e0..cd5632e49 100644 --- a/examples/jetson-nano_blink.go +++ b/examples/jetson-nano_blink.go @@ -31,5 +31,4 @@ func main() { ) robot.Start() - } diff --git a/examples/jetson-nano_servo.go b/examples/jetson-nano_servo.go index 9a2278c0c..064589ffc 100644 --- a/examples/jetson-nano_servo.go +++ b/examples/jetson-nano_servo.go @@ -21,7 +21,6 @@ import ( ) func main() { - jetsonAdaptor := jetson.NewAdaptor() servo := gpio.NewServoDriver(jetsonAdaptor, "32") @@ -29,7 +28,6 @@ func main() { flg := true work := func() { gobot.Every(100*time.Millisecond, func() { - log.Println("Turning", counter) servo.Move(uint8(counter)) if counter == 140 { @@ -42,10 +40,8 @@ func main() { counter = counter + 1 } else { counter = counter - 1 - } }) - } robot := gobot.NewRobot("Jetsonservo", diff --git a/examples/joystick_xboxone.go b/examples/joystick_xboxone.go index a680529e6..883a4d5f9 100644 --- a/examples/joystick_xboxone.go +++ b/examples/joystick_xboxone.go @@ -18,7 +18,6 @@ func main() { joystick := joystick.NewDriver(joystickAdaptor, joystick.XboxOne) work := func() { - // start button joystick.On(joystick.Event("start_press"), func(data interface{}) { fmt.Println("start_press") @@ -117,7 +116,7 @@ func main() { fmt.Println("lb_release") }) - //rb button + // rb button joystick.On(joystick.Event("rb_press"), func(data interface{}) { fmt.Println("rb_press") }) @@ -130,7 +129,7 @@ func main() { fmt.Println("right_x", data) }) - //ry stick + // ry stick joystick.On(joystick.Event("right_y"), func(data interface{}) { fmt.Println("right_y", data) }) @@ -143,12 +142,12 @@ func main() { fmt.Println("right_stick_release") }) - //lx stick + // lx stick joystick.On(joystick.Event("left_x"), func(data interface{}) { fmt.Println("left_x", data) }) - //ly stick + // ly stick joystick.On(joystick.Event("left_y"), func(data interface{}) { fmt.Println("left_y", data) }) @@ -160,7 +159,6 @@ func main() { joystick.On(joystick.Event("left_stick_release"), func(data interface{}) { fmt.Println("left_stick_release") }) - } robot := gobot.NewRobot("joystickBot", diff --git a/examples/nanopi_direct_pin_event.go b/examples/nanopi_direct_pin_event.go index 39c2a2c81..f29f4dd8d 100644 --- a/examples/nanopi_direct_pin_event.go +++ b/examples/nanopi_direct_pin_event.go @@ -34,7 +34,6 @@ var ( // LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC // Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state changes func main() { - board := nanopi.NewNeoAdaptor() work := func() { diff --git a/examples/nanopi_pca9533.go b/examples/nanopi_pca9533.go index 9c5f64bb1..73a5d614a 100644 --- a/examples/nanopi_pca9533.go +++ b/examples/nanopi_pca9533.go @@ -129,5 +129,4 @@ func initialize(pca *i2c.PCA953xDriver, led2FrequHz float32, led3FrequHz float32 if err != nil { fmt.Println("errW:", err) } - } diff --git a/examples/raspi_adafruit_dcmotor.go b/examples/raspi_adafruit_dcmotor.go index 8850a0bbc..9c3b668cc 100644 --- a/examples/raspi_adafruit_dcmotor.go +++ b/examples/raspi_adafruit_dcmotor.go @@ -49,7 +49,6 @@ func main() { work := func() { gobot.Every(5*time.Second, func() { - dcMotor := 2 // 0-based adafruitDCMotorRunner(adaFruit, dcMotor) }) diff --git a/examples/raspi_direct_pin_event.go b/examples/raspi_direct_pin_event.go index ccb44c0a9..0f50f3122 100644 --- a/examples/raspi_direct_pin_event.go +++ b/examples/raspi_direct_pin_event.go @@ -34,7 +34,6 @@ var ( // LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC // Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state changes func main() { - board := raspi.NewAdaptor() work := func() { diff --git a/examples/raspi_generic.go b/examples/raspi_generic.go index 45ea5cbe3..319986cdc 100644 --- a/examples/raspi_generic.go +++ b/examples/raspi_generic.go @@ -74,7 +74,6 @@ func main() { if read && write { if reflect.DeepEqual(wData, rData) { fmt.Printf("EEPROM addr: %d equal: %v\n", eepromAddr, rData) - } else { fmt.Printf("EEPROM addr: %d wr: %v differ rd: %v\n", eepromAddr, wData, rData) } diff --git a/examples/raspi_hmc5883l.go b/examples/raspi_hmc5883l.go index 57c55b430..1a6e46dc1 100644 --- a/examples/raspi_hmc5883l.go +++ b/examples/raspi_hmc5883l.go @@ -27,7 +27,6 @@ func main() { work := func() { gobot.Every(200*time.Millisecond, func() { - // get heading in radians, to convert to degrees multiply by 180/math.Pi heading, _ := hmc5883l.Heading() fmt.Println("Heading", heading) diff --git a/examples/raspi_ina3221.go b/examples/raspi_ina3221.go index 001f41532..13f4786bd 100644 --- a/examples/raspi_ina3221.go +++ b/examples/raspi_ina3221.go @@ -16,12 +16,10 @@ import ( ) func main() { - r := raspi.NewAdaptor() ina := i2c.NewINA3221Driver(r) work := func() { - gobot.Every(5*time.Second, func() { for _, ch := range []i2c.INA3221Channel{i2c.INA3221Channel1, i2c.INA3221Channel2, i2c.INA3221Channel3} { val, err := ina.GetBusVoltage(ch) diff --git a/examples/raspi_pca9533.go b/examples/raspi_pca9533.go index a48ec1f4d..f71959f2f 100644 --- a/examples/raspi_pca9533.go +++ b/examples/raspi_pca9533.go @@ -129,5 +129,4 @@ func initialize(pca *i2c.PCA953xDriver, led2FrequHz float32, led3FrequHz float32 if err != nil { fmt.Println("errW:", err) } - } diff --git a/examples/raspi_ssd1306.go b/examples/raspi_ssd1306.go index fc08aa938..c43f58175 100644 --- a/examples/raspi_ssd1306.go +++ b/examples/raspi_ssd1306.go @@ -23,7 +23,6 @@ func main() { stage := false work := func() { - gobot.Every(1*time.Second, func() { oled.Clear() if stage { diff --git a/examples/raspi_stepper_move.go b/examples/raspi_stepper_move.go index 5c22b9b2a..61784039c 100644 --- a/examples/raspi_stepper_move.go +++ b/examples/raspi_stepper_move.go @@ -19,15 +19,15 @@ func main() { stepper := gpio.NewStepperDriver(r, [4]string{"7", "11", "13", "15"}, gpio.StepperModes.DualPhaseStepping, 2048) work := func() { - //set spped + // set spped stepper.SetSpeed(15) - //Move forward one revolution + // Move forward one revolution if err := stepper.Move(2048); err != nil { fmt.Println(err) } - //Move backward one revolution + // Move backward one revolution if err := stepper.Move(-2048); err != nil { fmt.Println(err) } diff --git a/examples/tinkerboard_adafruit1109_lcd_keys.go b/examples/tinkerboard_adafruit1109_lcd_keys.go index ae3f93fe9..305c09484 100644 --- a/examples/tinkerboard_adafruit1109_lcd_keys.go +++ b/examples/tinkerboard_adafruit1109_lcd_keys.go @@ -110,9 +110,7 @@ func main() { } } }) - }) - } robot := gobot.NewRobot("adaBot", diff --git a/examples/tinkerboard_direct_pin.go b/examples/tinkerboard_direct_pin.go index 4a3b43522..222425f60 100644 --- a/examples/tinkerboard_direct_pin.go +++ b/examples/tinkerboard_direct_pin.go @@ -62,7 +62,6 @@ func main() { } else { level = 1 } - }) } diff --git a/examples/tinkerboard_generic.go b/examples/tinkerboard_generic.go index e54948b4d..c76e9e16e 100644 --- a/examples/tinkerboard_generic.go +++ b/examples/tinkerboard_generic.go @@ -84,7 +84,6 @@ func main() { if read && write { if reflect.DeepEqual(wData, rData) { fmt.Printf("EEPROM addr: %d equal: %v\n", eepromAddr, rData) - } else { fmt.Printf("EEPROM addr: %d wr: %v differ rd: %v\n", eepromAddr, wData, rData) } diff --git a/examples/tinkerboard_mfcrc522gpio.go b/examples/tinkerboard_mfcrc522gpio.go index b630b2efe..fa126e2df 100644 --- a/examples/tinkerboard_mfcrc522gpio.go +++ b/examples/tinkerboard_mfcrc522gpio.go @@ -41,7 +41,6 @@ func main() { } gobot.Every(2*time.Second, func() { - if !wasCardDetected { fmt.Println("\n+++ poll for card +++") if err := d.IsCardPresent(); err != nil { @@ -64,7 +63,6 @@ func main() { fmt.Printf("-- start text --\n%s\n-- end text --\n", text) } } - }) } diff --git a/examples/tinkerboard_pca9533.go b/examples/tinkerboard_pca9533.go index 2b1360969..cf9b03085 100644 --- a/examples/tinkerboard_pca9533.go +++ b/examples/tinkerboard_pca9533.go @@ -129,5 +129,4 @@ func initialize(pca *i2c.PCA953xDriver, led2FrequHz float32, led3FrequHz float32 if err != nil { fmt.Println("errW:", err) } - } diff --git a/examples/tinkerboard_pcf8583_clock.go b/examples/tinkerboard_pcf8583_clock.go index da2e93dca..ddd3209be 100644 --- a/examples/tinkerboard_pcf8583_clock.go +++ b/examples/tinkerboard_pcf8583_clock.go @@ -25,7 +25,6 @@ func main() { pcf := i2c.NewPCF8583Driver(board, i2c.WithBus(1), i2c.WithPCF8583Mode(i2c.PCF8583CtrlModeClock50)) work := func() { - currentTime := time.Now() log.Println(currentTime) diff --git a/helpers_test.go b/helpers_test.go index b97cf7c03..dee5d39a1 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -23,8 +23,10 @@ type testDriver struct { Commander } -var testDriverStart = func() (err error) { return } -var testDriverHalt = func() (err error) { return } +var ( + testDriverStart = func() (err error) { return } + testDriverHalt = func() (err error) { return } +) func (t *testDriver) Start() (err error) { return testDriverStart() } func (t *testDriver) Halt() (err error) { return testDriverHalt() } @@ -51,8 +53,10 @@ type testAdaptor struct { port string } -var testAdaptorConnect = func() (err error) { return } -var testAdaptorFinalize = func() (err error) { return } +var ( + testAdaptorConnect = func() (err error) { return } + testAdaptorFinalize = func() (err error) { return } +) func (t *testAdaptor) Finalize() (err error) { return testAdaptorFinalize() } func (t *testAdaptor) Connect() (err error) { return testAdaptorConnect() } @@ -60,7 +64,7 @@ func (t *testAdaptor) Name() string { return t.name } func (t *testAdaptor) SetName(n string) { t.name = n } func (t *testAdaptor) Port() string { return t.port } -func newTestAdaptor(name string, port string) *testAdaptor { +func newTestAdaptor(name string, port string) *testAdaptor { //nolint:unparam // keep for tests return &testAdaptor{ name: name, port: port, diff --git a/platforms/adaptors/digitalpinsadaptor.go b/platforms/adaptors/digitalpinsadaptor.go index a171134e4..5321bb2e5 100644 --- a/platforms/adaptors/digitalpinsadaptor.go +++ b/platforms/adaptors/digitalpinsadaptor.go @@ -10,8 +10,10 @@ import ( "gobot.io/x/gobot/v2/system" ) -type digitalPinTranslator func(pin string) (chip string, line int, err error) -type digitalPinInitializer func(gobot.DigitalPinner) error +type ( + digitalPinTranslator func(pin string) (chip string, line int, err error) + digitalPinInitializer func(gobot.DigitalPinner) error +) type digitalPinsOptioner interface { setDigitalPinInitializer(digitalPinInitializer) @@ -158,7 +160,8 @@ func WithGpioDebounce(pin string, period time.Duration) func(Optioner) { // WithGpioEventOnFallingEdge prepares the given input pin to be generate an event on falling edge. // This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI. func WithGpioEventOnFallingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string, - seqno uint32, lseqno uint32)) func(Optioner) { + seqno uint32, lseqno uint32), +) func(Optioner) { return func(o Optioner) { a, ok := o.(digitalPinsOptioner) if ok { @@ -170,7 +173,8 @@ func WithGpioEventOnFallingEdge(pin string, handler func(lineOffset int, timesta // WithGpioEventOnRisingEdge prepares the given input pin to be generate an event on rising edge. // This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI. func WithGpioEventOnRisingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string, - seqno uint32, lseqno uint32)) func(Optioner) { + seqno uint32, lseqno uint32), +) func(Optioner) { return func(o Optioner) { a, ok := o.(digitalPinsOptioner) if ok { @@ -182,7 +186,8 @@ func WithGpioEventOnRisingEdge(pin string, handler func(lineOffset int, timestam // WithGpioEventOnBothEdges prepares the given input pin to be generate an event on rising and falling edges. // This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI. func WithGpioEventOnBothEdges(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string, - seqno uint32, lseqno uint32)) func(Optioner) { + seqno uint32, lseqno uint32), +) func(Optioner) { return func(o Optioner) { a, ok := o.(digitalPinsOptioner) if ok { @@ -336,7 +341,8 @@ func (a *DigitalPinsAdaptor) prepareDigitalPinDebounce(id string, period time.Du } func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnFallingEdge(id string, handler func(int, time.Duration, string, - uint32, uint32)) { + uint32, uint32), +) { if a.pinOptions == nil { a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) } @@ -345,7 +351,8 @@ func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnFallingEdge(id string, hand } func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnRisingEdge(id string, handler func(int, time.Duration, string, - uint32, uint32)) { + uint32, uint32), +) { if a.pinOptions == nil { a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) } @@ -354,7 +361,8 @@ func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnRisingEdge(id string, handl } func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnBothEdges(id string, handler func(int, time.Duration, string, - uint32, uint32)) { + uint32, uint32), +) { if a.pinOptions == nil { a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) } diff --git a/platforms/adaptors/digitalpinsadaptor_test.go b/platforms/adaptors/digitalpinsadaptor_test.go index 59a4f74d5..fce9649a7 100644 --- a/platforms/adaptors/digitalpinsadaptor_test.go +++ b/platforms/adaptors/digitalpinsadaptor_test.go @@ -2,12 +2,11 @@ package adaptors import ( "fmt" - "testing" - "time" - "runtime" "strconv" "sync" + "testing" + "time" "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" @@ -16,9 +15,11 @@ import ( ) // make sure that this adaptor fulfills all the required interfaces -var _ gobot.DigitalPinnerProvider = (*DigitalPinsAdaptor)(nil) -var _ gpio.DigitalReader = (*DigitalPinsAdaptor)(nil) -var _ gpio.DigitalWriter = (*DigitalPinsAdaptor)(nil) +var ( + _ gobot.DigitalPinnerProvider = (*DigitalPinsAdaptor)(nil) + _ gpio.DigitalReader = (*DigitalPinsAdaptor)(nil) + _ gpio.DigitalWriter = (*DigitalPinsAdaptor)(nil) +) func initTestDigitalPinsAdaptorWithMockedFilesystem(mockPaths []string) (*DigitalPinsAdaptor, *system.MockFilesystem) { sys := system.NewAccesser() diff --git a/platforms/adaptors/pwmpinsadaptor.go b/platforms/adaptors/pwmpinsadaptor.go index 914771940..f1b88de91 100644 --- a/platforms/adaptors/pwmpinsadaptor.go +++ b/platforms/adaptors/pwmpinsadaptor.go @@ -15,8 +15,10 @@ import ( // 100ns = 10MHz, 10ns = 100MHz, 1ns = 1GHz const pwmPeriodDefault = 10000000 // 10 ms = 100 Hz -type pwmPinTranslator func(pin string) (path string, channel int, err error) -type pwmPinInitializer func(gobot.PWMPinner) error +type ( + pwmPinTranslator func(pin string) (path string, channel int, err error) + pwmPinInitializer func(gobot.PWMPinner) error +) type pwmPinsOption interface { setInitializer(pwmPinInitializer) @@ -228,7 +230,7 @@ func (a *PWMPinsAdaptor) pwmPin(id string) (gobot.PWMPinner, error) { // also this value will be adjusted in the same ratio. The order of writing the values must be observed, otherwise an // error occur "write error: Invalid argument". func setPeriod(pin gobot.PWMPinner, period uint32, adjustDuty bool) error { - var errorBase = fmt.Sprintf("setPeriod(%v, %d) failed", pin, period) + errorBase := fmt.Sprintf("setPeriod(%v, %d) failed", pin, period) var oldDuty uint32 var err error @@ -255,11 +257,11 @@ func setPeriod(pin gobot.PWMPinner, period uint32, adjustDuty bool) error { if err := pin.SetPeriod(period); err != nil { return fmt.Errorf("%s with '%v'", errorBase, err) } - if err := pin.SetDutyCycle(uint32(duty)); err != nil { + if err := pin.SetDutyCycle(duty); err != nil { return fmt.Errorf("%s with '%v'", errorBase, err) } } else { - if err := pin.SetDutyCycle(uint32(duty)); err != nil { + if err := pin.SetDutyCycle(duty); err != nil { return fmt.Errorf("%s with '%v'", errorBase, err) } if err := pin.SetPeriod(period); err != nil { diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index fad38191f..322533c7a 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -16,7 +16,7 @@ import ( ) const ( - pwmDir = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/" + pwmDir = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/" //nolint:gosec // false positive pwmPwm0Dir = pwmDir + "pwm44/" pwmExportPath = pwmDir + "export" pwmUnexportPath = pwmDir + "unexport" @@ -36,9 +36,11 @@ var pwmMockPaths = []string{ } // make sure that this PWMPinsAdaptor fulfills all the required interfaces -var _ gobot.PWMPinnerProvider = (*PWMPinsAdaptor)(nil) -var _ gpio.PwmWriter = (*PWMPinsAdaptor)(nil) -var _ gpio.ServoWriter = (*PWMPinsAdaptor)(nil) +var ( + _ gobot.PWMPinnerProvider = (*PWMPinsAdaptor)(nil) + _ gpio.PwmWriter = (*PWMPinsAdaptor)(nil) + _ gpio.ServoWriter = (*PWMPinsAdaptor)(nil) +) func initTestPWMPinsAdaptorWithMockedFilesystem(mockPaths []string) (*PWMPinsAdaptor, *system.MockFilesystem) { sys := system.NewAccesser() @@ -270,7 +272,7 @@ func TestSetPeriod(t *testing.T) { func Test_PWMPin(t *testing.T) { translateErr := "translator_error" translator := func(string) (string, int, error) { return pwmDir, 44, nil } - var tests = map[string]struct { + tests := map[string]struct { mockPaths []string period string dutyCycle string @@ -353,7 +355,6 @@ func Test_PWMPin(t *testing.T) { assert.Contains(t, err.Error(), tc.wantErr) assert.Nil(t, got) } - }) } } diff --git a/platforms/adaptors/spibusadaptor.go b/platforms/adaptors/spibusadaptor.go index 12e6acf00..55608300a 100644 --- a/platforms/adaptors/spibusadaptor.go +++ b/platforms/adaptors/spibusadaptor.go @@ -27,7 +27,8 @@ type SpiBusAdaptor struct { // NewSpiBusAdaptor provides the access to SPI buses of the board. The validator is used to check the // bus number (given by user) to the abilities of the board. func NewSpiBusAdaptor(sys *system.Accesser, v spiBusNumberValidator, busNum, chipNum, mode, bits int, - maxSpeed int64) *SpiBusAdaptor { + maxSpeed int64, +) *SpiBusAdaptor { a := &SpiBusAdaptor{ sys: sys, validateBusNumber: v, diff --git a/platforms/audio/audio_adaptor_test.go b/platforms/audio/audio_adaptor_test.go index b11e9741e..42f69549e 100644 --- a/platforms/audio/audio_adaptor_test.go +++ b/platforms/audio/audio_adaptor_test.go @@ -71,7 +71,7 @@ func TestAudioAdaptorSoundWithValidMP3Filename(t *testing.T) { func myExecCommand(command string, args ...string) *exec.Cmd { cs := []string{"-test.run=TestHelperProcess", "--", command} cs = append(cs, args...) - cmd := exec.Command(os.Args[0], cs...) + cmd := exec.Command(os.Args[0], cs...) //nolint:gosec // ok for test cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} return cmd } diff --git a/platforms/beaglebone/beaglebone_adaptor.go b/platforms/beaglebone/beaglebone_adaptor.go index c208f9fa6..2486b9cf2 100644 --- a/platforms/beaglebone/beaglebone_adaptor.go +++ b/platforms/beaglebone/beaglebone_adaptor.go @@ -127,7 +127,7 @@ func (c *Adaptor) DigitalWrite(id string, val byte) error { defer c.mutex.Unlock() if strings.Contains(id, "usr") { - fi, e := c.sys.OpenFile(c.usrLed+id+"/brightness", os.O_WRONLY|os.O_APPEND, 0666) + fi, e := c.sys.OpenFile(c.usrLed+id+"/brightness", os.O_WRONLY|os.O_APPEND, 0o666) defer fi.Close() //nolint:staticcheck // for historical reasons if e != nil { return e @@ -145,14 +145,14 @@ func (c *Adaptor) AnalogRead(pin string) (val int, err error) { if err != nil { return } - fi, err := c.sys.OpenFile(fmt.Sprintf("%v/%v", c.analogPath, analogPin), os.O_RDONLY, 0644) + fi, err := c.sys.OpenFile(fmt.Sprintf("%v/%v", c.analogPath, analogPin), os.O_RDONLY, 0o644) defer fi.Close() //nolint:staticcheck // for historical reasons if err != nil { return } - var buf = make([]byte, 1024) + buf := make([]byte, 1024) _, err = fi.Read(buf) if err != nil { return @@ -238,7 +238,7 @@ func (p pwmPinData) findPWMDir(sys *system.Accesser) (dir string, err error) { func (c *Adaptor) muxPin(pin, cmd string) error { path := fmt.Sprintf("/sys/devices/platform/ocp/ocp:%s_pinmux/state", pin) - fi, e := c.sys.OpenFile(path, os.O_WRONLY, 0666) + fi, e := c.sys.OpenFile(path, os.O_WRONLY, 0o666) defer fi.Close() //nolint:staticcheck // for historical reasons if e != nil { return e diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index 987d08e9a..55a927a6b 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -15,16 +15,18 @@ import ( ) // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ aio.AnalogReader = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ gpio.ServoWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) -var _ spi.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ aio.AnalogReader = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ gpio.ServoWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) + _ spi.Connector = (*Adaptor)(nil) +) func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system.MockFilesystem) { a := NewAdaptor() @@ -244,7 +246,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateSpiBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -276,7 +278,7 @@ func Test_validateSpiBusNumber(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -321,7 +323,7 @@ func Test_translateAndMuxPWMPin(t *testing.T) { } a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) - var tests = map[string]struct { + tests := map[string]struct { wantDir string wantChannel int wantErr error diff --git a/platforms/ble/battery_driver.go b/platforms/ble/battery_driver.go index 0366a63d6..fc38e7262 100644 --- a/platforms/ble/battery_driver.go +++ b/platforms/ble/battery_driver.go @@ -57,6 +57,6 @@ func (b *BatteryDriver) GetBatteryLevel() (level uint8) { } buf := bytes.NewBuffer(c) val, _ := buf.ReadByte() - l = uint8(val) + l = val return l } diff --git a/platforms/ble/ble_client_adaptor.go b/platforms/ble/ble_client_adaptor.go index ce65c3807..8af9419dc 100644 --- a/platforms/ble/ble_client_adaptor.go +++ b/platforms/ble/ble_client_adaptor.go @@ -11,8 +11,10 @@ import ( "tinygo.org/x/bluetooth" ) -var currentAdapter *bluetooth.Adapter -var bleMutex sync.Mutex +var ( + currentAdapter *bluetooth.Adapter + bleMutex sync.Mutex +) // BLEConnector is the interface that a BLE ClientAdaptor must implement type BLEConnector interface { @@ -212,7 +214,7 @@ func (b *ClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { } // getBLEAdapter is singleton for bluetooth adapter connection -func getBLEAdapter(impl string) (*bluetooth.Adapter, error) { +func getBLEAdapter(impl string) (*bluetooth.Adapter, error) { //nolint:unparam // TODO: impl is unused, maybe an error if currentAdapter != nil { return currentAdapter, nil } diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index 69113b4ad..f235930a6 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -13,14 +13,16 @@ import ( ) // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ gpio.ServoWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ gpio.ServoWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) +) var mockPaths = []string{ "/sys/class/gpio/export", @@ -176,7 +178,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -211,7 +213,7 @@ func Test_validateI2cBusNumber(t *testing.T) { } func Test_translatePWMPin(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { usePro bool wantDir string wantChannel int diff --git a/platforms/dexter/gopigo3/driver.go b/platforms/dexter/gopigo3/driver.go index bbed8c56a..f4c3f12ad 100644 --- a/platforms/dexter/gopigo3/driver.go +++ b/platforms/dexter/gopigo3/driver.go @@ -307,9 +307,9 @@ func (g *Driver) SetLED(led Led, red, green, blue uint8) error { goPiGo3Address, SET_LED, byte(led), - byte(red), - byte(green), - byte(blue), + red, + green, + blue, }) } @@ -403,7 +403,7 @@ func (g *Driver) GetMotorStatus(motor Motor) (flags uint8, power uint16, encoder return flags, power, encoder, dps, err } // get flags - flags = uint8(response[4]) + flags = response[4] // get power power = uint16(response[5]) if power&0x80 == 0x80 { @@ -420,7 +420,7 @@ func (g *Driver) GetMotorStatus(motor Motor) (flags uint8, power uint16, encoder if e&0x80000000 == 0x80000000 { encoder = int(uint64(e) - 0x100000000) } - //get dps + // get dps d := make([]byte, 4) d[1] = response[10] d[0] = response[11] @@ -596,7 +596,7 @@ func (g *Driver) DigitalWrite(pin string, val byte) error { goPiGo3Address, SET_GROVE_STATE, byte(grovePin), - byte(val), + val, }) } diff --git a/platforms/dexter/gopigo3/driver_test.go b/platforms/dexter/gopigo3/driver_test.go index 4b1c5846d..c133742d4 100644 --- a/platforms/dexter/gopigo3/driver_test.go +++ b/platforms/dexter/gopigo3/driver_test.go @@ -9,8 +9,10 @@ import ( "gobot.io/x/gobot/v2/drivers/spi" ) -var _ gobot.Driver = (*Driver)(nil) -var negativeEncoder = false +var ( + _ gobot.Driver = (*Driver)(nil) + negativeEncoder = false +) func initTestDriver() *Driver { d := NewDriver(&TestConnector{}) @@ -272,8 +274,7 @@ func (ctr *TestConnector) SpiDefaultMaxSpeed() int64 { return 0 } -type TestSpiDevice struct { -} +type TestSpiDevice struct{} func (c TestSpiDevice) Close() error { return nil diff --git a/platforms/digispark/digispark_adaptor.go b/platforms/digispark/digispark_adaptor.go index d72e88173..29c0815b0 100644 --- a/platforms/digispark/digispark_adaptor.go +++ b/platforms/digispark/digispark_adaptor.go @@ -54,7 +54,6 @@ func (d *Adaptor) Finalize() (err error) { return } // DigitalWrite writes a value to the pin. Acceptable values are 1 or 0. func (d *Adaptor) DigitalWrite(pin string, level byte) (err error) { p, err := strconv.Atoi(pin) - if err != nil { return } diff --git a/platforms/digispark/digispark_adaptor_test.go b/platforms/digispark/digispark_adaptor_test.go index f144f0a05..7f5fc36d3 100644 --- a/platforms/digispark/digispark_adaptor_test.go +++ b/platforms/digispark/digispark_adaptor_test.go @@ -12,9 +12,11 @@ import ( var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ gpio.ServoWriter = (*Adaptor)(nil) +var ( + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ gpio.ServoWriter = (*Adaptor)(nil) +) type mock struct { locationA uint8 @@ -33,6 +35,7 @@ func (l *mock) digitalWrite(pin uint8, state uint8) error { l.state = state return l.error() } + func (l *mock) pinMode(pin uint8, mode uint8) error { l.pin = pin l.mode = mode @@ -48,6 +51,7 @@ func (l *mock) pwmUpdateCompare(channelA uint8, channelB uint8) error { l.pwmChannelB = channelB return l.error() } + func (l *mock) pwmUpdatePrescaler(value uint) error { l.pwmPrescalerValue = value return l.error() diff --git a/platforms/digispark/digispark_i2c.go b/platforms/digispark/digispark_i2c.go index 07a8a9547..6249c2a20 100644 --- a/platforms/digispark/digispark_i2c.go +++ b/platforms/digispark/digispark_i2c.go @@ -38,7 +38,7 @@ func (c *digisparkI2cConnection) Test(address uint8) error { return c.adaptor.littleWire.i2cStart(address, 0) } -// UpdateDelay updates i2c signal delay amount; tune if neccessary to fit your requirements +// UpdateDelay updates i2c signal delay amount; tune if necessary to fit your requirements func (c *digisparkI2cConnection) UpdateDelay(duration uint) error { if !c.adaptor.i2c { return errors.New("Digispark i2c not initialized") diff --git a/platforms/digispark/digispark_i2c_test.go b/platforms/digispark/digispark_i2c_test.go index dfc0dd463..9b5ccbeec 100644 --- a/platforms/digispark/digispark_i2c_test.go +++ b/platforms/digispark/digispark_i2c_test.go @@ -8,11 +8,15 @@ import ( "gobot.io/x/gobot/v2/drivers/i2c" ) -const availableI2cAddress = 0x40 -const maxUint8 = ^uint8(0) +const ( + availableI2cAddress = 0x40 + maxUint8 = ^uint8(0) +) -var _ i2c.Connector = (*Adaptor)(nil) -var i2cData = []byte{5, 4, 3, 2, 1, 0} +var ( + _ i2c.Connector = (*Adaptor)(nil) + i2cData = []byte{5, 4, 3, 2, 1, 0} +) type i2cMock struct { duration uint diff --git a/platforms/digispark/littleWire.go b/platforms/digispark/littleWire.go index d3e3c3c83..0f2236835 100644 --- a/platforms/digispark/littleWire.go +++ b/platforms/digispark/littleWire.go @@ -106,7 +106,7 @@ func (l *littleWire) i2cRead(readBuffer []byte, length int, endWithStop uint8) e return l.error() } -// i2cUpdateDelay updates i2c signal delay amount. Tune if neccessary to fit your requirements +// i2cUpdateDelay updates i2c signal delay amount. Tune if necessary to fit your requirements func (l *littleWire) i2cUpdateDelay(duration uint) error { C.i2c_updateDelay(l.lwHandle, C.uint(duration)) return l.error() diff --git a/platforms/digispark/littleWire.h b/platforms/digispark/littleWire.h index a46a353b2..ada3f0dbc 100644 --- a/platforms/digispark/littleWire.h +++ b/platforms/digispark/littleWire.h @@ -405,7 +405,7 @@ void i2c_write(littleWire* lwHandle, unsigned char* sendBuffer, unsigned char le void i2c_read(littleWire* lwHandle, unsigned char* readBuffer, unsigned char length, unsigned char endWithStop); /** - * Update i2c signal delay amount. Tune if neccessary to fit your requirements. + * Update i2c signal delay amount. Tune if necessary to fit your requirements. * * @param lwHandle littleWire device pointer * @param duration Delay amount diff --git a/platforms/dji/tello/crc.go b/platforms/dji/tello/crc.go index 834a74d4a..3aa031b0d 100644 --- a/platforms/dji/tello/crc.go +++ b/platforms/dji/tello/crc.go @@ -23,7 +23,7 @@ var crc8table = []byte{ func CalculateCRC8(pkt []byte) byte { crc := byte(0x77) for _, val := range pkt { - crc = crc8table[(crc^byte(val))&0xff] + crc = crc8table[(crc^val)&0xff] } return crc diff --git a/platforms/dji/tello/driver.go b/platforms/dji/tello/driver.go index f48d28e99..808993c05 100644 --- a/platforms/dji/tello/driver.go +++ b/platforms/dji/tello/driver.go @@ -208,7 +208,8 @@ func NewDriver(port string) *Driver { // NewDriverWithIP creates a driver for the Tello EDU drone. Pass in the ip address and UDP port to use for the responses // from the drone. func NewDriverWithIP(ip string, port string) *Driver { - d := &Driver{name: gobot.DefaultName("Tello"), + d := &Driver{ + name: gobot.DefaultName("Tello"), reqAddr: ip + ":8889", respPort: port, videoPort: "11111", @@ -275,7 +276,6 @@ func (d *Driver) Start() error { panic(err) } }) - if err != nil { panic(err) } @@ -519,7 +519,7 @@ func (d *Driver) Rate() error { } // bound is a naive implementation that returns the smaller of x or y. -func bound(x, y float32) float32 { +func bound(x, y float32) float32 { //nolint:unparam // keep y as parameter if x < -y { return -y } diff --git a/platforms/dji/tello/driver_test.go b/platforms/dji/tello/driver_test.go index 793015bbd..3571c0160 100644 --- a/platforms/dji/tello/driver_test.go +++ b/platforms/dji/tello/driver_test.go @@ -20,6 +20,7 @@ type WriteCloserDoNothing struct{} func (w *WriteCloserDoNothing) Write(p []byte) (n int, err error) { return 0, nil } + func (w *WriteCloserDoNothing) Close() error { return nil } diff --git a/platforms/dragonboard/dragonboard_adaptor_test.go b/platforms/dragonboard/dragonboard_adaptor_test.go index e54a4d5c3..acf7117f4 100644 --- a/platforms/dragonboard/dragonboard_adaptor_test.go +++ b/platforms/dragonboard/dragonboard_adaptor_test.go @@ -12,13 +12,15 @@ import ( ) // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) +) -func initTestAdaptor(t *testing.T) *Adaptor { +func initTestAdaptor() *Adaptor { a := NewAdaptor() if err := a.Connect(); err != nil { panic(err) @@ -27,14 +29,14 @@ func initTestAdaptor(t *testing.T) *Adaptor { } func TestName(t *testing.T) { - a := initTestAdaptor(t) + a := initTestAdaptor() assert.True(t, strings.HasPrefix(a.Name(), "DragonBoard")) a.SetName("NewName") assert.Equal(t, "NewName", a.Name()) } func TestDigitalIO(t *testing.T) { - a := initTestAdaptor(t) + a := initTestAdaptor() mockPaths := []string{ "/sys/class/gpio/export", "/sys/class/gpio/unexport", @@ -57,7 +59,7 @@ func TestDigitalIO(t *testing.T) { } func TestFinalizeErrorAfterGPIO(t *testing.T) { - a := initTestAdaptor(t) + a := initTestAdaptor() mockPaths := []string{ "/sys/class/gpio/export", "/sys/class/gpio/unexport", @@ -78,7 +80,7 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { } func TestI2cDefaultBus(t *testing.T) { - a := initTestAdaptor(t) + a := initTestAdaptor() assert.Equal(t, 0, a.DefaultI2cBus()) } @@ -100,7 +102,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ diff --git a/platforms/firmata/client/client.go b/platforms/firmata/client/client.go index 5b770265d..d445ed2a2 100644 --- a/platforms/firmata/client/client.go +++ b/platforms/firmata/client/client.go @@ -333,16 +333,18 @@ func (b *Client) ReportAnalog(pin int, state int) error { // I2cRead reads numBytes from address once. func (b *Client) I2cRead(address int, numBytes int) error { - return b.WriteSysex([]byte{I2CRequest, byte(address), (I2CModeRead << 3), - byte(numBytes) & 0x7F, (byte(numBytes) >> 7) & 0x7F}) + return b.WriteSysex([]byte{ + I2CRequest, byte(address), (I2CModeRead << 3), + byte(numBytes) & 0x7F, (byte(numBytes) >> 7) & 0x7F, + }) } // I2cWrite writes data to address. func (b *Client) I2cWrite(address int, data []byte) error { ret := []byte{I2CRequest, byte(address), (I2CModeWrite << 3)} for _, val := range data { - ret = append(ret, byte(val&0x7F)) - ret = append(ret, byte((val>>7)&0x7F)) + ret = append(ret, val&0x7F) + ret = append(ret, (val>>7)&0x7F) } return b.WriteSysex(ret) } @@ -360,7 +362,7 @@ func (b *Client) togglePinReporting(pin int, state int, mode byte) error { state = 0 } - return b.write([]byte{byte(mode) | byte(pin), byte(state)}) + return b.write([]byte{mode | byte(pin), byte(state)}) } // WriteSysex writes an arbitrary Sysex command to the microcontroller. @@ -421,7 +423,7 @@ func (b *Client) process() error { portValue := buf[0] | (buf[1] << 7) for i := 0; i < 8; i++ { - pinNumber := int((8*byte(port) + byte(i))) + pinNumber := int((8*port + byte(i))) if len(b.pins) > pinNumber { if b.pins[pinNumber].Mode == Input { b.pins[pinNumber].Value = int((portValue >> (byte(i) & 0x07)) & 0x01) @@ -505,9 +507,9 @@ func (b *Client) process() error { b.Publish(b.Event(fmt.Sprintf("PinState%v", pin)), b.pins[pin]) case I2CReply: reply := I2cReply{ - Address: int(byte(currentBuffer[2]) | byte(currentBuffer[3])<<7), - Register: int(byte(currentBuffer[4]) | byte(currentBuffer[5])<<7), - Data: []byte{byte(currentBuffer[6]) | byte(currentBuffer[7])<<7}, + Address: int(currentBuffer[2] | currentBuffer[3]<<7), + Register: int(currentBuffer[4] | currentBuffer[5]<<7), + Data: []byte{currentBuffer[6] | currentBuffer[7]<<7}, } for i := 8; i < len(currentBuffer); i = i + 2 { if currentBuffer[i] == byte(0xF7) { @@ -517,7 +519,7 @@ func (b *Client) process() error { break } reply.Data = append(reply.Data, - byte(currentBuffer[i])|byte(currentBuffer[i+1])<<7, + currentBuffer[i]|currentBuffer[i+1]<<7, ) } b.Publish(b.Event("I2cReply"), reply) diff --git a/platforms/firmata/client/client_test.go b/platforms/firmata/client/client_test.go index 968e04adc..5d979fead 100644 --- a/platforms/firmata/client/client_test.go +++ b/platforms/firmata/client/client_test.go @@ -16,33 +16,43 @@ type readWriteCloser struct { id string } -var testWriteData = bytes.Buffer{} -var writeDataMutex sync.Mutex +var ( + testWriteData = bytes.Buffer{} + writeDataMutex sync.Mutex +) // do not set this data directly, use always addTestReadData() -var testReadDataMap = make(map[string][]byte) -var rwDataMapMutex sync.Mutex +var ( + testReadDataMap = make(map[string][]byte) + rwDataMapMutex sync.Mutex +) // arduino uno r3 protocol response "2.3" var testDataProtocolResponse = []byte{249, 2, 3} // arduino uno r3 firmware response "StandardFirmata.ino" -var testDataFirmwareResponse = []byte{240, 121, 2, 3, 83, 0, 116, 0, 97, 0, 110, 0, 100, 0, 97, +var testDataFirmwareResponse = []byte{ + 240, 121, 2, 3, 83, 0, 116, 0, 97, 0, 110, 0, 100, 0, 97, 0, 114, 0, 100, 0, 70, 0, 105, 0, 114, 0, 109, 0, 97, 0, 116, 0, 97, 0, 46, - 0, 105, 0, 110, 0, 111, 0, 247} + 0, 105, 0, 110, 0, 111, 0, 247, +} // arduino uno r3 capabilities response -var testDataCapabilitiesResponse = []byte{240, 108, 127, 127, 0, 1, 1, 1, 4, 14, 127, 0, 1, 1, 1, 3, +var testDataCapabilitiesResponse = []byte{ + 240, 108, 127, 127, 0, 1, 1, 1, 4, 14, 127, 0, 1, 1, 1, 3, 8, 4, 14, 127, 0, 1, 1, 1, 4, 14, 127, 0, 1, 1, 1, 3, 8, 4, 14, 127, 0, 1, 1, 1, 3, 8, 4, 14, 127, 0, 1, 1, 1, 4, 14, 127, 0, 1, 1, 1, 4, 14, 127, 0, 1, 1, 1, 3, 8, 4, 14, 127, 0, 1, 1, 1, 3, 8, 4, 14, 127, 0, 1, 1, 1, 3, 8, 4, 14, 127, 0, 1, 1, 1, 4, 14, 127, 0, 1, 1, 1, 4, 14, 127, 0, 1, 1, 1, 2, 10, 127, 0, 1, 1, 1, 2, 10, 127, 0, 1, 1, 1, 2, 10, 127, 0, 1, 1, 1, 2, 10, - 127, 0, 1, 1, 1, 2, 10, 6, 1, 127, 0, 1, 1, 1, 2, 10, 6, 1, 127, 247} + 127, 0, 1, 1, 1, 2, 10, 6, 1, 127, 0, 1, 1, 1, 2, 10, 6, 1, 127, 247, +} // arduino uno r3 analog mapping response -var testDataAnalogMappingResponse = []byte{240, 106, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 0, 1, 2, 3, 4, 5, 247} +var testDataAnalogMappingResponse = []byte{ + 240, 106, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 0, 1, 2, 3, 4, 5, 247, +} func (readWriteCloser) Write(p []byte) (int, error) { writeDataMutex.Lock() @@ -79,7 +89,7 @@ func (rwc readWriteCloser) Read(b []byte) (int, error) { if len(data) < size { size = len(data) } - copy(b, []byte(data)[:size]) + copy(b, data[:size]) testReadDataMap[rwc.id] = data[size:] return size, nil } diff --git a/platforms/firmata/firmata_adaptor_test.go b/platforms/firmata/firmata_adaptor_test.go index 9f31cbb93..f943e57af 100644 --- a/platforms/firmata/firmata_adaptor_test.go +++ b/platforms/firmata/firmata_adaptor_test.go @@ -16,13 +16,15 @@ import ( ) // make sure that this Adaptor fulfills all required analog and digital interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ aio.AnalogReader = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ gpio.ServoWriter = (*Adaptor)(nil) -var _ FirmataAdaptor = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ aio.AnalogReader = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ gpio.ServoWriter = (*Adaptor)(nil) + _ FirmataAdaptor = (*Adaptor)(nil) +) type readWriteCloser struct{} @@ -30,15 +32,17 @@ func (readWriteCloser) Write(p []byte) (int, error) { return testWriteData.Write(p) } -var testReadData = []byte{} -var testWriteData = bytes.Buffer{} +var ( + testReadData = []byte{} + testWriteData = bytes.Buffer{} +) func (readWriteCloser) Read(b []byte) (int, error) { size := len(b) if len(testReadData) < size { size = len(testReadData) } - copy(b, []byte(testReadData)[:size]) + copy(b, testReadData[:size]) testReadData = testReadData[size:] return size, nil @@ -69,9 +73,11 @@ func newMockFirmataBoard() *mockFirmataBoard { // setup mock for GPIO, PWM and servo tests func (mockFirmataBoard) Connect(io.ReadWriteCloser) error { return nil } + func (m mockFirmataBoard) Disconnect() error { return m.disconnectError } + func (m mockFirmataBoard) Pins() []client.Pin { return m.pins } @@ -113,7 +119,7 @@ func TestAdaptorFinalize(t *testing.T) { } func TestAdaptorConnect(t *testing.T) { - var openSP = func(port string) (io.ReadWriteCloser, error) { + openSP := func(port string) (io.ReadWriteCloser, error) { return &readWriteCloser{}, nil } a := NewAdaptor("/dev/null") diff --git a/platforms/firmata/firmata_i2c_test.go b/platforms/firmata/firmata_i2c_test.go index 9afb94445..4bc3c55fd 100644 --- a/platforms/firmata/firmata_i2c_test.go +++ b/platforms/firmata/firmata_i2c_test.go @@ -31,6 +31,7 @@ func (t *i2cMockFirmataBoard) I2cRead(address int, numBytes int) error { }() return nil } + func (t *i2cMockFirmataBoard) I2cWrite(address int, data []byte) error { t.i2cWritten = append(t.i2cWritten, data...) return nil diff --git a/platforms/holystone/hs200/hs200_driver.go b/platforms/holystone/hs200/hs200_driver.go index c9f2808ef..e11f4114d 100644 --- a/platforms/holystone/hs200/hs200_driver.go +++ b/platforms/holystone/hs200/hs200_driver.go @@ -45,8 +45,10 @@ func NewDriver(tcpaddress string, udpaddress string) *Driver { } command[10] = checksum(command) - return &Driver{name: gobot.DefaultName("HS200"), stopc: make(chan struct{}), - tcpaddress: tcpaddress, udpaddress: udpaddress, cmd: command, mutex: &sync.RWMutex{}} + return &Driver{ + name: gobot.DefaultName("HS200"), stopc: make(chan struct{}), + tcpaddress: tcpaddress, udpaddress: udpaddress, cmd: command, mutex: &sync.RWMutex{}, + } } // Name returns the name of the device. diff --git a/platforms/intel-iot/curie/imu_driver_test.go b/platforms/intel-iot/curie/imu_driver_test.go index 48723d230..30eb76413 100644 --- a/platforms/intel-iot/curie/imu_driver_test.go +++ b/platforms/intel-iot/curie/imu_driver_test.go @@ -21,15 +21,17 @@ func (readWriteCloser) Write(p []byte) (int, error) { return testWriteData.Write(p) } -var testReadData = []byte{} -var testWriteData = bytes.Buffer{} +var ( + testReadData = []byte{} + testWriteData = bytes.Buffer{} +) func (readWriteCloser) Read(b []byte) (int, error) { size := len(b) if len(testReadData) < size { size = len(testReadData) } - copy(b, []byte(testReadData)[:size]) + copy(b, testReadData[:size]) testReadData = testReadData[size:] return size, nil @@ -63,6 +65,7 @@ func (mockFirmataBoard) Connect(io.ReadWriteCloser) error { return nil } func (m mockFirmataBoard) Disconnect() error { return m.disconnectError } + func (m mockFirmataBoard) Pins() []client.Pin { return m.pins } diff --git a/platforms/intel-iot/edison/edison_adaptor.go b/platforms/intel-iot/edison/edison_adaptor.go index 0dbd92bca..bcd754126 100644 --- a/platforms/intel-iot/edison/edison_adaptor.go +++ b/platforms/intel-iot/edison/edison_adaptor.go @@ -262,7 +262,7 @@ func (c *Adaptor) arduinoI2CSetup() error { } func (c *Adaptor) readFile(path string) ([]byte, error) { - file, err := c.sys.OpenFile(path, os.O_RDONLY, 0644) + file, err := c.sys.OpenFile(path, os.O_RDONLY, 0o644) defer file.Close() //nolint:staticcheck // for historical reasons if err != nil { return make([]byte, 0), err @@ -356,7 +356,7 @@ func (c *Adaptor) translateAndMuxPWMPin(id string) (string, int, error) { if err := c.digitalWrite(id, 1); err != nil { return "", -1, err } - if err := c.changePinMode(strconv.Itoa(int(sysPin.pin)), "1"); err != nil { + if err := c.changePinMode(strconv.Itoa(sysPin.pin), "1"); err != nil { return "", -1, err } return "/sys/class/pwm/pwmchip0", sysPin.pwmPin, nil @@ -378,7 +378,7 @@ func (c *Adaptor) newExportedDigitalPin(pin int, o ...func(gobot.DigitalPinOptio // changePinMode writes pin mode to current_pinmux file func (c *Adaptor) changePinMode(pin, mode string) error { - file, err := c.sys.OpenFile("/sys/kernel/debug/gpio_debug/gpio"+pin+"/current_pinmux", os.O_WRONLY, 0644) + file, err := c.sys.OpenFile("/sys/kernel/debug/gpio_debug/gpio"+pin+"/current_pinmux", os.O_WRONLY, 0o644) defer file.Close() //nolint:staticcheck // for historical reasons if err != nil { return err diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index 79e557e7a..d27024a4d 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -14,14 +14,16 @@ import ( ) // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ aio.AnalogReader = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ aio.AnalogReader = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) +) var testPinFiles = []string{ "/sys/bus/iio/devices/iio:device1/in_voltage0_raw", @@ -411,7 +413,6 @@ func TestDigitalPinInFileError(t *testing.T) { _, err := a.DigitalPin("13") assert.Contains(t, err.Error(), "no such file") - } func TestDigitalPinInResistorFileError(t *testing.T) { @@ -569,11 +570,10 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // assert assert.NotNil(t, err) assert.Contains(t, err.Error(), "close error") - } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { board string busNr int wantErr error diff --git a/platforms/intel-iot/joule/joule_adaptor_test.go b/platforms/intel-iot/joule/joule_adaptor_test.go index 316a1da0d..3ef493fb1 100644 --- a/platforms/intel-iot/joule/joule_adaptor_test.go +++ b/platforms/intel-iot/joule/joule_adaptor_test.go @@ -13,13 +13,15 @@ import ( ) // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) +) func initTestAdaptorWithMockedFilesystem() (*Adaptor, *system.MockFilesystem) { a := NewAdaptor() @@ -187,7 +189,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ diff --git a/platforms/jetson/jetson_adaptor_test.go b/platforms/jetson/jetson_adaptor_test.go index a7529f16f..6ba241227 100644 --- a/platforms/jetson/jetson_adaptor_test.go +++ b/platforms/jetson/jetson_adaptor_test.go @@ -2,12 +2,11 @@ package jetson import ( "fmt" - "strings" - "testing" - "runtime" "strconv" + "strings" "sync" + "testing" "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" @@ -18,13 +17,15 @@ import ( ) // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) -var _ spi.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) + _ spi.Connector = (*Adaptor)(nil) +) func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system.MockFilesystem) { a := NewAdaptor() @@ -175,7 +176,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateSpiBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -207,7 +208,7 @@ func Test_validateSpiBusNumber(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ diff --git a/platforms/jetson/pwm_pin.go b/platforms/jetson/pwm_pin.go index 9a9fcf313..18b432e0c 100644 --- a/platforms/jetson/pwm_pin.go +++ b/platforms/jetson/pwm_pin.go @@ -126,7 +126,7 @@ func (p *PWMPin) SetDutyCycle(duty uint32) error { func (p *PWMPin) writeFile(subpath string, value string) error { sysfspath := path.Join(p.path, subpath) - fi, err := p.sys.OpenFile(sysfspath, os.O_WRONLY|os.O_APPEND, 0644) + fi, err := p.sys.OpenFile(sysfspath, os.O_WRONLY|os.O_APPEND, 0o644) defer fi.Close() //nolint:staticcheck // for historical reasons if err != nil { diff --git a/platforms/joystick/bin/scanner.go b/platforms/joystick/bin/scanner.go index ec74112c9..fb4816fcf 100644 --- a/platforms/joystick/bin/scanner.go +++ b/platforms/joystick/bin/scanner.go @@ -1,7 +1,6 @@ //go:build utils // +build utils -// // Do not build by default. // // Joystick scanner @@ -9,17 +8,19 @@ // https://github.com/0xcafed00d/joystick/blob/master/joysticktest/joysticktest.go // Simple program that displays the state of the specified joystick // -// go run joysticktest.go 2 +// go run joysticktest.go 2 +// // displays state of joystick id 2 package main import ( "fmt" - "github.com/nsf/termbox-go" - "github.com/0xcafed00d/joystick" "os" "strconv" "time" + + "github.com/0xcafed00d/joystick" + "github.com/nsf/termbox-go" ) func printAt(x, y int, s string) { @@ -31,7 +32,6 @@ func printAt(x, y int, s string) { func readJoystick(js joystick.Joystick) { jinfo, err := js.Read() - if err != nil { printAt(1, 5, "Error: "+err.Error()) return @@ -55,7 +55,6 @@ func readJoystick(js joystick.Joystick) { } func main() { - jsid := 0 if len(os.Args) > 1 { i, err := strconv.Atoi(os.Args[1]) diff --git a/platforms/keyboard/keyboard.go b/platforms/keyboard/keyboard.go index 78ddc4f96..8ad037d90 100644 --- a/platforms/keyboard/keyboard.go +++ b/platforms/keyboard/keyboard.go @@ -78,7 +78,7 @@ const ( var originalState string func Parse(input bytes) KeyEvent { - var event = KeyEvent{Bytes: input, Char: string(input[:])} + event := KeyEvent{Bytes: input, Char: string(input[:])} var code byte diff --git a/platforms/leap/leap_motion_driver_test.go b/platforms/leap/leap_motion_driver_test.go index 735ad8e4a..34490e40c 100644 --- a/platforms/leap/leap_motion_driver_test.go +++ b/platforms/leap/leap_motion_driver_test.go @@ -30,9 +30,11 @@ func (n *NullReadWriteCloser) Write(p []byte) (int, error) { defer n.mtx.Unlock() return len(p), n.writeError } + func (n *NullReadWriteCloser) Read(b []byte) (int, error) { return len(b), nil } + func (n *NullReadWriteCloser) Close() error { return nil } diff --git a/platforms/mavlink/common/common.go b/platforms/mavlink/common/common.go index 1b26feee0..4f8133186 100644 --- a/platforms/mavlink/common/common.go +++ b/platforms/mavlink/common/common.go @@ -486,7 +486,7 @@ const ( // // MAV_ROI /* The ROI (region of interest) for the vehicle. This can be - be used by the vehicle for camera/vehicle attitude alignment (see + used by the vehicle for camera/vehicle attitude alignment (see MAV_CMD_NAV_ROI).*/ // const ( diff --git a/platforms/mavlink/common/mavlink.go b/platforms/mavlink/common/mavlink.go index 8051e5538..895a84531 100644 --- a/platforms/mavlink/common/mavlink.go +++ b/platforms/mavlink/common/mavlink.go @@ -188,7 +188,7 @@ func crcAccumulate(data uint8, crcAccum uint16) uint16 { tmp = data ^ (uint8)(crcAccum&0xff) tmp ^= (tmp << 4) - crcAccum = (uint16(crcAccum) >> 8) ^ (uint16(tmp) << 8) ^ (uint16(tmp) << 3) ^ (uint16(tmp) >> 4) + crcAccum = (crcAccum >> 8) ^ (uint16(tmp) << 8) ^ (uint16(tmp) << 3) ^ (uint16(tmp) >> 4) return crcAccum } diff --git a/platforms/mavlink/mavlink_driver.go b/platforms/mavlink/mavlink_driver.go index 97c12cdd5..d4330633d 100644 --- a/platforms/mavlink/mavlink_driver.go +++ b/platforms/mavlink/mavlink_driver.go @@ -25,8 +25,7 @@ type Driver struct { gobot.Eventer } -type MavlinkInterface interface { -} +type MavlinkInterface interface{} // NewDriver creates a new mavlink driver. // diff --git a/platforms/microbit/accelerometer_driver.go b/platforms/microbit/accelerometer_driver.go index b1cc4e3a9..97b26ad89 100644 --- a/platforms/microbit/accelerometer_driver.go +++ b/platforms/microbit/accelerometer_driver.go @@ -29,7 +29,7 @@ type AccelerometerData struct { const ( // BLE services - //accelerometerService = "e95d0753251d470aa062fa1922dfa9a8" + // accelerometerService = "e95d0753251d470aa062fa1922dfa9a8" // BLE characteristics accelerometerCharacteristic = "e95dca4b251d470aa062fa1922dfa9a8" @@ -85,7 +85,8 @@ func (b *AccelerometerDriver) Start() error { result := &AccelerometerData{ X: float32(a.X) / 1000.0, Y: float32(a.Y) / 1000.0, - Z: float32(a.Z) / 1000.0} + Z: float32(a.Z) / 1000.0, + } b.Publish(b.Event(Accelerometer), result) }) diff --git a/platforms/microbit/button_driver.go b/platforms/microbit/button_driver.go index 09b17107a..3fc779329 100644 --- a/platforms/microbit/button_driver.go +++ b/platforms/microbit/button_driver.go @@ -14,7 +14,7 @@ type ButtonDriver struct { const ( // BLE services - //buttonService = "e95d9882251d470aa062fa1922dfa9a8" + // buttonService = "e95d9882251d470aa062fa1922dfa9a8" // BLE characteristics buttonACharacteristic = "e95dda90251d470aa062fa1922dfa9a8" diff --git a/platforms/microbit/io_pin_driver.go b/platforms/microbit/io_pin_driver.go index b855c16bc..e9e4e51d6 100644 --- a/platforms/microbit/io_pin_driver.go +++ b/platforms/microbit/io_pin_driver.go @@ -22,7 +22,7 @@ type IOPinDriver struct { const ( // BLE services - //ioPinService = "e95d127b251d470aa062fa1922dfa9a8" + // ioPinService = "e95d127b251d470aa062fa1922dfa9a8" // BLE characteristics pinDataCharacteristic = "e95d8d00251d470aa062fa1922dfa9a8" diff --git a/platforms/microbit/io_pin_driver_test.go b/platforms/microbit/io_pin_driver_test.go index ace606c7d..e04eb1faa 100644 --- a/platforms/microbit/io_pin_driver_test.go +++ b/platforms/microbit/io_pin_driver_test.go @@ -15,9 +15,11 @@ import ( var _ gobot.Driver = (*IOPinDriver)(nil) // that supports the DigitalReader, DigitalWriter, & AnalogReader interfaces -var _ gpio.DigitalReader = (*IOPinDriver)(nil) -var _ gpio.DigitalWriter = (*IOPinDriver)(nil) -var _ aio.AnalogReader = (*IOPinDriver)(nil) +var ( + _ gpio.DigitalReader = (*IOPinDriver)(nil) + _ gpio.DigitalWriter = (*IOPinDriver)(nil) + _ aio.AnalogReader = (*IOPinDriver)(nil) +) func initTestIOPinDriver() *IOPinDriver { d := NewIOPinDriver(NewBleTestAdaptor()) diff --git a/platforms/microbit/led_driver.go b/platforms/microbit/led_driver.go index 3c9af03de..80aca8cd8 100644 --- a/platforms/microbit/led_driver.go +++ b/platforms/microbit/led_driver.go @@ -14,7 +14,7 @@ type LEDDriver struct { const ( // BLE services - //ledService = "e95dd91d251d470aa062fa1922dfa9a8" + // ledService = "e95dd91d251d470aa062fa1922dfa9a8" // BLE characteristics ledMatrixStateCharacteristic = "e95d7b77251d470aa062fa1922dfa9a8" diff --git a/platforms/microbit/magnetometer_driver.go b/platforms/microbit/magnetometer_driver.go index c899be683..c398eddc8 100644 --- a/platforms/microbit/magnetometer_driver.go +++ b/platforms/microbit/magnetometer_driver.go @@ -29,7 +29,7 @@ type MagnetometerData struct { const ( // BLE services - //magnetometerService = "e95df2d8251d470aa062fa1922dfa9a8" + // magnetometerService = "e95df2d8251d470aa062fa1922dfa9a8" // BLE characteristics magnetometerCharacteristic = "e95dfb11251d470aa062fa1922dfa9a8" @@ -85,7 +85,8 @@ func (b *MagnetometerDriver) Start() error { result := &MagnetometerData{ X: float32(a.X) / 1000.0, Y: float32(a.Y) / 1000.0, - Z: float32(a.Z) / 1000.0} + Z: float32(a.Z) / 1000.0, + } b.Publish(b.Event(Magnetometer), result) }) diff --git a/platforms/microbit/temperature_driver.go b/platforms/microbit/temperature_driver.go index 0e7ca7ea1..7daf96077 100644 --- a/platforms/microbit/temperature_driver.go +++ b/platforms/microbit/temperature_driver.go @@ -16,7 +16,7 @@ type TemperatureDriver struct { const ( // BLE services - //temperatureService = "e95d6100251d470aa062fa1922dfa9a8" + // temperatureService = "e95d6100251d470aa062fa1922dfa9a8" // BLE characteristics temperatureCharacteristic = "e95d9250251d470aa062fa1922dfa9a8" diff --git a/platforms/mqtt/doc.go b/platforms/mqtt/doc.go index 5665a7c3f..06f3e194e 100644 --- a/platforms/mqtt/doc.go +++ b/platforms/mqtt/doc.go @@ -3,7 +3,7 @@ Package mqtt provides Gobot adaptor for the mqtt message service. Installing: - Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) + Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For further information refer to mqtt README: https://github.com/hybridgroup/gobot/blob/master/platforms/mqtt/README.md diff --git a/platforms/mqtt/mqtt_adaptor.go b/platforms/mqtt/mqtt_adaptor.go index d0889e6c2..24b412445 100644 --- a/platforms/mqtt/mqtt_adaptor.go +++ b/platforms/mqtt/mqtt_adaptor.go @@ -11,10 +11,8 @@ import ( paho "github.com/eclipse/paho.mqtt.golang" ) -var ( - // ErrNilClient is returned when a client action can't be taken because the struct has no client - ErrNilClient = fmt.Errorf("no MQTT client available") -) +// ErrNilClient is returned when a client action can't be taken because the struct has no client +var ErrNilClient = fmt.Errorf("no MQTT client available") // Message is a message received from the broker. type Message paho.Message @@ -234,5 +232,8 @@ func (a *Adaptor) newTLSConfig() *tls.Config { InsecureSkipVerify: false, // Certificates = list of certs client sends to server. Certificates: certs, + // MinVersion contains the minimum TLS version that is acceptable. + // TLS 1.2 is currently used as the minimum when acting as a client. + MinVersion: tls.VersionTLS12, } } diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index e75bc6397..3953b6189 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -18,7 +18,7 @@ const ( ) const ( - pwmDir = "/sys/devices/platform/soc/1c21400.pwm/pwm/pwmchip0/" + pwmDir = "/sys/devices/platform/soc/1c21400.pwm/pwm/pwmchip0/" //nolint:gosec // false positive pwmPwmDir = pwmDir + "pwm0/" pwmExportPath = pwmDir + "export" pwmUnexportPath = pwmDir + "unexport" @@ -47,14 +47,16 @@ var gpioMockPaths = []string{ } // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ gpio.ServoWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ gpio.ServoWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) +) func preparePwmFs(fs *system.MockFilesystem) { fs.Files[pwmEnablePath].Contents = "0" @@ -232,7 +234,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateSpiBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -261,7 +263,7 @@ func Test_validateSpiBusNumber(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -296,7 +298,7 @@ func Test_validateI2cBusNumber(t *testing.T) { } func Test_translateDigitalPin(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { access string pin string wantChip string @@ -339,7 +341,7 @@ func Test_translateDigitalPin(t *testing.T) { func Test_translatePWMPin(t *testing.T) { basePaths := []string{"/sys/devices/platform/soc/1c21400.pwm/pwm/"} - var tests = map[string]struct { + tests := map[string]struct { pin string chip string wantDir string diff --git a/platforms/nats/doc.go b/platforms/nats/doc.go index 3d3bcabd4..5628b9695 100644 --- a/platforms/nats/doc.go +++ b/platforms/nats/doc.go @@ -2,7 +2,7 @@ Package nats provides Gobot adaptor for the nats message service. Installing: - Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) + Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For further information refer to nats README: https://github.com/hybridgroup/gobot/blob/master/platforms/nats/README.md diff --git a/platforms/neurosky/neurosky_driver.go b/platforms/neurosky/neurosky_driver.go index a09328ea5..1ebe5198f 100644 --- a/platforms/neurosky/neurosky_driver.go +++ b/platforms/neurosky/neurosky_driver.go @@ -151,7 +151,7 @@ func (n *Driver) parse(buf *bytes.Buffer) error { if _, err := buf.Read(payload); err != nil { return err } - //checksum, _ := buf.ReadByte() + // checksum, _ := buf.ReadByte() buf.Next(1) if err := n.parsePacket(bytes.NewBuffer(payload)); err != nil { panic(err) @@ -183,7 +183,7 @@ func (n *Driver) parsePacket(buf *bytes.Buffer) error { n.Publish(n.Event("blink"), ret) case CodeWave: buf.Next(1) - var ret = make([]byte, 2) + ret := make([]byte, 2) if _, err := buf.Read(ret); err != nil { return err } diff --git a/platforms/neurosky/neurosky_driver_test.go b/platforms/neurosky/neurosky_driver_test.go index 6a85a44a4..d35cd819a 100644 --- a/platforms/neurosky/neurosky_driver_test.go +++ b/platforms/neurosky/neurosky_driver_test.go @@ -160,9 +160,11 @@ func TestNeuroskyDriverParse(t *testing.T) { // CodeAsicEEG go func() { time.Sleep(5 * time.Millisecond) - _ = d.parse(bytes.NewBuffer([]byte{0xAA, 0xAA, 30, 0x83, 24, 1, 121, 89, 0, + _ = d.parse(bytes.NewBuffer([]byte{ + 0xAA, 0xAA, 30, 0x83, 24, 1, 121, 89, 0, 97, 26, 0, 30, 189, 0, 57, 1, 0, 62, 160, 0, 31, 127, 0, 18, 207, 0, 13, - 108, 0x00})) + 108, 0x00, + })) }() _ = d.On(d.Event(EEG), func(data interface{}) { diff --git a/platforms/parrot/ardrone/ardrone_driver_test.go b/platforms/parrot/ardrone/ardrone_driver_test.go index 3f37b1d2d..bec2ff8e2 100644 --- a/platforms/parrot/ardrone/ardrone_driver_test.go +++ b/platforms/parrot/ardrone/ardrone_driver_test.go @@ -41,6 +41,7 @@ func TestArdroneDriverHalt(t *testing.T) { d := initTestArdroneDriver() assert.Nil(t, d.Halt()) } + func TestArdroneDriverTakeOff(t *testing.T) { d := initTestArdroneDriver() d.TakeOff() diff --git a/platforms/parrot/bebop/client/client.go b/platforms/parrot/bebop/client/client.go index 50c76bcbf..9d54c183b 100644 --- a/platforms/parrot/bebop/client/client.go +++ b/platforms/parrot/bebop/client/client.go @@ -202,9 +202,9 @@ func New() *Bebop { } } -func (b *Bebop) write(buf []byte) (int, error) { +func (b *Bebop) write(buf []byte) error { b.writeChan <- buf - return 0, nil + return nil } func (b *Bebop) Discover() error { @@ -248,13 +248,11 @@ func (b *Bebop) Discover() error { func (b *Bebop) Connect() error { err := b.Discover() - if err != nil { return err } c2daddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", b.IP, b.C2dPort)) - if err != nil { return err } @@ -266,7 +264,6 @@ func (b *Bebop) Connect() error { } d2caddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", b.D2cPort)) - if err != nil { return err } @@ -278,7 +275,6 @@ func (b *Bebop) Connect() error { go func() { for { _, err := b.c2dClient.Write(<-b.writeChan) - if err != nil { fmt.Println(err) } @@ -302,8 +298,7 @@ func (b *Bebop) Connect() error { // wait a little bit so that there is enough time to get some ACKs time.Sleep(500 * time.Millisecond) for { - _, err := b.write(b.generatePcmd().Bytes()) - if err != nil { + if err := b.write(b.generatePcmd().Bytes()); err != nil { fmt.Println("pcmd c2dClient.Write", err) } time.Sleep(25 * time.Millisecond) @@ -337,8 +332,7 @@ func (b *Bebop) FlatTrim() error { cmd.Write(tmp.Bytes()) - _, err := b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) GenerateAllStates() error { @@ -358,8 +352,7 @@ func (b *Bebop) GenerateAllStates() error { cmd.Write(tmp.Bytes()) - _, err := b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) TakeOff() error { @@ -379,8 +372,7 @@ func (b *Bebop) TakeOff() error { cmd.Write(tmp.Bytes()) - _, err := b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) Land() error { @@ -400,8 +392,7 @@ func (b *Bebop) Land() error { cmd.Write(tmp.Bytes()) - _, err := b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) Up(val int) error { @@ -558,9 +549,7 @@ func (b *Bebop) packetReceiver(buf []byte) { // if frame.Type == int(ARNETWORKAL_FRAME_TYPE_DATA_WITH_ACK) { ack := b.createAck(frame).Bytes() - _, err := b.write(ack) - - if err != nil { + if err := b.write(ack); err != nil { fmt.Println("ARNETWORKAL_FRAME_TYPE_DATA_WITH_ACK", err) } } @@ -571,8 +560,7 @@ func (b *Bebop) packetReceiver(buf []byte) { arstreamFrame := NewARStreamFrame(frame.Data) ack := b.createARStreamACK(arstreamFrame).Bytes() - _, err := b.write(ack) - if err != nil { + if err := b.write(ack); err != nil { fmt.Println("ARNETWORKAL_FRAME_TYPE_DATA_LOW_LATENCY", err) } } @@ -582,8 +570,7 @@ func (b *Bebop) packetReceiver(buf []byte) { // if frame.Id == int(ARNETWORK_MANAGER_INTERNAL_BUFFER_ID_PING) { pong := b.createPong(frame).Bytes() - _, err := b.write(pong) - if err != nil { + if err := b.write(pong); err != nil { fmt.Println("ARNETWORK_MANAGER_INTERNAL_BUFFER_ID_PING", err) } } @@ -592,15 +579,13 @@ func (b *Bebop) packetReceiver(buf []byte) { func (b *Bebop) StartRecording() error { buf := b.videoRecord(ARCOMMANDS_ARDRONE3_MEDIARECORD_VIDEO_RECORD_START) - _, err := b.write(b.networkFrameGenerator(buf, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(buf, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) StopRecording() error { buf := b.videoRecord(ARCOMMANDS_ARDRONE3_MEDIARECORD_VIDEO_RECORD_STOP) - _, err := b.write(b.networkFrameGenerator(buf, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(buf, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) videoRecord(state byte) *bytes.Buffer { @@ -665,8 +650,7 @@ func (b *Bebop) HullProtection(protect bool) error { } cmd.Write(tmp.Bytes()) - _, err := b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) Outdoor(outdoor bool) error { @@ -695,8 +679,7 @@ func (b *Bebop) Outdoor(outdoor bool) error { } cmd.Write(tmp.Bytes()) - _, err := b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) VideoEnable(enable bool) error { @@ -721,8 +704,7 @@ func (b *Bebop) VideoEnable(enable bool) error { } cmd.Write(tmp.Bytes()) - _, err := b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) VideoStreamMode(mode int8) error { @@ -747,8 +729,7 @@ func (b *Bebop) VideoStreamMode(mode int8) error { } cmd.Write(tmp.Bytes()) - _, err := b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) - return err + return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func bool2int8(b bool) int8 { @@ -834,13 +815,13 @@ func (b *Bebop) createARStreamACK(frame ARStreamFrame) *bytes.Buffer { ackPacket.Write(tmp.Bytes()) tmp = &bytes.Buffer{} - if err := binary.Write(tmp, binary.LittleEndian, uint64(b.tmpFrame.arstreamACK.HighPacketsAck)); err != nil { + if err := binary.Write(tmp, binary.LittleEndian, b.tmpFrame.arstreamACK.HighPacketsAck); err != nil { panic(err) } ackPacket.Write(tmp.Bytes()) tmp = &bytes.Buffer{} - if err := binary.Write(tmp, binary.LittleEndian, uint64(b.tmpFrame.arstreamACK.LowPacketsAck)); err != nil { + if err := binary.Write(tmp, binary.LittleEndian, b.tmpFrame.arstreamACK.LowPacketsAck); err != nil { panic(err) } ackPacket.Write(tmp.Bytes()) diff --git a/platforms/parrot/bebop/client/examples/video.go b/platforms/parrot/bebop/client/examples/video.go index 3946c42c2..0e3731f7d 100644 --- a/platforms/parrot/bebop/client/examples/video.go +++ b/platforms/parrot/bebop/client/examples/video.go @@ -53,14 +53,12 @@ func main() { ffmpeg := exec.Command("ffmpeg", "-i", "pipe:0", "http://localhost:8090/bebop.ffm") ffmpegErr, err := ffmpeg.StderrPipe() - if err != nil { fmt.Println(err) return } ffmpegIn, err := ffmpeg.StdinPipe() - if err != nil { fmt.Println(err) return diff --git a/platforms/parrot/minidrone/minidrone_driver.go b/platforms/parrot/minidrone/minidrone_driver.go index e1d3a1183..926ea0bdb 100644 --- a/platforms/parrot/minidrone/minidrone_driver.go +++ b/platforms/parrot/minidrone/minidrone_driver.go @@ -25,8 +25,8 @@ type Driver struct { const ( // BLE services - //droneCommandService = "9a66fa000800919111e4012d1540cb8e" - //droneNotificationService = "9a66fb000800919111e4012d1540cb8e" + // droneCommandService = "9a66fa000800919111e4012d1540cb8e" + // droneNotificationService = "9a66fb000800919111e4012d1540cb8e" // send characteristics pcmdCharacteristic = "9a66fa0a0800919111e4012d1540cb8e" @@ -419,7 +419,6 @@ func (b *Driver) GunControl(id uint8) error { b.stepsfa0b++ buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x10, 0x02, id, 0x00} return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) - } func (b *Driver) generateAnimation(direction int8) *bytes.Buffer { @@ -468,7 +467,7 @@ func (b *Driver) generatePcmd() *bytes.Buffer { if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Gaz)); err != nil { panic(err) } - if err := binary.Write(cmd, binary.LittleEndian, float32(pcmd.Psi)); err != nil { + if err := binary.Write(cmd, binary.LittleEndian, pcmd.Psi); err != nil { panic(err) } if err := binary.Write(cmd, binary.LittleEndian, int16(0)); err != nil { diff --git a/platforms/particle/adaptor.go b/platforms/particle/adaptor.go index dbaaf0ca9..2d6b3262f 100644 --- a/platforms/particle/adaptor.go +++ b/platforms/particle/adaptor.go @@ -182,7 +182,6 @@ func (s *Adaptor) EventStream(source string, name string) (event *gobot.Event, e func (s *Adaptor) Variable(name string) (result string, err error) { url := fmt.Sprintf("%v/%s?access_token=%s", s.deviceURL(), name, s.AccessToken) resp, err := s.request("GET", url, nil) - if err != nil { return } @@ -245,9 +244,9 @@ func (s *Adaptor) request(method string, url string, params url.Values) (m map[s var resp *http.Response if method == "POST" { - resp, err = http.PostForm(url, params) + resp, err = http.PostForm(url, params) //nolint:gosec // accepted, because local function and no exposed routing } else if method == "GET" { - resp, err = http.Get(url) + resp, err = http.Get(url) //nolint:gosec // accepted, because local function and no exposed routing } if err != nil { @@ -255,7 +254,6 @@ func (s *Adaptor) request(method string, url string, params url.Values) (m map[s } buf, err := io.ReadAll(resp.Body) - if err != nil { return } diff --git a/platforms/pebble/pebble_adaptor_test.go b/platforms/pebble/pebble_adaptor_test.go index e15597863..23e2488a5 100644 --- a/platforms/pebble/pebble_adaptor_test.go +++ b/platforms/pebble/pebble_adaptor_test.go @@ -17,6 +17,7 @@ func TestAdaptor(t *testing.T) { a := initTestAdaptor() assert.Equal(t, "Pebble", a.Name()) } + func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() assert.Nil(t, a.Connect()) diff --git a/platforms/raspi/pwm_pin.go b/platforms/raspi/pwm_pin.go index 366ca698d..05f49a952 100644 --- a/platforms/raspi/pwm_pin.go +++ b/platforms/raspi/pwm_pin.go @@ -107,7 +107,7 @@ func (p *PWMPin) SetDutyCycle(duty uint32) error { } func (p *PWMPin) writeValue(data string) (err error) { - fi, err := p.sys.OpenFile(p.path, os.O_WRONLY|os.O_APPEND, 0644) + fi, err := p.sys.OpenFile(p.path, os.O_WRONLY|os.O_APPEND, 0o644) defer fi.Close() //nolint:staticcheck // for historical reasons if err != nil { diff --git a/platforms/raspi/raspi_adaptor.go b/platforms/raspi/raspi_adaptor.go index 19414926a..2d915d550 100644 --- a/platforms/raspi/raspi_adaptor.go +++ b/platforms/raspi/raspi_adaptor.go @@ -5,7 +5,6 @@ import ( "fmt" "strconv" "strings" - "sync" multierror "github.com/hashicorp/go-multierror" @@ -209,7 +208,7 @@ func (c *Adaptor) readRevision() string { } for _, v := range strings.Split(string(content), "\n") { if strings.Contains(v, "Revision") { - s := strings.Split(string(v), " ") + s := strings.Split(v, " ") version, _ := strconv.ParseInt("0x"+s[len(s)-1], 0, 64) if version <= 3 { c.revision = "1" diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index f73e3f2df..17cbb5b03 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -2,12 +2,11 @@ package raspi import ( "fmt" - "strings" - "testing" - "runtime" "strconv" + "strings" "sync" + "testing" "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" @@ -18,15 +17,17 @@ import ( ) // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ gpio.ServoWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) -var _ spi.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ gpio.ServoWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) + _ spi.Connector = (*Adaptor)(nil) +) func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system.MockFilesystem) { a := NewAdaptor() @@ -45,7 +46,7 @@ func TestName(t *testing.T) { func TestGetDefaultBus(t *testing.T) { const contentPattern = "Hardware : BCM2708\n%sSerial : 000000003bc748ea\n" - var tests = map[string]struct { + tests := map[string]struct { revisionPart string wantRev string wantBus int @@ -77,9 +78,9 @@ func TestGetDefaultBus(t *testing.T) { fs := a.sys.UseMockFilesystem([]string{infoFile}) fs.Files[infoFile].Contents = fmt.Sprintf(contentPattern, tc.revisionPart) assert.Equal(t, "", a.revision) - //act, will read and refresh the revision + // act, will read and refresh the revision gotBus := a.DefaultI2cBus() - //assert + // assert assert.Equal(t, tc.wantRev, a.revision) assert.Equal(t, tc.wantBus, gotBus) }) @@ -274,7 +275,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateSpiBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -306,7 +307,7 @@ func Test_validateSpiBusNumber(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ diff --git a/platforms/rockpi/rockpi_adaptor_test.go b/platforms/rockpi/rockpi_adaptor_test.go index 121777a13..9d1d590e8 100644 --- a/platforms/rockpi/rockpi_adaptor_test.go +++ b/platforms/rockpi/rockpi_adaptor_test.go @@ -21,7 +21,7 @@ func TestDefaultI2cBus(t *testing.T) { } func Test_getPinTranslatorFunction(t *testing.T) { - var cases = map[string]struct { + cases := map[string]struct { pin string model string expectedLine int @@ -71,7 +71,7 @@ func Test_getPinTranslatorFunction(t *testing.T) { } func Test_validateSpiBusNumber(t *testing.T) { - var cases = map[string]struct { + cases := map[string]struct { busNr int expectedErr error }{ @@ -103,7 +103,7 @@ func Test_validateSpiBusNumber(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var cases = map[string]struct { + cases := map[string]struct { busNr int wantErr error }{ diff --git a/platforms/sphero/ollie/ollie_driver.go b/platforms/sphero/ollie/ollie_driver.go index eb4f29a18..4ef37d836 100644 --- a/platforms/sphero/ollie/ollie_driver.go +++ b/platforms/sphero/ollie/ollie_driver.go @@ -29,8 +29,8 @@ type Driver struct { const ( // bluetooth service IDs - //spheroBLEService = "22bb746f2bb075542d6f726568705327" - //robotControlService = "22bb746f2ba075542d6f726568705327" + // spheroBLEService = "22bb746f2bb075542d6f726568705327" + // robotControlService = "22bb746f2ba075542d6f726568705327" // BLE characteristic IDs wakeCharacteristic = "22bb746f2bbf75542d6f726568705327" @@ -214,16 +214,15 @@ func (b *Driver) SetTXPower(level int) error { // HandleResponses handles responses returned from Ollie func (b *Driver) HandleResponses(data []byte, e error) { - - //since packets can only be 20 bytes long, we have to puzzle them together + // since packets can only be 20 bytes long, we have to puzzle them together newMessage := false - //append message parts to existing + // append message parts to existing if len(data) > 0 && data[0] != 0xFF { b.asyncBuffer = append(b.asyncBuffer, data...) } - //clear message when new one begins (first byte is always 0xFF) + // clear message when new one begins (first byte is always 0xFF) if len(data) > 0 && data[0] == 0xFF { b.asyncMessage = b.asyncBuffer b.asyncBuffer = data @@ -231,14 +230,14 @@ func (b *Driver) HandleResponses(data []byte, e error) { } parts := b.asyncMessage - //3 is the id of data streaming, located at index 2 byte + // 3 is the id of data streaming, located at index 2 byte if newMessage && len(parts) > 2 && parts[2] == 3 { b.handleDataStreaming(parts) } - //index 1 is the type of the message, 0xFF being a direct response, 0xFE an asynchronous message + // index 1 is the type of the message, 0xFF being a direct response, 0xFE an asynchronous message if len(data) > 4 && data[1] == 0xFF && data[0] == 0xFF { - //locator request + // locator request if data[4] == 0x0B && len(data) == 16 { b.handleLocatorDetected(data) } @@ -253,14 +252,14 @@ func (b *Driver) HandleResponses(data []byte, e error) { // GetLocatorData calls the passed function with the data from the locator func (b *Driver) GetLocatorData(f func(p Point2D)) { - //CID 0x15 is the code for the locator request + // CID 0x15 is the code for the locator request b.PacketChannel() <- b.craftPacket([]uint8{}, 0x02, 0x15) b.locatorCallback = f } // GetPowerState calls the passed function with the Power State information from the sphero func (b *Driver) GetPowerState(f func(p PowerStatePacket)) { - //CID 0x20 is the code for the power state + // CID 0x20 is the code for the power state b.PacketChannel() <- b.craftPacket([]uint8{}, 0x00, 0x20) b.powerstateCallback = f } @@ -271,8 +270,8 @@ func (b *Driver) handleDataStreaming(data []byte) { return } - //data packet is the same as for the normal sphero, since the same communication api is used - //only difference in communication is that the "newer" spheros use BLE for communinations + // data packet is the same as for the normal sphero, since the same communication api is used + // only difference in communication is that the "newer" spheros use BLE for communinations var dataPacket DataStreamingPacket buffer := bytes.NewBuffer(data[5:]) // skip header if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { @@ -387,7 +386,6 @@ func (b *Driver) craftPacket(body []uint8, did byte, cid byte) *Packet { } func (b *Driver) handlePowerStateDetected(data []uint8) { - var dataPacket PowerStatePacket buffer := bytes.NewBuffer(data[5:]) // skip header if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { @@ -398,11 +396,11 @@ func (b *Driver) handlePowerStateDetected(data []uint8) { } func (b *Driver) handleLocatorDetected(data []uint8) { - //read the unsigned raw values + // read the unsigned raw values ux := binary.BigEndian.Uint16(data[5:7]) uy := binary.BigEndian.Uint16(data[7:9]) - //convert to signed values + // convert to signed values var x, y int16 if ux > 32255 { @@ -417,7 +415,7 @@ func (b *Driver) handleLocatorDetected(data []uint8) { y = int16(uy) } - //create point obj + // create point obj p := new(Point2D) p.X = x p.Y = y @@ -428,7 +426,6 @@ func (b *Driver) handleLocatorDetected(data []uint8) { } func (b *Driver) handleCollisionDetected(data []uint8) { - if len(data) == ResponsePacketMaxSize { // Check if this is the header of collision response. (i.e. first part of data) // Collision response is 22 bytes long. (individual packet size is maxed at 20) diff --git a/platforms/sphero/ollie/ollie_driver_test.go b/platforms/sphero/ollie/ollie_driver_test.go index 472cc55bf..4eecfee7a 100644 --- a/platforms/sphero/ollie/ollie_driver_test.go +++ b/platforms/sphero/ollie/ollie_driver_test.go @@ -49,7 +49,7 @@ func TestLocatorData(t *testing.T) { } for _, point := range tables { - //0x0B is the locator ID + // 0x0B is the locator ID packet := []byte{0xFF, 0xFF, 0x00, 0x00, 0x0B, point.x1, point.x2, point.y1, point.y2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} d.GetLocatorData(func(p Point2D) { @@ -72,8 +72,9 @@ func TestDataStreaming(t *testing.T) { response = true }) - //example data packet - p1 := []string{"FFFE030053000A003900FAFFFE0007FFFF000000", + // example data packet + p1 := []string{ + "FFFE030053000A003900FAFFFE0007FFFF000000", "000000000000000000FFECFFFB00010000004B01", "BD1034FFFF000300000000000000000000000000", "0000002701FDE500560000000000000065000000", @@ -92,10 +93,10 @@ func TestDataStreaming(t *testing.T) { } - //send empty packet to indicate start of next message + // send empty packet to indicate start of next message d.HandleResponses([]byte{0xFF}, nil) time.Sleep(10 * time.Millisecond) if response == false { - t.Error("no response recieved") + t.Error("no response received") } } diff --git a/platforms/sphero/ollie/ollie_packets.go b/platforms/sphero/ollie/ollie_packets.go index 06c43e34f..673c18954 100644 --- a/platforms/sphero/ollie/ollie_packets.go +++ b/platforms/sphero/ollie/ollie_packets.go @@ -24,7 +24,7 @@ type PowerStatePacket struct { BattVoltage uint16 // Number of charges in the total lifetime of the sphero NumCharges uint16 - //Seconds awake since last charge + // Seconds awake since last charge TimeSinceChg uint16 } diff --git a/platforms/sphero/sphero_driver.go b/platforms/sphero/sphero_driver.go index e1f568a98..b2e9d48ae 100644 --- a/platforms/sphero/sphero_driver.go +++ b/platforms/sphero/sphero_driver.go @@ -403,7 +403,7 @@ func (s *SpheroDriver) getSyncResponse(packet *packet) []byte { return []byte{} } -func (s *SpheroDriver) craftPacket(body []uint8, did byte, cid byte) *packet { +func (s *SpheroDriver) craftPacket(body []uint8, did byte, cid byte) *packet { //nolint:unparam // keep did as parameter s.mtx.Lock() defer s.mtx.Unlock() packet := new(packet) diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 9509388e7..02ce04c1d 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -18,7 +18,7 @@ const ( ) const ( - pwmDir = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip2/" + pwmDir = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip2/" //nolint:gosec // false positive pwmPwmDir = pwmDir + "pwm0/" pwmExportPath = pwmDir + "export" pwmUnexportPath = pwmDir + "unexport" @@ -47,14 +47,16 @@ var gpioMockPaths = []string{ } // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ gpio.ServoWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ gpio.ServoWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) +) func preparePwmFs(fs *system.MockFilesystem) { fs.Files[pwmEnablePath].Contents = "0" @@ -232,7 +234,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateSpiBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -268,7 +270,7 @@ func Test_validateSpiBusNumber(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -309,7 +311,7 @@ func Test_validateI2cBusNumber(t *testing.T) { } func Test_translateDigitalPin(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { access string pin string wantChip string @@ -355,7 +357,7 @@ func Test_translatePWMPin(t *testing.T) { "/sys/devices/platform/ff680020.pwm/pwm/", "/sys/devices/platform/ff680030.pwm/pwm/", } - var tests = map[string]struct { + tests := map[string]struct { pin string chip string wantDir string diff --git a/platforms/upboard/up2/adaptor.go b/platforms/upboard/up2/adaptor.go index 19478ab27..5f0360b00 100644 --- a/platforms/upboard/up2/adaptor.go +++ b/platforms/upboard/up2/adaptor.go @@ -125,7 +125,7 @@ func (c *Adaptor) DigitalWrite(id string, val byte) error { // is it one of the built-in LEDs? if id == LEDRed || id == LEDBlue || id == LEDGreen || id == LEDYellow { pinPath := fmt.Sprintf(c.ledPath, id) - fi, err := c.sys.OpenFile(pinPath, os.O_WRONLY|os.O_APPEND, 0666) + fi, err := c.sys.OpenFile(pinPath, os.O_WRONLY|os.O_APPEND, 0o666) defer fi.Close() //nolint:staticcheck // for historical reasons if err != nil { return err @@ -170,5 +170,4 @@ func (c *Adaptor) translatePWMPin(id string) (string, int, error) { return "", -1, fmt.Errorf("'%s' is not a valid id for a PWM pin", id) } return "/sys/class/pwm/pwmchip0", sysPin.pwmPin, nil - } diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index 998df6882..d81836dcc 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -14,15 +14,17 @@ import ( ) // make sure that this Adaptor fulfills all the required interfaces -var _ gobot.Adaptor = (*Adaptor)(nil) -var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) -var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) -var _ gpio.DigitalReader = (*Adaptor)(nil) -var _ gpio.DigitalWriter = (*Adaptor)(nil) -var _ gpio.PwmWriter = (*Adaptor)(nil) -var _ gpio.ServoWriter = (*Adaptor)(nil) -var _ i2c.Connector = (*Adaptor)(nil) -var _ spi.Connector = (*Adaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) + _ gobot.PWMPinnerProvider = (*Adaptor)(nil) + _ gpio.DigitalReader = (*Adaptor)(nil) + _ gpio.DigitalWriter = (*Adaptor)(nil) + _ gpio.PwmWriter = (*Adaptor)(nil) + _ gpio.ServoWriter = (*Adaptor)(nil) + _ i2c.Connector = (*Adaptor)(nil) + _ spi.Connector = (*Adaptor)(nil) +) var pwmMockPaths = []string{ "/sys/class/pwm/pwmchip0/export", @@ -141,7 +143,7 @@ func TestSpiDefaultValues(t *testing.T) { } func Test_validateSpiBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -195,7 +197,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { } func Test_validateI2cBusNumber(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { busNr int wantErr error }{ @@ -231,7 +233,7 @@ func Test_validateI2cBusNumber(t *testing.T) { } func Test_translatePWMPin(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { wantDir string wantChannel int wantErr error diff --git a/robot.go b/robot.go index 6aa1283bf..647cd8b77 100644 --- a/robot.go +++ b/robot.go @@ -5,9 +5,8 @@ import ( "log" "os" "os/signal" - "sync/atomic" - "sync" + "sync/atomic" multierror "github.com/hashicorp/go-multierror" ) @@ -103,10 +102,10 @@ func (r *Robots) Each(f func(*Robot)) { // NewRobot returns a new Robot. It supports the following optional params: // -// name: string with the name of the Robot. A name will be automatically generated if no name is supplied. -// []Connection: Connections which are automatically started and stopped with the robot -// []Device: Devices which are automatically started and stopped with the robot -// func(): The work routine the robot will execute once all devices and connections have been initialized and started +// name: string with the name of the Robot. A name will be automatically generated if no name is supplied. +// []Connection: Connections which are automatically started and stopped with the robot +// []Device: Devices which are automatically started and stopped with the robot +// func(): The work routine the robot will execute once all devices and connections have been initialized and started func NewRobot(v ...interface{}) *Robot { r := &Robot{ Name: fmt.Sprintf("%X", Rand(int(^uint(0)>>1))), diff --git a/robot_test.go b/robot_test.go index 4d34634f6..5f7e69ced 100644 --- a/robot_test.go +++ b/robot_test.go @@ -47,11 +47,11 @@ func TestRobotStart(t *testing.T) { func TestRobotStartAutoRun(t *testing.T) { adaptor1 := newTestAdaptor("Connection1", "/dev/null") driver1 := newTestDriver(adaptor1, "Device1", "0") - //work := func() {} + // work := func() {} r := NewRobot("autorun", []Connection{adaptor1}, []Device{driver1}, - //work, + // work, ) go func() { diff --git a/robot_work.go b/robot_work.go index 516b3a59d..b3a4e4ac7 100644 --- a/robot_work.go +++ b/robot_work.go @@ -3,9 +3,8 @@ package gobot import ( "context" "fmt" - "time" - "sync" + "time" "github.com/gofrs/uuid" ) @@ -30,7 +29,7 @@ const ( // // someWork := myRobot.Every(context.Background(), time.Second * 2, func(){ // fmt.Println("Here I am doing work") -// }) +// }) // // someWork.CallCancelFunc() // Cancel next tick and remove from work registry // @@ -38,7 +37,7 @@ const ( // // someWork2 := myRobot.Every(context.Background(), time.Second * 2, func(){ // fmt.Println("Here I am doing more work") -// }) +// }) // // somework2.CallCancelFunc() // diff --git a/robot_work_test.go b/robot_work_test.go index 36ed3b4bd..53f401033 100644 --- a/robot_work_test.go +++ b/robot_work_test.go @@ -3,7 +3,6 @@ package gobot import ( "context" "testing" - "time" "github.com/gofrs/uuid" diff --git a/system/digitalpin_access.go b/system/digitalpin_access.go index f5d29befb..9ba351338 100644 --- a/system/digitalpin_access.go +++ b/system/digitalpin_access.go @@ -23,7 +23,8 @@ func (h *sysfsDigitalPinAccess) isSupported() bool { } func (h *sysfsDigitalPinAccess) createPin(chip string, pin int, - o ...func(gobot.DigitalPinOptioner) bool) gobot.DigitalPinner { + o ...func(gobot.DigitalPinOptioner) bool, +) gobot.DigitalPinner { return newDigitalPinSysfs(h.fs, strconv.Itoa(pin), o...) } @@ -41,7 +42,8 @@ func (h *gpiodDigitalPinAccess) isSupported() bool { } func (h *gpiodDigitalPinAccess) createPin(chip string, pin int, - o ...func(gobot.DigitalPinOptioner) bool) gobot.DigitalPinner { + o ...func(gobot.DigitalPinOptioner) bool, +) gobot.DigitalPinner { return newDigitalPinGpiod(chip, pin, o...) } diff --git a/system/digitalpin_access_test.go b/system/digitalpin_access_test.go index 58e5f4292..beda36d0c 100644 --- a/system/digitalpin_access_test.go +++ b/system/digitalpin_access_test.go @@ -16,7 +16,7 @@ func Test_isSupportedSysfs(t *testing.T) { } func Test_isSupportedGpiod(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { mockPaths []string want bool }{ diff --git a/system/digitalpin_bench_test.go b/system/digitalpin_bench_test.go index eb60722c6..c89a65c71 100644 --- a/system/digitalpin_bench_test.go +++ b/system/digitalpin_bench_test.go @@ -20,5 +20,4 @@ func BenchmarkDigitalRead(b *testing.B) { for i := 0; i < b.N; i++ { _, _ = pin.Read() } - } diff --git a/system/digitalpin_config.go b/system/digitalpin_config.go index c576eabd2..26d8bafaf 100644 --- a/system/digitalpin_config.go +++ b/system/digitalpin_config.go @@ -115,7 +115,8 @@ func WithPinDebounce(period time.Duration) func(gobot.DigitalPinOptioner) bool { // WithPinEventOnFallingEdge initializes the input pin for edge detection and call the event handler on falling edges. func WithPinEventOnFallingEdge(handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, - lseqno uint32)) func(gobot.DigitalPinOptioner) bool { + lseqno uint32), +) func(gobot.DigitalPinOptioner) bool { return func(d gobot.DigitalPinOptioner) bool { return d.SetEventHandlerForEdge(handler, digitalPinEventOnFallingEdge) } @@ -123,7 +124,8 @@ func WithPinEventOnFallingEdge(handler func(lineOffset int, timestamp time.Durat // WithPinEventOnRisingEdge initializes the input pin for edge detection and call the event handler on rising edges. func WithPinEventOnRisingEdge(handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, - lseqno uint32)) func(gobot.DigitalPinOptioner) bool { + lseqno uint32), +) func(gobot.DigitalPinOptioner) bool { return func(d gobot.DigitalPinOptioner) bool { return d.SetEventHandlerForEdge(handler, digitalPinEventOnRisingEdge) } @@ -131,7 +133,8 @@ func WithPinEventOnRisingEdge(handler func(lineOffset int, timestamp time.Durati // WithPinEventOnBothEdges initializes the input pin for edge detection and call the event handler on all edges. func WithPinEventOnBothEdges(handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, - lseqno uint32)) func(gobot.DigitalPinOptioner) bool { + lseqno uint32), +) func(gobot.DigitalPinOptioner) bool { return func(d gobot.DigitalPinOptioner) bool { return d.SetEventHandlerForEdge(handler, digitalPinEventOnBothEdges) } diff --git a/system/digitalpin_config_test.go b/system/digitalpin_config_test.go index 808286333..be73c5190 100644 --- a/system/digitalpin_config_test.go +++ b/system/digitalpin_config_test.go @@ -39,7 +39,7 @@ func TestWithPinLabel(t *testing.T) { oldLabel = "old label" newLabel = "my optional label" ) - var tests = map[string]struct { + tests := map[string]struct { setLabel string want bool }{ @@ -70,7 +70,7 @@ func TestWithPinDirectionOutput(t *testing.T) { oldVal = 3 newVal = 5 ) - var tests = map[string]struct { + tests := map[string]struct { oldDir string want bool wantVal int @@ -100,7 +100,7 @@ func TestWithPinDirectionOutput(t *testing.T) { } func TestWithPinDirectionInput(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { oldDir string want bool }{ @@ -128,7 +128,7 @@ func TestWithPinDirectionInput(t *testing.T) { } func TestWithPinActiveLow(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { oldActiveLow bool want bool }{ @@ -154,7 +154,7 @@ func TestWithPinActiveLow(t *testing.T) { } func TestWithPinPullDown(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { oldBias int want bool wantVal int @@ -181,7 +181,7 @@ func TestWithPinPullDown(t *testing.T) { } func TestWithPinPullUp(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { oldBias int want bool wantVal int @@ -208,7 +208,7 @@ func TestWithPinPullUp(t *testing.T) { } func TestWithPinOpenDrain(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { oldDrive int want bool wantVal int @@ -239,7 +239,7 @@ func TestWithPinOpenDrain(t *testing.T) { } func TestWithPinOpenSource(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { oldDrive int want bool wantVal int @@ -274,7 +274,7 @@ func TestWithPinDebounce(t *testing.T) { oldVal = time.Duration(10) newVal = time.Duration(14) ) - var tests = map[string]struct { + tests := map[string]struct { oldDebouncePeriod time.Duration want bool wantVal time.Duration @@ -305,7 +305,7 @@ func TestWithPinEventOnFallingEdge(t *testing.T) { oldVal = digitalPinEventNone newVal = digitalPinEventOnFallingEdge ) - var tests = map[string]struct { + tests := map[string]struct { oldEdge int want bool wantVal int @@ -343,7 +343,7 @@ func TestWithPinEventOnRisingEdge(t *testing.T) { oldVal = digitalPinEventNone newVal = digitalPinEventOnRisingEdge ) - var tests = map[string]struct { + tests := map[string]struct { oldEdge int want bool wantVal int @@ -381,7 +381,7 @@ func TestWithPinEventOnBothEdges(t *testing.T) { oldVal = digitalPinEventNone newVal = digitalPinEventOnBothEdges ) - var tests = map[string]struct { + tests := map[string]struct { oldEdge int want bool wantVal int diff --git a/system/digitalpin_gpiod.go b/system/digitalpin_gpiod.go index 1c5497b5e..df913cad1 100644 --- a/system/digitalpin_gpiod.go +++ b/system/digitalpin_gpiod.go @@ -28,24 +28,36 @@ type digitalPinGpiod struct { var digitalPinGpiodReconfigure = digitalPinGpiodReconfigureLine // to allow unit testing -var digitalPinGpiodUsed = map[bool]string{true: "used", false: "unused"} -var digitalPinGpiodActiveLow = map[bool]string{true: "low", false: "high"} -var digitalPinGpiodDebounced = map[bool]string{true: "debounced", false: "not debounced"} +var ( + digitalPinGpiodUsed = map[bool]string{true: "used", false: "unused"} + digitalPinGpiodActiveLow = map[bool]string{true: "low", false: "high"} + digitalPinGpiodDebounced = map[bool]string{true: "debounced", false: "not debounced"} +) -var digitalPinGpiodDirection = map[gpiod.LineDirection]string{gpiod.LineDirectionUnknown: "unknown direction", - gpiod.LineDirectionInput: "input", gpiod.LineDirectionOutput: "output"} +var digitalPinGpiodDirection = map[gpiod.LineDirection]string{ + gpiod.LineDirectionUnknown: "unknown direction", + gpiod.LineDirectionInput: "input", gpiod.LineDirectionOutput: "output", +} -var digitalPinGpiodDrive = map[gpiod.LineDrive]string{gpiod.LineDrivePushPull: "push-pull", gpiod.LineDriveOpenDrain: "open-drain", - gpiod.LineDriveOpenSource: "open-source"} +var digitalPinGpiodDrive = map[gpiod.LineDrive]string{ + gpiod.LineDrivePushPull: "push-pull", gpiod.LineDriveOpenDrain: "open-drain", + gpiod.LineDriveOpenSource: "open-source", +} -var digitalPinGpiodBias = map[gpiod.LineBias]string{gpiod.LineBiasUnknown: "unknown", gpiod.LineBiasDisabled: "disabled", - gpiod.LineBiasPullUp: "pull-up", gpiod.LineBiasPullDown: "pull-down"} +var digitalPinGpiodBias = map[gpiod.LineBias]string{ + gpiod.LineBiasUnknown: "unknown", gpiod.LineBiasDisabled: "disabled", + gpiod.LineBiasPullUp: "pull-up", gpiod.LineBiasPullDown: "pull-down", +} -var digitalPinGpiodEdgeDetect = map[gpiod.LineEdge]string{gpiod.LineEdgeNone: "no", gpiod.LineEdgeRising: "rising", - gpiod.LineEdgeFalling: "falling", gpiod.LineEdgeBoth: "both"} +var digitalPinGpiodEdgeDetect = map[gpiod.LineEdge]string{ + gpiod.LineEdgeNone: "no", gpiod.LineEdgeRising: "rising", + gpiod.LineEdgeFalling: "falling", gpiod.LineEdgeBoth: "both", +} -var digitalPinGpiodEventClock = map[gpiod.LineEventClock]string{gpiod.LineEventClockMonotonic: "monotonic", - gpiod.LineEventClockRealtime: "realtime"} +var digitalPinGpiodEventClock = map[gpiod.LineEventClock]string{ + gpiod.LineEventClockMonotonic: "monotonic", + gpiod.LineEventClockRealtime: "realtime", +} // newDigitalPinGpiod returns a digital pin given the pin number, with the label "gobotio" followed by the pin number. // The pin label can be modified optionally. The pin is handled by the character device Kernel ABI. @@ -53,7 +65,7 @@ func newDigitalPinGpiod(chipName string, pin int, options ...func(gobot.DigitalP if chipName == "" { chipName = "gpiochip0" } - cfg := newDigitalPinConfig("gobotio"+strconv.Itoa(int(pin)), options...) + cfg := newDigitalPinConfig("gobotio"+strconv.Itoa(pin), options...) d := &digitalPinGpiod{ chipName: chipName, pin: pin, @@ -218,7 +230,7 @@ func digitalPinGpiodReconfigureLine(d *digitalPinGpiod, forceInput bool) error { } } else { if systemGpiodDebug { - log.Printf("ouput (%s): ini-state %d, drive %d, inverse %t, bias %d", + log.Printf("output (%s): ini-state %d, drive %d, inverse %t, bias %d", id, d.outInitialState, d.drive, d.activeLow, d.bias) } opts = append(opts, gpiod.AsOutput(d.outInitialState)) diff --git a/system/digitalpin_gpiod_test.go b/system/digitalpin_gpiod_test.go index 78e69f78a..04f8bdd61 100644 --- a/system/digitalpin_gpiod_test.go +++ b/system/digitalpin_gpiod_test.go @@ -8,10 +8,12 @@ import ( "gobot.io/x/gobot/v2" ) -var _ gobot.DigitalPinner = (*digitalPinGpiod)(nil) -var _ gobot.DigitalPinValuer = (*digitalPinGpiod)(nil) -var _ gobot.DigitalPinOptioner = (*digitalPinGpiod)(nil) -var _ gobot.DigitalPinOptionApplier = (*digitalPinGpiod)(nil) +var ( + _ gobot.DigitalPinner = (*digitalPinGpiod)(nil) + _ gobot.DigitalPinValuer = (*digitalPinGpiod)(nil) + _ gobot.DigitalPinOptioner = (*digitalPinGpiod)(nil) + _ gobot.DigitalPinOptionApplier = (*digitalPinGpiod)(nil) +) func Test_newDigitalPinGpiod(t *testing.T) { // arrange @@ -44,7 +46,7 @@ func Test_newDigitalPinGpiodWithOptions(t *testing.T) { } func TestApplyOptions(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { changed []bool simErr error wantReconfigured int @@ -113,7 +115,7 @@ func TestApplyOptions(t *testing.T) { } func TestExport(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { simErr error wantReconfigured int wantErr error @@ -154,7 +156,7 @@ func TestExport(t *testing.T) { } func TestUnexport(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { simNoLine bool simReconfErr error simCloseErr error @@ -216,7 +218,7 @@ func TestUnexport(t *testing.T) { } func TestWrite(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { val int simErr error want int @@ -265,7 +267,7 @@ func TestWrite(t *testing.T) { } func TestRead(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { simVal int simErr error wantErr []string diff --git a/system/digitalpin_mock.go b/system/digitalpin_mock.go index c2e8d2fd2..440df69ea 100644 --- a/system/digitalpin_mock.go +++ b/system/digitalpin_mock.go @@ -13,7 +13,8 @@ type digitalPinMock struct{} func (h *mockDigitalPinAccess) isSupported() bool { return true } func (h *mockDigitalPinAccess) createPin(chip string, pin int, - o ...func(gobot.DigitalPinOptioner) bool) gobot.DigitalPinner { + o ...func(gobot.DigitalPinOptioner) bool, +) gobot.DigitalPinner { dpm := &digitalPinMock{} return dpm } diff --git a/system/digitalpin_sysfs.go b/system/digitalpin_sysfs.go index b716ff639..f29a4157e 100644 --- a/system/digitalpin_sysfs.go +++ b/system/digitalpin_sysfs.go @@ -68,7 +68,7 @@ func (d *digitalPinSysfs) Export() error { // Unexport release the pin func (d *digitalPinSysfs) Unexport() error { - unexport, err := d.fs.openFile(gpioPath+"/unexport", os.O_WRONLY, 0644) + unexport, err := d.fs.openFile(gpioPath+"/unexport", os.O_WRONLY, 0o644) if err != nil { return err } @@ -115,7 +115,7 @@ func (d *digitalPinSysfs) Read() (int, error) { } func (d *digitalPinSysfs) reconfigure() error { - exportFile, err := d.fs.openFile(gpioPath+"/export", os.O_WRONLY, 0644) + exportFile, err := d.fs.openFile(gpioPath+"/export", os.O_WRONLY, 0o644) if err != nil { return err } @@ -137,7 +137,7 @@ func (d *digitalPinSysfs) reconfigure() error { attempt := 0 for { attempt++ - d.dirFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/direction", gpioPath, d.label), os.O_RDWR, 0644) + d.dirFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/direction", gpioPath, d.label), os.O_RDWR, 0o644) if err == nil { break } @@ -151,7 +151,7 @@ func (d *digitalPinSysfs) reconfigure() error { d.valFile.Close() } if err == nil { - d.valFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/value", gpioPath, d.label), os.O_RDWR, 0644) + d.valFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/value", gpioPath, d.label), os.O_RDWR, 0o644) } // configure direction @@ -162,7 +162,7 @@ func (d *digitalPinSysfs) reconfigure() error { // configure inverse logic if err == nil { if d.activeLow { - d.activeLowFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/active_low", gpioPath, d.label), os.O_RDWR, 0644) + d.activeLowFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/active_low", gpioPath, d.label), os.O_RDWR, 0o644) if err == nil { _, err = writeFile(d.activeLowFile, []byte("1")) } diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index 5c2fe57b0..4079a45da 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -9,10 +9,12 @@ import ( "gobot.io/x/gobot/v2" ) -var _ gobot.DigitalPinner = (*digitalPinSysfs)(nil) -var _ gobot.DigitalPinValuer = (*digitalPinSysfs)(nil) -var _ gobot.DigitalPinOptioner = (*digitalPinSysfs)(nil) -var _ gobot.DigitalPinOptionApplier = (*digitalPinSysfs)(nil) +var ( + _ gobot.DigitalPinner = (*digitalPinSysfs)(nil) + _ gobot.DigitalPinValuer = (*digitalPinSysfs)(nil) + _ gobot.DigitalPinOptioner = (*digitalPinSysfs)(nil) + _ gobot.DigitalPinOptionApplier = (*digitalPinSysfs)(nil) +) func initTestDigitalPinSysFsWithMockedFilesystem(mockPaths []string) (*digitalPinSysfs, *MockFilesystem) { fs := newMockFilesystem(mockPaths) diff --git a/system/fs.go b/system/fs.go index ad7edccf3..2bdfd365d 100644 --- a/system/fs.go +++ b/system/fs.go @@ -35,7 +35,6 @@ func (fs *nativeFilesystem) find(baseDir string, pattern string) ([]string, erro for _, item := range items { if reg.MatchString(item.Name()) { found = append(found, path.Join(baseDir, item.Name())) - } } return found, nil diff --git a/system/fs_mock.go b/system/fs_mock.go index 197bad026..f7f1a5f1f 100644 --- a/system/fs_mock.go +++ b/system/fs_mock.go @@ -9,8 +9,10 @@ import ( "time" ) -var _ File = (*MockFile)(nil) -var _ filesystem = (*MockFilesystem)(nil) +var ( + _ File = (*MockFile)(nil) + _ filesystem = (*MockFilesystem)(nil) +) // MockFilesystem represents a filesystem of mock files. type MockFilesystem struct { diff --git a/system/fs_mock_test.go b/system/fs_mock_test.go index 40202c980..dca212b19 100644 --- a/system/fs_mock_test.go +++ b/system/fs_mock_test.go @@ -12,18 +12,18 @@ func TestMockFilesystemOpen(t *testing.T) { f1 := fs.Files["foo"] assert.False(t, f1.Opened) - f2, err := fs.openFile("foo", 0, 0666) + f2, err := fs.openFile("foo", 0, 0o666) assert.Equal(t, f2, f1) assert.Nil(t, err) err = f2.Sync() assert.Nil(t, err) - _, err = fs.openFile("bar", 0, 0666) + _, err = fs.openFile("bar", 0, 0o666) assert.Errorf(t, err, " : bar: no such file") fs.Add("bar") - f4, _ := fs.openFile("bar", 0, 0666) + f4, _ := fs.openFile("bar", 0, 0o666) assert.NotEqual(t, f1.Fd(), f4.Fd()) } @@ -45,7 +45,7 @@ func TestMockFilesystemStat(t *testing.T) { func TestMockFilesystemFind(t *testing.T) { // arrange fs := newMockFilesystem([]string{"/foo", "/bar/foo", "/bar/foo/baz", "/bar/baz/foo", "/bar/foo/bak"}) - var tests = map[string]struct { + tests := map[string]struct { baseDir string pattern string want []string @@ -72,7 +72,7 @@ func TestMockFilesystemWrite(t *testing.T) { fs := newMockFilesystem([]string{"bar"}) f1 := fs.Files["bar"] - f2, err := fs.openFile("bar", 0, 0666) + f2, err := fs.openFile("bar", 0, 0o666) assert.Nil(t, err) // Never been read or written. assert.True(t, f1.Seq <= 0) @@ -88,7 +88,7 @@ func TestMockFilesystemRead(t *testing.T) { f1 := fs.Files["bar"] f1.Contents = "Yip" - f2, err := fs.openFile("bar", 0, 0666) + f2, err := fs.openFile("bar", 0, 0o666) assert.Nil(t, err) // Never been read or written. assert.True(t, f1.Seq <= 0) diff --git a/system/fs_test.go b/system/fs_test.go index 0f5e4e8ad..b4e3a3152 100644 --- a/system/fs_test.go +++ b/system/fs_test.go @@ -9,7 +9,7 @@ import ( func TestFilesystemOpen(t *testing.T) { fs := &nativeFilesystem{} - file, err := fs.openFile(os.DevNull, os.O_RDONLY, 0666) + file, err := fs.openFile(os.DevNull, os.O_RDONLY, 0o666) assert.Nil(t, err) var _ File = file } diff --git a/system/i2c_device.go b/system/i2c_device.go index 9b7717527..2c2e4cba1 100644 --- a/system/i2c_device.go +++ b/system/i2c_device.go @@ -189,7 +189,7 @@ func (d *i2cDevice) WriteByteData(address int, reg uint8, val uint8) error { return err } - var data = val + data := val return d.smbusAccess(address, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, unsafe.Pointer(&data)) } @@ -202,7 +202,7 @@ func (d *i2cDevice) WriteWordData(address int, reg uint8, val uint16) error { return err } - var data = val + data := val return d.smbusAccess(address, I2C_SMBUS_WRITE, reg, I2C_SMBUS_WORD_DATA, unsafe.Pointer(&data)) } @@ -381,7 +381,7 @@ func (d *i2cDevice) syscallIoctl(signal uintptr, payload unsafe.Pointer, sender return nil } -func (d *i2cDevice) openFileLazy(sender string) (err error) { +func (d *i2cDevice) openFileLazy(sender string) (err error) { //nolint:unparam // useful for debugging // lazy initialization // note: "os.ModeExclusive" is undefined without create the file. This means for the existing character device, // a second open will not return an error e.g. due to a busy resource, so most likely "os.ModeExclusive" is not really diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index 1e5e666a1..78682ec40 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -59,7 +59,7 @@ func initTestI2cDeviceWithMockedSys() (*i2cDevice, *mockSyscall) { } func TestNewI2cDevice(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { dev string wantErr string }{ @@ -113,7 +113,7 @@ func TestWriteRead(t *testing.T) { } func TestReadByte(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { funcs uint64 syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) wantErr string @@ -157,7 +157,7 @@ func TestReadByte(t *testing.T) { } func TestReadByteData(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { funcs uint64 syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) wantErr string @@ -204,7 +204,7 @@ func TestReadByteData(t *testing.T) { } func TestReadWordData(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { funcs uint64 syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) wantErr string @@ -268,7 +268,7 @@ func TestReadBlockData(t *testing.T) { wantB8 = byte(99) wantB9 = byte(111) ) - var tests = map[string]struct { + tests := map[string]struct { funcs uint64 syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) wantErr string @@ -313,7 +313,7 @@ func TestReadBlockData(t *testing.T) { } func TestWriteByte(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { funcs uint64 syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) wantErr string @@ -355,7 +355,7 @@ func TestWriteByte(t *testing.T) { } func TestWriteByteData(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { funcs uint64 syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) wantErr string @@ -402,7 +402,7 @@ func TestWriteByteData(t *testing.T) { } func TestWriteWordData(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { funcs uint64 syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) wantErr string @@ -467,7 +467,7 @@ func TestWriteBlockData(t *testing.T) { b8 = byte(0x88) b9 = byte(0x99) ) - var tests = map[string]struct { + tests := map[string]struct { funcs uint64 syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) wantErr string @@ -528,7 +528,7 @@ func Test_setAddress(t *testing.T) { } func Test_queryFunctionality(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { requested uint64 dev string syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) diff --git a/system/pwmpin_sysfs.go b/system/pwmpin_sysfs.go index d695c6761..5950b7674 100644 --- a/system/pwmpin_sysfs.go +++ b/system/pwmpin_sysfs.go @@ -12,8 +12,8 @@ import ( const pwmDebug = false const ( - pwmPinErrorPattern = "%s() failed for id %s with %v" - pwmPinSetErrorPattern = "%s(%v) failed for id %s with %v" + pwmPinErrorPattern = "%s() failed for id %s with %v" //nolint:gosec // false positive + pwmPinSetErrorPattern = "%s(%v) failed for id %s with %v" //nolint:gosec // false positive ) // pwmPinSysFs represents a PWM pin @@ -221,7 +221,7 @@ func (p *pwmPinSysFs) pwmPolarityPath() string { } func writePwmFile(fs filesystem, path string, data []byte) (int, error) { - file, err := fs.openFile(path, os.O_WRONLY, 0644) + file, err := fs.openFile(path, os.O_WRONLY, 0o644) defer file.Close() //nolint:staticcheck // for historical reasons if err != nil { return 0, err @@ -231,7 +231,7 @@ func writePwmFile(fs filesystem, path string, data []byte) (int, error) { } func readPwmFile(fs filesystem, path string) ([]byte, error) { - file, err := fs.openFile(path, os.O_RDONLY, 0644) + file, err := fs.openFile(path, os.O_RDONLY, 0o644) defer file.Close() //nolint:staticcheck // for historical reasons if err != nil { return make([]byte, 0), err diff --git a/system/spi_access_test.go b/system/spi_access_test.go index d70be2656..e6f0266fc 100644 --- a/system/spi_access_test.go +++ b/system/spi_access_test.go @@ -16,7 +16,7 @@ func TestGpioSpi_isSupported(t *testing.T) { } func TestPeriphioSpi_isSupported(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { mockPaths []string want bool }{ diff --git a/system/syscall_mock.go b/system/syscall_mock.go index 8f00d0198..45317c97d 100644 --- a/system/syscall_mock.go +++ b/system/syscall_mock.go @@ -35,13 +35,13 @@ func (sys *mockSyscall) syscall(trap uintptr, f File, signal uintptr, payload un if sys.smbus.readWrite == I2C_SMBUS_WRITE { // get the data object payload as byte slice - sys.dataSlice = unsafe.Slice((*byte)(unsafe.Pointer(sys.smbus.data)), sys.sliceSize) + sys.dataSlice = unsafe.Slice((*byte)(sys.smbus.data), sys.sliceSize) } if sys.smbus.readWrite == I2C_SMBUS_READ { // fill data object with data from given slice to simulate reading if sys.dataSlice != nil { - slc := unsafe.Slice((*byte)(unsafe.Pointer(sys.smbus.data)), sys.sliceSize) + slc := unsafe.Slice((*byte)(sys.smbus.data), sys.sliceSize) if sys.smbus.protocol == I2C_SMBUS_BLOCK_DATA || sys.smbus.protocol == I2C_SMBUS_I2C_BLOCK_DATA { copy(slc[1:], sys.dataSlice) } else { @@ -54,7 +54,7 @@ func (sys *mockSyscall) syscall(trap uintptr, f File, signal uintptr, payload un // call mock implementation if sys.Impl != nil { - return sys.Impl(trap, f.Fd(), signal, uintptr(unsafe.Pointer(payload))) + return sys.Impl(trap, f.Fd(), signal, uintptr(payload)) } return 0, 0, 0 } @@ -69,6 +69,6 @@ func (sys *mockSyscall) retrieveSliceSize() uint8 { return 2 default: // for I2C_SMBUS_BLOCK_DATA, I2C_SMBUS_I2C_BLOCK_DATA - return *(*byte)(unsafe.Pointer(sys.smbus.data)) + 1 // first data element contains data size + return *(*byte)(sys.smbus.data) + 1 // first data element contains data size } } diff --git a/system/system.go b/system/system.go index 824d43865..708885265 100644 --- a/system/system.go +++ b/system/system.go @@ -113,7 +113,8 @@ func (a *Accesser) UseMockSpi() *MockSpiAccess { // NewDigitalPin returns a new system digital pin, according to the given pin number. func (a *Accesser) NewDigitalPin(chip string, pin int, - o ...func(gobot.DigitalPinOptioner) bool) gobot.DigitalPinner { + o ...func(gobot.DigitalPinOptioner) bool, +) gobot.DigitalPinner { return a.digitalPinAccess.createPin(chip, pin, o...) } diff --git a/system/system_options.go b/system/system_options.go index 302e4462e..049d888c7 100644 --- a/system/system_options.go +++ b/system/system_options.go @@ -40,7 +40,6 @@ func (a *Accesser) setDigitalPinToGpiodAccess() { if systemDebug { fmt.Println("gpiod driver not supported, fallback to sysfs") } - } func (a *Accesser) setSpiToGpioAccess(p gobot.DigitalPinnerProvider, sclkPin, nssPin, mosiPin, misoPin string) { diff --git a/system/system_test.go b/system/system_test.go index 9f2c7243a..2e4e26363 100644 --- a/system/system_test.go +++ b/system/system_test.go @@ -44,7 +44,7 @@ func TestNewAccesser_NewSpiDevice(t *testing.T) { } func TestNewAccesser_IsSysfsDigitalPinAccess(t *testing.T) { - var tests = map[string]struct { + tests := map[string]struct { gpiodAccesser bool wantSys bool }{ From ee4368b10f0d33af9a1eea29e981509128f1c781 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sat, 21 Oct 2023 10:08:03 +0200 Subject: [PATCH 11/57] test(all): substitude assert.Errorf by assert.Error (#1011) --- drivers/gpio/buzzer_driver_test.go | 6 +-- drivers/gpio/direct_pin_driver_test.go | 18 +++---- drivers/gpio/hd44780_driver_test.go | 18 +++---- drivers/gpio/led_driver_test.go | 10 ++-- drivers/gpio/rgb_led_driver_test.go | 10 ++-- drivers/gpio/servo_driver_test.go | 8 ++-- drivers/gpio/stepper_driver_test.go | 2 +- drivers/i2c/adafruit1109_driver_test.go | 4 +- drivers/i2c/adafruit_driver_test.go | 18 +++---- drivers/i2c/ads1x15_driver_1015_test.go | 18 +++---- drivers/i2c/ads1x15_driver_1115_test.go | 18 +++---- drivers/i2c/ads1x15_driver_test.go | 2 +- drivers/i2c/adxl345_driver_test.go | 4 +- drivers/i2c/bh1750_driver_test.go | 4 +- drivers/i2c/blinkm_driver_test.go | 8 ++-- drivers/i2c/bme280_driver_test.go | 10 ++-- drivers/i2c/bmp180_driver_test.go | 6 +-- drivers/i2c/bmp280_driver_test.go | 8 ++-- drivers/i2c/bmp388_driver_test.go | 8 ++-- drivers/i2c/drv2605l_driver_test.go | 4 +- drivers/i2c/hmc6352_driver_test.go | 4 +- drivers/i2c/i2c_connection_test.go | 18 +++---- drivers/i2c/i2c_driver_test.go | 2 +- drivers/i2c/ina3221_driver_test.go | 8 ++-- drivers/i2c/jhd1313m1_driver_test.go | 16 +++---- drivers/i2c/l3gd20h_driver_test.go | 4 +- drivers/i2c/lidarlite_driver_test.go | 8 ++-- drivers/i2c/mcp23017_driver_test.go | 18 +++---- drivers/i2c/mma7660_driver_test.go | 2 +- drivers/i2c/mpl115a2_driver_test.go | 2 +- drivers/i2c/mpu6050_driver_test.go | 4 +- drivers/i2c/pca9685_driver_test.go | 6 +-- drivers/i2c/sht2x_driver_test.go | 4 +- drivers/i2c/ssd1306_driver_test.go | 4 +- drivers/i2c/tsl2561_driver_test.go | 10 ++-- drivers/spi/mcp3002_test.go | 2 +- drivers/spi/mcp3004_test.go | 2 +- drivers/spi/mcp3008_test.go | 2 +- drivers/spi/mcp3202_test.go | 2 +- drivers/spi/mcp3204_test.go | 2 +- drivers/spi/mcp3208_test.go | 2 +- drivers/spi/mcp3304_test.go | 2 +- drivers/spi/ssd1306_driver_test.go | 2 +- platforms/adaptors/digitalpinsadaptor_test.go | 12 ++--- platforms/adaptors/i2cbusadaptor_test.go | 4 +- platforms/adaptors/pwmpinsadaptor_test.go | 8 ++-- platforms/adaptors/spibusadaptor_test.go | 6 +-- platforms/audio/audio_adaptor_test.go | 2 +- .../beaglebone/beaglebone_adaptor_test.go | 12 ++--- platforms/chip/chip_adaptor_test.go | 4 +- platforms/digispark/digispark_adaptor_test.go | 8 ++-- platforms/digispark/digispark_i2c_test.go | 4 +- .../dragonboard/dragonboard_adaptor_test.go | 2 +- platforms/firmata/firmata_adaptor_test.go | 4 +- platforms/firmata/firmata_i2c_test.go | 2 +- platforms/intel-iot/curie/imu_driver_test.go | 14 +++--- .../intel-iot/edison/edison_adaptor_test.go | 12 ++--- .../intel-iot/joule/joule_adaptor_test.go | 6 +-- platforms/jetson/jetson_adaptor_test.go | 4 +- platforms/jetson/pwm_pin_test.go | 47 ++++++++++++++----- platforms/leap/leap_motion_adaptor_test.go | 2 +- platforms/mavlink/mavlink_adaptor_test.go | 4 +- platforms/mavlink/mavlink_udp_adaptor_test.go | 2 +- platforms/microbit/io_pin_driver_test.go | 8 ++-- platforms/mqtt/mqtt_adaptor_test.go | 2 +- platforms/nanopi/nanopi_adaptor_test.go | 10 ++-- platforms/nats/nats_adaptor_test.go | 2 +- platforms/neurosky/neurosky_adaptor_test.go | 4 +- .../parrot/ardrone/ardrone_adaptor_test.go | 2 +- platforms/parrot/bebop/bebop_adaptor_test.go | 2 +- platforms/particle/adaptor_test.go | 8 ++-- platforms/raspi/pwm_pin_test.go | 8 ++-- platforms/raspi/raspi_adaptor_test.go | 6 +-- platforms/sphero/sphero_adaptor_test.go | 4 +- platforms/tinkerboard/adaptor_test.go | 10 ++-- platforms/upboard/up2/adaptor_test.go | 2 +- system/digitalpin_sysfs_test.go | 12 ++--- system/fs_mock_test.go | 4 +- system/i2c_device_test.go | 22 ++++----- system/pwmpin_sysfs_test.go | 12 ++--- 80 files changed, 306 insertions(+), 281 deletions(-) diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index 4b16758fd..a6c371800 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -57,7 +57,7 @@ func TestBuzzerDriverOnError(t *testing.T) { return errors.New("write error") }) - assert.Errorf(t, d.On(), "write error") + assert.Error(t, d.On(), "write error") } func TestBuzzerDriverOffError(t *testing.T) { @@ -67,7 +67,7 @@ func TestBuzzerDriverOffError(t *testing.T) { return errors.New("write error") }) - assert.Errorf(t, d.Off(), "write error") + assert.Error(t, d.Off(), "write error") } func TestBuzzerDriverToneError(t *testing.T) { @@ -77,5 +77,5 @@ func TestBuzzerDriverToneError(t *testing.T) { return errors.New("write error") }) - assert.Errorf(t, d.Tone(100, 0.01), "write error") + assert.Error(t, d.Tone(100, 0.01), "write error") } diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index 1c8faaca1..5aeeec020 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -43,13 +43,13 @@ func TestDirectPinDriver(t *testing.T) { assert.Nil(t, ret["err"]) err = d.Command("DigitalWrite")(map[string]interface{}{"level": "1"}) - assert.Errorf(t, err.(error), "write error") + assert.Error(t, err.(error), "write error") err = d.Command("PwmWrite")(map[string]interface{}{"level": "1"}) - assert.Errorf(t, err.(error), "write error") + assert.Error(t, err.(error), "write error") err = d.Command("ServoWrite")(map[string]interface{}{"level": "1"}) - assert.Errorf(t, err.(error), "write error") + assert.Error(t, err.(error), "write error") } func TestDirectPinDriverStart(t *testing.T) { @@ -74,7 +74,7 @@ func TestDirectPinDriverOff(t *testing.T) { func TestDirectPinDriverOffNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Errorf(t, d.Off(), "DigitalWrite is not supported by this platform") + assert.Error(t, d.Off(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverOn(t *testing.T) { @@ -91,7 +91,7 @@ func TestDirectPinDriverOnError(t *testing.T) { func TestDirectPinDriverOnNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Errorf(t, d.On(), "DigitalWrite is not supported by this platform") + assert.Error(t, d.On(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWrite(t *testing.T) { @@ -103,7 +103,7 @@ func TestDirectPinDriverDigitalWrite(t *testing.T) { func TestDirectPinDriverDigitalWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Errorf(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") + assert.Error(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWriteError(t *testing.T) { @@ -122,7 +122,7 @@ func TestDirectPinDriverDigitalReadNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") _, e := d.DigitalRead() - assert.Errorf(t, e, "DigitalRead is not supported by this platform") + assert.Error(t, e, "DigitalRead is not supported by this platform") } func TestDirectPinDriverPwmWrite(t *testing.T) { @@ -134,7 +134,7 @@ func TestDirectPinDriverPwmWrite(t *testing.T) { func TestDirectPinDriverPwmWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Errorf(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") + assert.Error(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") } func TestDirectPinDriverPwmWriteError(t *testing.T) { @@ -151,7 +151,7 @@ func TestDirectPinDriverServoWrite(t *testing.T) { func TestDirectPinDriverServoWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Errorf(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") + assert.Error(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") } func TestDirectPinDriverServoWriteError(t *testing.T) { diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index dc4c01e16..4ac7ad98c 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -93,7 +93,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_4BITMODE, "13", "15", pins) - assert.Errorf(t, d.Start(), "Initialization error") + assert.Error(t, d.Start(), "Initialization error") pins = HD44780DataPin{ D0: "31", @@ -106,7 +106,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_8BITMODE, "13", "15", pins) - assert.Errorf(t, d.Start(), "Initialization error") + assert.Error(t, d.Start(), "Initialization error") } func TestHD44780DriverWrite(t *testing.T) { @@ -130,14 +130,14 @@ func TestHD44780DriverWriteError(t *testing.T) { return errors.New("write error") } _ = d.Start() - assert.Errorf(t, d.Write("hello gobot"), "write error") + assert.Error(t, d.Write("hello gobot"), "write error") d, a = initTestHD44780Driver8BitModeWithStubbedAdaptor() a.testAdaptorDigitalWrite = func(string, byte) (err error) { return errors.New("write error") } _ = d.Start() - assert.Errorf(t, d.Write("hello gobot"), "write error") + assert.Error(t, d.Write("hello gobot"), "write error") } func TestHD44780DriverClear(t *testing.T) { @@ -158,10 +158,10 @@ func TestHD44780DriverSetCursor(t *testing.T) { func TestHD44780DriverSetCursorInvalid(t *testing.T) { d := initTestHD44780Driver() - assert.Errorf(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") - assert.Errorf(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") - assert.Errorf(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") - assert.Errorf(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") + assert.Error(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") + assert.Error(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") + assert.Error(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") + assert.Error(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") } func TestHD44780DriverDisplayOn(t *testing.T) { @@ -233,5 +233,5 @@ func TestHD44780DriverCreateChar(t *testing.T) { func TestHD44780DriverCreateCharError(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - assert.Errorf(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") + assert.Error(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") } diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index 4cbeef303..3d1877575 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -38,16 +38,16 @@ func TestLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - assert.Errorf(t, err.(error), "write error") + assert.Error(t, err.(error), "write error") err = d.Command("On")(nil) - assert.Errorf(t, err.(error), "write error") + assert.Error(t, err.(error), "write error") err = d.Command("Off")(nil) - assert.Errorf(t, err.(error), "write error") + assert.Error(t, err.(error), "write error") err = d.Command("Brightness")(map[string]interface{}{"level": 100.0}) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") } func TestLedDriverStart(t *testing.T) { @@ -76,7 +76,7 @@ func TestLedDriverBrightness(t *testing.T) { err = errors.New("pwm error") return } - assert.Errorf(t, d.Brightness(150), "pwm error") + assert.Error(t, d.Brightness(150), "pwm error") } func TestLEDDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index 5173b02ee..dcae08b36 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -42,16 +42,16 @@ func TestRgbLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") err = d.Command("On")(nil) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") err = d.Command("Off")(nil) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") err = d.Command("SetRGB")(map[string]interface{}{"r": 0xff, "g": 0xff, "b": 0xff}) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") } func TestRgbLedDriverStart(t *testing.T) { @@ -83,7 +83,7 @@ func TestRgbLedDriverSetLevel(t *testing.T) { err = errors.New("pwm error") return } - assert.Errorf(t, d.SetLevel("1", 150), "pwm error") + assert.Error(t, d.SetLevel("1", 150), "pwm error") } func TestRgbLedDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index 0d3058b66..e93a7c3db 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -29,16 +29,16 @@ func TestServoDriver(t *testing.T) { } err = d.Command("Min")(nil) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") err = d.Command("Center")(nil) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") err = d.Command("Max")(nil) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") err = d.Command("Move")(map[string]interface{}{"angle": 100.0}) - assert.Errorf(t, err.(error), "pwm error") + assert.Error(t, err.(error), "pwm error") } func TestServoDriverStart(t *testing.T) { diff --git a/drivers/gpio/stepper_driver_test.go b/drivers/gpio/stepper_driver_test.go index 9e88dd693..78aceef98 100644 --- a/drivers/gpio/stepper_driver_test.go +++ b/drivers/gpio/stepper_driver_test.go @@ -57,7 +57,7 @@ func TestStepperDriverDefaultDirection(t *testing.T) { func TestStepperDriverInvalidDirection(t *testing.T) { d := initStepperMotorDriver() err := d.SetDirection("reverse") - assert.Errorf(t, err, "Invalid direction. Value should be forward or backward") + assert.Error(t, err, "Invalid direction. Value should be forward or backward") } func TestStepperDriverMoveForward(t *testing.T) { diff --git a/drivers/i2c/adafruit1109_driver_test.go b/drivers/i2c/adafruit1109_driver_test.go index ae7cb92de..d9d812343 100644 --- a/drivers/i2c/adafruit1109_driver_test.go +++ b/drivers/i2c/adafruit1109_driver_test.go @@ -73,7 +73,7 @@ func TestAdafruit1109StartWriteErr(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.Start(), "write error") + assert.Error(t, d.Start(), "write error") } func TestAdafruit1109StartReadErr(t *testing.T) { @@ -81,7 +81,7 @@ func TestAdafruit1109StartReadErr(t *testing.T) { adaptor.i2cReadImpl = func([]byte) (int, error) { return 0, errors.New("read error") } - assert.Errorf(t, d.Start(), "MCP write-read: MCP write-ReadByteData(reg=0): read error") + assert.Error(t, d.Start(), "MCP write-read: MCP write-ReadByteData(reg=0): read error") } func TestAdafruit1109Halt(t *testing.T) { diff --git a/drivers/i2c/adafruit_driver_test.go b/drivers/i2c/adafruit_driver_test.go index d100a73fe..0d94cffff 100644 --- a/drivers/i2c/adafruit_driver_test.go +++ b/drivers/i2c/adafruit_driver_test.go @@ -45,7 +45,7 @@ func TestAdafruitMotorHatDriverStartWriteError(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.Start(), "write error") + assert.Error(t, d.Start(), "write error") } func TestAdafruitMotorHatDriverStartReadError(t *testing.T) { @@ -53,13 +53,13 @@ func TestAdafruitMotorHatDriverStartReadError(t *testing.T) { adaptor.i2cReadImpl = func([]byte) (int, error) { return 0, errors.New("read error") } - assert.Errorf(t, d.Start(), "read error") + assert.Error(t, d.Start(), "read error") } func TestAdafruitMotorHatDriverStartConnectError(t *testing.T) { d, adaptor := initTestAdafruitMotorHatDriverWithStubbedAdaptor() adaptor.Testi2cConnectErr(true) - assert.Errorf(t, d.Start(), "Invalid i2c connection") + assert.Error(t, d.Start(), "Invalid i2c connection") } func TestAdafruitMotorHatDriverHalt(t *testing.T) { @@ -96,7 +96,7 @@ func TestAdafruitMotorHatDriverSetServoMotorFreqError(t *testing.T) { } freq := 60.0 - assert.Errorf(t, ada.SetServoMotorFreq(freq), "write error") + assert.Error(t, ada.SetServoMotorFreq(freq), "write error") } func TestAdafruitMotorHatDriverSetServoMotorPulse(t *testing.T) { @@ -122,7 +122,7 @@ func TestAdafruitMotorHatDriverSetServoMotorPulseError(t *testing.T) { var channel byte = 7 var on int32 = 1234 var off int32 = 4321 - assert.Errorf(t, ada.SetServoMotorPulse(channel, on, off), "write error") + assert.Error(t, ada.SetServoMotorPulse(channel, on, off), "write error") } func TestAdafruitMotorHatDriverSetDCMotorSpeed(t *testing.T) { @@ -144,7 +144,7 @@ func TestAdafruitMotorHatDriverSetDCMotorSpeedError(t *testing.T) { return 0, errors.New("write error") } - assert.Errorf(t, ada.SetDCMotorSpeed(1, 255), "write error") + assert.Error(t, ada.SetDCMotorSpeed(1, 255), "write error") } func TestAdafruitMotorHatDriverRunDCMotor(t *testing.T) { @@ -166,9 +166,9 @@ func TestAdafruitMotorHatDriverRunDCMotorError(t *testing.T) { } dcMotor := 1 - assert.Errorf(t, ada.RunDCMotor(dcMotor, AdafruitForward), "write error") - assert.Errorf(t, ada.RunDCMotor(dcMotor, AdafruitBackward), "write error") - assert.Errorf(t, ada.RunDCMotor(dcMotor, AdafruitRelease), "write error") + assert.Error(t, ada.RunDCMotor(dcMotor, AdafruitForward), "write error") + assert.Error(t, ada.RunDCMotor(dcMotor, AdafruitBackward), "write error") + assert.Error(t, ada.RunDCMotor(dcMotor, AdafruitRelease), "write error") } func TestAdafruitMotorHatDriverSetStepperMotorSpeed(t *testing.T) { diff --git a/drivers/i2c/ads1x15_driver_1015_test.go b/drivers/i2c/ads1x15_driver_1015_test.go index 2e23bce0f..285c5c499 100644 --- a/drivers/i2c/ads1x15_driver_1015_test.go +++ b/drivers/i2c/ads1x15_driver_1015_test.go @@ -115,14 +115,14 @@ func TestADS1x15AnalogReadError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestADS1x15AnalogReadInvalidPin(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.AnalogRead("99") - assert.Errorf(t, err, "Invalid channel (99), must be between 0 and 3") + assert.Error(t, err, "Invalid channel (99), must be between 0 and 3") } func TestADS1x15AnalogReadWriteError(t *testing.T) { @@ -133,41 +133,41 @@ func TestADS1x15AnalogReadWriteError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") _, err = d.AnalogRead("0-1") - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") _, err = d.AnalogRead("2-3") - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestADS1x15ReadInvalidChannel(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(9, 1, 1600) - assert.Errorf(t, err, "Invalid channel (9), must be between 0 and 3") + assert.Error(t, err, "Invalid channel (9), must be between 0 and 3") } func TestADS1x15ReadInvalidGain(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(0, 8, 1600) - assert.Errorf(t, err, "Gain (8) must be one of: [0 1 2 3 4 5 6 7]") + assert.Error(t, err, "Gain (8) must be one of: [0 1 2 3 4 5 6 7]") } func TestADS1x15ReadInvalidDataRate(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(0, 1, 321) - assert.Errorf(t, err, "Invalid data rate (321). Accepted values: [128 250 490 920 1600 2400 3300]") + assert.Error(t, err, "Invalid data rate (321). Accepted values: [128 250 490 920 1600 2400 3300]") } func TestADS1x15ReadDifferenceInvalidChannel(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.ReadDifference(9, 1, 1600) - assert.Errorf(t, err, "Invalid channel (9), must be between 0 and 3") + assert.Error(t, err, "Invalid channel (9), must be between 0 and 3") } func TestADS1015_rawRead(t *testing.T) { diff --git a/drivers/i2c/ads1x15_driver_1115_test.go b/drivers/i2c/ads1x15_driver_1115_test.go index c1fd7d0e3..9b2b6b478 100644 --- a/drivers/i2c/ads1x15_driver_1115_test.go +++ b/drivers/i2c/ads1x15_driver_1115_test.go @@ -115,14 +115,14 @@ func TestADS1115AnalogReadError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestADS1115AnalogReadInvalidPin(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.AnalogRead("98") - assert.Errorf(t, err, "Invalid channel (98), must be between 0 and 3") + assert.Error(t, err, "Invalid channel (98), must be between 0 and 3") } func TestADS1115AnalogReadWriteError(t *testing.T) { @@ -133,41 +133,41 @@ func TestADS1115AnalogReadWriteError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") _, err = d.AnalogRead("0-1") - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") _, err = d.AnalogRead("2-3") - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestADS1115ReadInvalidChannel(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(7, 1, 1600) - assert.Errorf(t, err, "Invalid channel (7), must be between 0 and 3") + assert.Error(t, err, "Invalid channel (7), must be between 0 and 3") } func TestADS1115ReadInvalidGain(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(0, 21, 1600) - assert.Errorf(t, err, "Gain (21) must be one of: [0 1 2 3 4 5 6 7]") + assert.Error(t, err, "Gain (21) must be one of: [0 1 2 3 4 5 6 7]") } func TestADS1115ReadInvalidDataRate(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(0, 1, 678) - assert.Errorf(t, err, "Invalid data rate (678). Accepted values: [8 16 32 64 128 250 475 860]") + assert.Error(t, err, "Invalid data rate (678). Accepted values: [8 16 32 64 128 250 475 860]") } func TestADS1115ReadDifferenceInvalidChannel(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.ReadDifference(5, 1, 1600) - assert.Errorf(t, err, "Invalid channel (5), must be between 0 and 3") + assert.Error(t, err, "Invalid channel (5), must be between 0 and 3") } func TestADS1115_rawRead(t *testing.T) { diff --git a/drivers/i2c/ads1x15_driver_test.go b/drivers/i2c/ads1x15_driver_test.go index 9d93f770f..23df9842e 100644 --- a/drivers/i2c/ads1x15_driver_test.go +++ b/drivers/i2c/ads1x15_driver_test.go @@ -99,5 +99,5 @@ func TestADS1x15_ads1x15BestGainForVoltage(t *testing.T) { assert.Equal(t, 2, g) _, err := ads1x15BestGainForVoltage(20.0) - assert.Errorf(t, err, "The maximum voltage which can be read is 6.144000") + assert.Error(t, err, "The maximum voltage which can be read is 6.144000") } diff --git a/drivers/i2c/adxl345_driver_test.go b/drivers/i2c/adxl345_driver_test.go index eb2bc7333..8f905802c 100644 --- a/drivers/i2c/adxl345_driver_test.go +++ b/drivers/i2c/adxl345_driver_test.go @@ -205,7 +205,7 @@ func TestADXL345RawXYZError(t *testing.T) { // act _, _, _, err := d.RawXYZ() // assert - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestADXL345XYZ(t *testing.T) { @@ -269,7 +269,7 @@ func TestADXL345XYZError(t *testing.T) { // act _, _, _, err := d.XYZ() // assert - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestADXL345_initialize(t *testing.T) { diff --git a/drivers/i2c/bh1750_driver_test.go b/drivers/i2c/bh1750_driver_test.go index c2cbf9745..9ff8703fa 100644 --- a/drivers/i2c/bh1750_driver_test.go +++ b/drivers/i2c/bh1750_driver_test.go @@ -96,7 +96,7 @@ func TestBH1750LuxError(t *testing.T) { } _, err := d.Lux() - assert.Errorf(t, err, "wrong number of bytes read") + assert.Error(t, err, "wrong number of bytes read") } func TestBH1750RawSensorDataError(t *testing.T) { @@ -106,5 +106,5 @@ func TestBH1750RawSensorDataError(t *testing.T) { } _, err := d.RawSensorData() - assert.Errorf(t, err, "wrong number of bytes read") + assert.Error(t, err, "wrong number of bytes read") } diff --git a/drivers/i2c/blinkm_driver_test.go b/drivers/i2c/blinkm_driver_test.go index e3a00e73b..c3ed3a5f0 100644 --- a/drivers/i2c/blinkm_driver_test.go +++ b/drivers/i2c/blinkm_driver_test.go @@ -125,7 +125,7 @@ func TestBlinkMFirmwareVersion(t *testing.T) { } _, err := d.FirmwareVersion() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestBlinkMColor(t *testing.T) { @@ -153,7 +153,7 @@ func TestBlinkMColor(t *testing.T) { } _, err := d.Color() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestBlinkMFade(t *testing.T) { @@ -163,7 +163,7 @@ func TestBlinkMFade(t *testing.T) { } err := d.Fade(100, 100, 100) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestBlinkMRGB(t *testing.T) { @@ -173,5 +173,5 @@ func TestBlinkMRGB(t *testing.T) { } err := d.Rgb(100, 100, 100) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } diff --git a/drivers/i2c/bme280_driver_test.go b/drivers/i2c/bme280_driver_test.go index 9ffc61313..77147cc25 100644 --- a/drivers/i2c/bme280_driver_test.go +++ b/drivers/i2c/bme280_driver_test.go @@ -92,7 +92,7 @@ func TestBME280InitH1Error(t *testing.T) { return buf.Len(), nil } - assert.Errorf(t, bme280.Start(), "h1 read error") + assert.Error(t, bme280.Start(), "h1 read error") } func TestBME280InitH2Error(t *testing.T) { @@ -111,7 +111,7 @@ func TestBME280InitH2Error(t *testing.T) { return buf.Len(), nil } - assert.Errorf(t, bme280.Start(), "h2 read error") + assert.Error(t, bme280.Start(), "h2 read error") } func TestBME280HumidityWriteError(t *testing.T) { @@ -122,7 +122,7 @@ func TestBME280HumidityWriteError(t *testing.T) { return 0, errors.New("write error") } hum, err := bme280.Humidity() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") assert.Equal(t, float32(0.0), hum) } @@ -134,7 +134,7 @@ func TestBME280HumidityReadError(t *testing.T) { return 0, errors.New("read error") } hum, err := bme280.Humidity() - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") assert.Equal(t, float32(0.0), hum) } @@ -159,7 +159,7 @@ func TestBME280HumidityNotEnabled(t *testing.T) { } _ = bme280.Start() hum, err := bme280.Humidity() - assert.Errorf(t, err, "Humidity disabled") + assert.Error(t, err, "Humidity disabled") assert.Equal(t, float32(0.0), hum) } diff --git a/drivers/i2c/bmp180_driver_test.go b/drivers/i2c/bmp180_driver_test.go index de26fdfaa..610b67c8c 100644 --- a/drivers/i2c/bmp180_driver_test.go +++ b/drivers/i2c/bmp180_driver_test.go @@ -108,7 +108,7 @@ func TestBMP180TemperatureError(t *testing.T) { } _ = bmp180.Start() _, err := bmp180.Temperature() - assert.Errorf(t, err, "temp error") + assert.Error(t, err, "temp error") } func TestBMP180PressureError(t *testing.T) { @@ -138,7 +138,7 @@ func TestBMP180PressureError(t *testing.T) { } _ = bmp180.Start() _, err := bmp180.Pressure() - assert.Errorf(t, err, "press error") + assert.Error(t, err, "press error") } func TestBMP180PressureWriteError(t *testing.T) { @@ -150,7 +150,7 @@ func TestBMP180PressureWriteError(t *testing.T) { } _, err := bmp180.Pressure() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestBMP180_initialization(t *testing.T) { diff --git a/drivers/i2c/bmp280_driver_test.go b/drivers/i2c/bmp280_driver_test.go index 6f769e09f..2dc45298b 100644 --- a/drivers/i2c/bmp280_driver_test.go +++ b/drivers/i2c/bmp280_driver_test.go @@ -106,7 +106,7 @@ func TestBMP280TemperatureWriteError(t *testing.T) { return 0, errors.New("write error") } temp, err := d.Temperature() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") assert.Equal(t, float32(0.0), temp) } @@ -118,7 +118,7 @@ func TestBMP280TemperatureReadError(t *testing.T) { return 0, errors.New("read error") } temp, err := d.Temperature() - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") assert.Equal(t, float32(0.0), temp) } @@ -130,7 +130,7 @@ func TestBMP280PressureWriteError(t *testing.T) { return 0, errors.New("write error") } press, err := d.Pressure() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") assert.Equal(t, float32(0.0), press) } @@ -142,7 +142,7 @@ func TestBMP280PressureReadError(t *testing.T) { return 0, errors.New("read error") } press, err := d.Pressure() - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") assert.Equal(t, float32(0.0), press) } diff --git a/drivers/i2c/bmp388_driver_test.go b/drivers/i2c/bmp388_driver_test.go index 7f54414f5..8053710f5 100644 --- a/drivers/i2c/bmp388_driver_test.go +++ b/drivers/i2c/bmp388_driver_test.go @@ -102,7 +102,7 @@ func TestBMP388TemperatureWriteError(t *testing.T) { return 0, errors.New("write error") } temp, err := d.Temperature(2) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") assert.Equal(t, float32(0.0), temp) } @@ -114,7 +114,7 @@ func TestBMP388TemperatureReadError(t *testing.T) { return 0, errors.New("read error") } temp, err := d.Temperature(2) - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") assert.Equal(t, float32(0.0), temp) } @@ -126,7 +126,7 @@ func TestBMP388PressureWriteError(t *testing.T) { return 0, errors.New("write error") } press, err := d.Pressure(2) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") assert.Equal(t, float32(0.0), press) } @@ -138,7 +138,7 @@ func TestBMP388PressureReadError(t *testing.T) { return 0, errors.New("read error") } press, err := d.Pressure(2) - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") assert.Equal(t, float32(0.0), press) } diff --git a/drivers/i2c/drv2605l_driver_test.go b/drivers/i2c/drv2605l_driver_test.go index 125a0f9c5..afeb1ce6a 100644 --- a/drivers/i2c/drv2605l_driver_test.go +++ b/drivers/i2c/drv2605l_driver_test.go @@ -110,7 +110,7 @@ func TestDRV2605LSetModeReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - assert.Errorf(t, d.SetMode(DRV2605ModeIntTrig), "read error") + assert.Error(t, d.SetMode(DRV2605ModeIntTrig), "read error") } func TestDRV2605LSetStandbyMode(t *testing.T) { @@ -123,7 +123,7 @@ func TestDRV2605LSetStandbyModeReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - assert.Errorf(t, d.SetStandbyMode(true), "read error") + assert.Error(t, d.SetStandbyMode(true), "read error") } func TestDRV2605LSelectLibrary(t *testing.T) { diff --git a/drivers/i2c/hmc6352_driver_test.go b/drivers/i2c/hmc6352_driver_test.go index 81fcd14df..dee1b487e 100644 --- a/drivers/i2c/hmc6352_driver_test.go +++ b/drivers/i2c/hmc6352_driver_test.go @@ -80,7 +80,7 @@ func TestHMC6352Heading(t *testing.T) { heading, err = d.Heading() assert.Equal(t, uint16(0), heading) - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") // when write error d, a = initTestHMC6352DriverWithStubbedAdaptor() @@ -90,5 +90,5 @@ func TestHMC6352Heading(t *testing.T) { heading, err = d.Heading() assert.Equal(t, uint16(0), heading) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index 6be0e6237..fe9efaa70 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -87,7 +87,7 @@ func TestI2CRead(t *testing.T) { func TestI2CReadAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.Read([]byte{}) - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWrite(t *testing.T) { @@ -99,7 +99,7 @@ func TestI2CWrite(t *testing.T) { func TestI2CWriteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.Write([]byte{0x01}) - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadByte(t *testing.T) { @@ -111,7 +111,7 @@ func TestI2CReadByte(t *testing.T) { func TestI2CReadByteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadByte() - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadByteData(t *testing.T) { @@ -123,7 +123,7 @@ func TestI2CReadByteData(t *testing.T) { func TestI2CReadByteDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadByteData(0x01) - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadWordData(t *testing.T) { @@ -135,7 +135,7 @@ func TestI2CReadWordData(t *testing.T) { func TestI2CReadWordDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadWordData(0x01) - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteByte(t *testing.T) { @@ -147,7 +147,7 @@ func TestI2CWriteByte(t *testing.T) { func TestI2CWriteByteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteByte(0x01) - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteByteData(t *testing.T) { @@ -159,7 +159,7 @@ func TestI2CWriteByteData(t *testing.T) { func TestI2CWriteByteDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteByteData(0x01, 0x01) - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteWordData(t *testing.T) { @@ -171,7 +171,7 @@ func TestI2CWriteWordData(t *testing.T) { func TestI2CWriteWordDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteWordData(0x01, 0x01) - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteBlockData(t *testing.T) { @@ -183,7 +183,7 @@ func TestI2CWriteBlockData(t *testing.T) { func TestI2CWriteBlockDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteBlockData(0x01, []byte{0x01, 0x02}) - assert.Errorf(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") } func Test_setBit(t *testing.T) { diff --git a/drivers/i2c/i2c_driver_test.go b/drivers/i2c/i2c_driver_test.go index 51bc13e57..e2317e035 100644 --- a/drivers/i2c/i2c_driver_test.go +++ b/drivers/i2c/i2c_driver_test.go @@ -70,7 +70,7 @@ func TestStartConnectError(t *testing.T) { d, a := initDriverWithStubbedAdaptor() a.Testi2cConnectErr(true) // act, assert - assert.Errorf(t, d.Start(), "Invalid i2c connection") + assert.Error(t, d.Start(), "Invalid i2c connection") } func TestHalt(t *testing.T) { diff --git a/drivers/i2c/ina3221_driver_test.go b/drivers/i2c/ina3221_driver_test.go index 784306c5c..3650dec9f 100644 --- a/drivers/i2c/ina3221_driver_test.go +++ b/drivers/i2c/ina3221_driver_test.go @@ -70,7 +70,7 @@ func TestINA3221GetBusVoltageReadError(t *testing.T) { } _, err := d.GetBusVoltage(INA3221Channel1) - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestINA3221GetShuntVoltage(t *testing.T) { @@ -93,7 +93,7 @@ func TestINA3221GetShuntVoltageReadError(t *testing.T) { } _, err := d.GetShuntVoltage(INA3221Channel1) - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestINA3221GetCurrent(t *testing.T) { @@ -116,7 +116,7 @@ func TestINA3221CurrentReadError(t *testing.T) { } _, err := d.GetCurrent(INA3221Channel1) - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestINA3221GetLoadVoltage(t *testing.T) { @@ -141,5 +141,5 @@ func TestINA3221GetLoadVoltageReadError(t *testing.T) { } _, err := d.GetLoadVoltage(INA3221Channel2) - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } diff --git a/drivers/i2c/jhd1313m1_driver_test.go b/drivers/i2c/jhd1313m1_driver_test.go index 858689dd6..eef00c036 100644 --- a/drivers/i2c/jhd1313m1_driver_test.go +++ b/drivers/i2c/jhd1313m1_driver_test.go @@ -60,7 +60,7 @@ func TestJHD1313MDriverStart(t *testing.T) { func TestJHD1313MStartConnectError(t *testing.T) { d, adaptor := initTestJHD1313M1DriverWithStubbedAdaptor() adaptor.Testi2cConnectErr(true) - assert.Errorf(t, d.Start(), "Invalid i2c connection") + assert.Error(t, d.Start(), "Invalid i2c connection") } func TestJHD1313MDriverStartWriteError(t *testing.T) { @@ -68,7 +68,7 @@ func TestJHD1313MDriverStartWriteError(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.Start(), "write error") + assert.Error(t, d.Start(), "write error") } func TestJHD1313MDriverHalt(t *testing.T) { @@ -90,7 +90,7 @@ func TestJHD1313MDriverSetRgbError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.SetRGB(0x00, 0x00, 0x00), "write error") + assert.Error(t, d.SetRGB(0x00, 0x00, 0x00), "write error") } func TestJHD1313MDriverClear(t *testing.T) { @@ -106,7 +106,7 @@ func TestJHD1313MDriverClearError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.Clear(), "write error") + assert.Error(t, d.Clear(), "write error") } func TestJHD1313MDriverHome(t *testing.T) { @@ -128,7 +128,7 @@ func TestJHD1313MDriverWriteError(t *testing.T) { return 0, errors.New("write error") } - assert.Errorf(t, d.Write("Hello"), "write error") + assert.Error(t, d.Write("Hello"), "write error") } func TestJHD1313MDriverWriteTwoLines(t *testing.T) { @@ -144,7 +144,7 @@ func TestJHD1313MDriverWriteTwoLinesError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.Write("Hello\nthere"), "write error") + assert.Error(t, d.Write("Hello\nthere"), "write error") } func TestJHD1313MDriverSetPosition(t *testing.T) { @@ -189,7 +189,7 @@ func TestJHD1313MDriverSetCustomCharError(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} _ = d.Start() - assert.Errorf(t, d.SetCustomChar(10, data), "can't set a custom character at a position greater than 7") + assert.Error(t, d.SetCustomChar(10, data), "can't set a custom character at a position greater than 7") } func TestJHD1313MDriverSetCustomCharWriteError(t *testing.T) { @@ -200,7 +200,7 @@ func TestJHD1313MDriverSetCustomCharWriteError(t *testing.T) { return 0, errors.New("write error") } data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - assert.Errorf(t, d.SetCustomChar(0, data), "write error") + assert.Error(t, d.SetCustomChar(0, data), "write error") } func TestJHD1313MDriverCommands(t *testing.T) { diff --git a/drivers/i2c/l3gd20h_driver_test.go b/drivers/i2c/l3gd20h_driver_test.go index b59337ed2..5dcb88fda 100644 --- a/drivers/i2c/l3gd20h_driver_test.go +++ b/drivers/i2c/l3gd20h_driver_test.go @@ -214,7 +214,7 @@ func TestL3GD20HMeasurementError(t *testing.T) { _ = d.Start() _, _, _, err := d.XYZ() - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestL3GD20HMeasurementWriteError(t *testing.T) { @@ -223,7 +223,7 @@ func TestL3GD20HMeasurementWriteError(t *testing.T) { return 0, errors.New("write error") } _, _, _, err := d.XYZ() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestL3GD20H_initialize(t *testing.T) { diff --git a/drivers/i2c/lidarlite_driver_test.go b/drivers/i2c/lidarlite_driver_test.go index d3311822f..4050dc832 100644 --- a/drivers/i2c/lidarlite_driver_test.go +++ b/drivers/i2c/lidarlite_driver_test.go @@ -93,7 +93,7 @@ func TestLIDARLiteDriverDistance(t *testing.T) { distance, err = d.Distance() assert.Equal(t, int(0), distance) - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestLIDARLiteDriverDistanceError1(t *testing.T) { @@ -104,7 +104,7 @@ func TestLIDARLiteDriverDistanceError1(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestLIDARLiteDriverDistanceError2(t *testing.T) { @@ -118,7 +118,7 @@ func TestLIDARLiteDriverDistanceError2(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestLIDARLiteDriverDistanceError3(t *testing.T) { @@ -138,5 +138,5 @@ func TestLIDARLiteDriverDistanceError3(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index 8fff18697..bdb263951 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -241,7 +241,7 @@ func TestMCP23017CommandsWriteGPIOErrIODIR(t *testing.T) { // act err := d.WriteGPIO(7, "A", 0) // assert - assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") + assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") } func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { @@ -258,7 +258,7 @@ func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { // act err := d.WriteGPIO(7, "A", 0) // assert - assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=20): write error") + assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=20): write error") } func TestMCP23017ReadGPIO(t *testing.T) { @@ -381,7 +381,7 @@ func TestMCP23017ReadGPIOErr(t *testing.T) { // act _, err := d.ReadGPIO(7, "A") // assert - assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): read error") + assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): read error") } func TestMCP23017SetPinMode(t *testing.T) { @@ -431,7 +431,7 @@ func TestMCP23017SetPinModeErr(t *testing.T) { // act err := d.SetPinMode(7, "A", 0) // assert - assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") + assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") } func TestMCP23017SetPullUp(t *testing.T) { @@ -481,7 +481,7 @@ func TestMCP23017SetPullUpErr(t *testing.T) { // act err := d.SetPullUp(7, "A", 0) // assert - assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=12): write error") + assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=12): write error") } func TestMCP23017SetGPIOPolarity(t *testing.T) { @@ -531,7 +531,7 @@ func TestMCP23017SetGPIOPolarityErr(t *testing.T) { // act err := d.SetGPIOPolarity(7, "A", 0) // assert - assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=2): write error") + assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=2): write error") } func TestMCP23017_write(t *testing.T) { @@ -553,7 +553,7 @@ func TestMCP23017_write(t *testing.T) { return 0, errors.New("write error") } err = d.write(port.IODIR, uint8(7), 0) - assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): write error") + assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): write error") // read error d, a = initTestMCP23017WithStubbedAdaptor(0) @@ -561,7 +561,7 @@ func TestMCP23017_write(t *testing.T) { return len(b), errors.New("read error") } err = d.write(port.IODIR, uint8(7), 0) - assert.Errorf(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): read error") + assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): read error") a.i2cReadImpl = func(b []byte) (int, error) { return len(b), nil } @@ -588,7 +588,7 @@ func TestMCP23017_read(t *testing.T) { val, err := d.read(port.IODIR) assert.Equal(t, uint8(0), val) - assert.Errorf(t, err, "MCP write-ReadByteData(reg=0): read error") + assert.Error(t, err, "MCP write-ReadByteData(reg=0): read error") // read d, a = initTestMCP23017WithStubbedAdaptor(0) diff --git a/drivers/i2c/mma7660_driver_test.go b/drivers/i2c/mma7660_driver_test.go index 44529c6b6..1553218c4 100644 --- a/drivers/i2c/mma7660_driver_test.go +++ b/drivers/i2c/mma7660_driver_test.go @@ -90,7 +90,7 @@ func TestMMA7660XYZError(t *testing.T) { } _, _, _, err := d.XYZ() - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestMMA7660XYZNotReady(t *testing.T) { diff --git a/drivers/i2c/mpl115a2_driver_test.go b/drivers/i2c/mpl115a2_driver_test.go index 14a4fb86a..d7517197c 100644 --- a/drivers/i2c/mpl115a2_driver_test.go +++ b/drivers/i2c/mpl115a2_driver_test.go @@ -101,7 +101,7 @@ func TestMPL115A2ReadDataError(t *testing.T) { } _, err := d.Pressure() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestMPL115A2_initialization(t *testing.T) { diff --git a/drivers/i2c/mpu6050_driver_test.go b/drivers/i2c/mpu6050_driver_test.go index 905663829..94c9efb4e 100644 --- a/drivers/i2c/mpu6050_driver_test.go +++ b/drivers/i2c/mpu6050_driver_test.go @@ -124,7 +124,7 @@ func TestMPU6050GetDataReadError(t *testing.T) { return 0, errors.New("read error") } - assert.Errorf(t, d.GetData(), "read error") + assert.Error(t, d.GetData(), "read error") } func TestMPU6050GetDataWriteError(t *testing.T) { @@ -135,7 +135,7 @@ func TestMPU6050GetDataWriteError(t *testing.T) { return 0, errors.New("write error") } - assert.Errorf(t, d.GetData(), "write error") + assert.Error(t, d.GetData(), "write error") } func TestMPU6050_initialize(t *testing.T) { diff --git a/drivers/i2c/pca9685_driver_test.go b/drivers/i2c/pca9685_driver_test.go index 0c0b97852..5d1b3fee5 100644 --- a/drivers/i2c/pca9685_driver_test.go +++ b/drivers/i2c/pca9685_driver_test.go @@ -87,7 +87,7 @@ func TestPCA9685SetPWMError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.SetPWM(0, 0, 256), "write error") + assert.Error(t, d.SetPWM(0, 0, 256), "write error") } func TestPCA9685SetPWMFreq(t *testing.T) { @@ -116,7 +116,7 @@ func TestPCA9685SetPWMFreqReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - assert.Errorf(t, d.SetPWMFreq(60), "read error") + assert.Error(t, d.SetPWMFreq(60), "read error") } func TestPCA9685SetPWMFreqWriteError(t *testing.T) { @@ -130,7 +130,7 @@ func TestPCA9685SetPWMFreqWriteError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.SetPWMFreq(60), "write error") + assert.Error(t, d.SetPWMFreq(60), "write error") } func TestPCA9685Commands(t *testing.T) { diff --git a/drivers/i2c/sht2x_driver_test.go b/drivers/i2c/sht2x_driver_test.go index 1fb630b90..0fd369b79 100644 --- a/drivers/i2c/sht2x_driver_test.go +++ b/drivers/i2c/sht2x_driver_test.go @@ -116,7 +116,7 @@ func TestSHT2xTemperatureCrcError(t *testing.T) { return buf.Len(), nil } temp, err := d.Temperature() - assert.Errorf(t, err, "Invalid crc") + assert.Error(t, err, "Invalid crc") assert.Equal(t, float32(0.0), temp) } @@ -133,7 +133,7 @@ func TestSHT2xHumidityCrcError(t *testing.T) { return buf.Len(), nil } hum, err := d.Humidity() - assert.Errorf(t, err, "Invalid crc") + assert.Error(t, err, "Invalid crc") assert.Equal(t, float32(0.0), hum) } diff --git a/drivers/i2c/ssd1306_driver_test.go b/drivers/i2c/ssd1306_driver_test.go index ef6ae5590..28941e6c7 100644 --- a/drivers/i2c/ssd1306_driver_test.go +++ b/drivers/i2c/ssd1306_driver_test.go @@ -91,7 +91,7 @@ func TestSSD1306StartSizeError(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.Errorf(t, d.Start(), "128x54 resolution is unsupported, supported resolutions: 128x64, 128x32, 96x16") + assert.Error(t, d.Start(), "128x54 resolution is unsupported, supported resolutions: 128x64, 128x32, 96x16") } func TestSSD1306Halt(t *testing.T) { @@ -116,7 +116,7 @@ func TestSSD1306ShowImage(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) _ = s.Start() img := image.NewRGBA(image.Rect(0, 0, 640, 480)) - assert.Errorf(t, s.ShowImage(img), "image must match display width and height: 128x64") + assert.Error(t, s.ShowImage(img), "image must match display width and height: 128x64") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) assert.Nil(t, s.ShowImage(img)) diff --git a/drivers/i2c/tsl2561_driver_test.go b/drivers/i2c/tsl2561_driver_test.go index 7b60391a7..b719b3b53 100644 --- a/drivers/i2c/tsl2561_driver_test.go +++ b/drivers/i2c/tsl2561_driver_test.go @@ -72,7 +72,7 @@ func TestTSL2561DriverStartNotFound(t *testing.T) { copy(b, buf.Bytes()) return buf.Len(), nil } - assert.Errorf(t, d.Start(), "TSL2561 device not found (0x1)") + assert.Error(t, d.Start(), "TSL2561 device not found (0x1)") } func TestTSL2561DriverHalt(t *testing.T) { @@ -157,7 +157,7 @@ func TestTSL2561DriverGetDataWriteError(t *testing.T) { } _, _, err := d.getData() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestTSL2561DriverGetDataReadError(t *testing.T) { @@ -167,7 +167,7 @@ func TestTSL2561DriverGetDataReadError(t *testing.T) { } _, _, err := d.getData() - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestTSL2561DriverGetLuminocity(t *testing.T) { @@ -213,7 +213,7 @@ func TestTSL2561SetIntegrationTimeError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.SetIntegrationTime(TSL2561IntegrationTime101MS), "write error") + assert.Error(t, d.SetIntegrationTime(TSL2561IntegrationTime101MS), "write error") } func TestTSL2561SetGainError(t *testing.T) { @@ -221,7 +221,7 @@ func TestTSL2561SetGainError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Errorf(t, d.SetGain(TSL2561Gain16X), "write error") + assert.Error(t, d.SetGain(TSL2561Gain16X), "write error") } func TestTSL2561getHiLo13MS(t *testing.T) { diff --git a/drivers/spi/mcp3002_test.go b/drivers/spi/mcp3002_test.go index abbe0129f..560d1fbca 100644 --- a/drivers/spi/mcp3002_test.go +++ b/drivers/spi/mcp3002_test.go @@ -87,6 +87,6 @@ func TestMCP3002ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Errorf(t, err, "error while SPI read in mock") + assert.Error(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3004_test.go b/drivers/spi/mcp3004_test.go index 6cc1e82f6..b5db2db55 100644 --- a/drivers/spi/mcp3004_test.go +++ b/drivers/spi/mcp3004_test.go @@ -93,6 +93,6 @@ func TestMCP3004ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Errorf(t, err, "error while SPI read in mock") + assert.Error(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3008_test.go b/drivers/spi/mcp3008_test.go index e16230adc..10cbf5113 100644 --- a/drivers/spi/mcp3008_test.go +++ b/drivers/spi/mcp3008_test.go @@ -93,6 +93,6 @@ func TestMCP3008ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Errorf(t, err, "error while SPI read in mock") + assert.Error(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3202_test.go b/drivers/spi/mcp3202_test.go index c5fa0ba92..570f4ac8b 100644 --- a/drivers/spi/mcp3202_test.go +++ b/drivers/spi/mcp3202_test.go @@ -87,6 +87,6 @@ func TestMCP3202ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Errorf(t, err, "error while SPI read in mock") + assert.Error(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3204_test.go b/drivers/spi/mcp3204_test.go index e2bcc2e92..a2b223e05 100644 --- a/drivers/spi/mcp3204_test.go +++ b/drivers/spi/mcp3204_test.go @@ -93,6 +93,6 @@ func TestMCP3204ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Errorf(t, err, "error while SPI read in mock") + assert.Error(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3208_test.go b/drivers/spi/mcp3208_test.go index 64d3a6395..e28383a47 100644 --- a/drivers/spi/mcp3208_test.go +++ b/drivers/spi/mcp3208_test.go @@ -93,6 +93,6 @@ func TestMCP3208ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Errorf(t, err, "error while SPI read in mock") + assert.Error(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3304_test.go b/drivers/spi/mcp3304_test.go index 0740ddd45..1535771d9 100644 --- a/drivers/spi/mcp3304_test.go +++ b/drivers/spi/mcp3304_test.go @@ -93,6 +93,6 @@ func TestMCP3304ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Errorf(t, err, "error while SPI read in mock") + assert.Error(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/ssd1306_driver_test.go b/drivers/spi/ssd1306_driver_test.go index 7f01b1502..ff12e966b 100644 --- a/drivers/spi/ssd1306_driver_test.go +++ b/drivers/spi/ssd1306_driver_test.go @@ -38,7 +38,7 @@ func TestSSD1306DriverShowImage(t *testing.T) { d := initTestSSDDriver() _ = d.Start() img := image.NewRGBA(image.Rect(0, 0, 640, 480)) - assert.Errorf(t, d.ShowImage(img), "Image must match the display width and height") + assert.Error(t, d.ShowImage(img), "Image must match the display width and height") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) assert.Nil(t, d.ShowImage(img)) diff --git a/platforms/adaptors/digitalpinsadaptor_test.go b/platforms/adaptors/digitalpinsadaptor_test.go index fce9649a7..3441b4e1c 100644 --- a/platforms/adaptors/digitalpinsadaptor_test.go +++ b/platforms/adaptors/digitalpinsadaptor_test.go @@ -60,10 +60,10 @@ func TestDigitalPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.DigitalPinner)(nil), a.pins) _, err := a.DigitalRead("13") - assert.Errorf(t, err, "not connected for pin 13") + assert.Error(t, err, "not connected for pin 13") err = a.DigitalWrite("7", 1) - assert.Errorf(t, err, "not connected for pin 7") + assert.Error(t, err, "not connected for pin 7") err = a.Connect() assert.Nil(t, err) @@ -159,12 +159,12 @@ func TestDigitalRead(t *testing.T) { // assert error bubbling for read errors fs.WithReadError = true _, err = a.DigitalRead("13") - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") // assert error bubbling for write errors fs.WithWriteError = true _, err = a.DigitalRead("7") - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestDigitalReadWithGpiosActiveLow(t *testing.T) { @@ -228,12 +228,12 @@ func TestDigitalWrite(t *testing.T) { assert.Nil(t, err) // assert error on bad id - assert.Errorf(t, a.DigitalWrite("notexist", 1), "not a valid pin") + assert.Error(t, a.DigitalWrite("notexist", 1), "not a valid pin") // assert error bubbling fs.WithWriteError = true err = a.DigitalWrite("7", 0) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestDigitalWriteWithGpiosActiveLow(t *testing.T) { diff --git a/platforms/adaptors/i2cbusadaptor_test.go b/platforms/adaptors/i2cbusadaptor_test.go index b33b59a70..543d77056 100644 --- a/platforms/adaptors/i2cbusadaptor_test.go +++ b/platforms/adaptors/i2cbusadaptor_test.go @@ -61,13 +61,13 @@ func TestI2cGetI2cConnection(t *testing.T) { assert.Equal(t, 1, len(a.buses)) // assert invalid bus gets error c2, e2 := a.GetI2cConnection(0x01, 99) - assert.Errorf(t, e2, "99 not valid") + assert.Error(t, e2, "99 not valid") assert.Nil(t, c2) assert.Equal(t, 1, len(a.buses)) // assert unconnected gets error assert.Nil(t, a.Finalize()) c3, e3 := a.GetI2cConnection(0x01, 99) - assert.Errorf(t, e3, "not connected") + assert.Error(t, e3, "not connected") assert.Nil(t, c3) assert.Equal(t, 0, len(a.buses)) } diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index 322533c7a..6c98c4214 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -117,7 +117,7 @@ func TestPWMPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.PWMPinner)(nil), a.pins) err := a.PwmWrite("33", 1) - assert.Errorf(t, err, "not connected") + assert.Error(t, err, "not connected") err = a.Connect() assert.Nil(t, err) @@ -186,7 +186,7 @@ func TestPwmWrite(t *testing.T) { assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.PwmWrite("notexist", 42) - assert.Errorf(t, err, "'notexist' is not a valid id of a PWM pin") + assert.Error(t, err, "'notexist' is not a valid id of a PWM pin") fs.WithWriteError = true err = a.PwmWrite("33", 100) @@ -214,7 +214,7 @@ func TestServoWrite(t *testing.T) { assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("notexist", 42) - assert.Errorf(t, err, "'notexist' is not a valid id of a PWM pin") + assert.Error(t, err, "'notexist' is not a valid id of a PWM pin") fs.WithWriteError = true err = a.ServoWrite("33", 100) @@ -266,7 +266,7 @@ func TestSetPeriod(t *testing.T) { // act err = a.SetPeriod("not_exist", newPeriod) // assert - assert.Errorf(t, err, "'not_exist' is not a valid id of a PWM pin") + assert.Error(t, err, "'not_exist' is not a valid id of a PWM pin") } func Test_PWMPin(t *testing.T) { diff --git a/platforms/adaptors/spibusadaptor_test.go b/platforms/adaptors/spibusadaptor_test.go index bf5c36b81..20ed11605 100644 --- a/platforms/adaptors/spibusadaptor_test.go +++ b/platforms/adaptors/spibusadaptor_test.go @@ -40,7 +40,7 @@ func TestNewSpiAdaptor(t *testing.T) { assert.Equal(t, 4, a.SpiDefaultBitCount()) assert.Equal(t, int64(5), a.SpiDefaultMaxSpeed()) _, err := a.GetSpiConnection(10, 0, 0, 8, 10000000) - assert.Errorf(t, err, "not connected") + assert.Error(t, err, "not connected") } func TestGetSpiConnection(t *testing.T) { @@ -73,12 +73,12 @@ func TestGetSpiConnection(t *testing.T) { assert.Equal(t, 2, len(a.connections)) // assert bus validation error con, err := a.GetSpiConnection(busNum+1, chipNum, mode, bits, maxSpeed) - assert.Errorf(t, err, "16 not valid") + assert.Error(t, err, "16 not valid") assert.Nil(t, con) // assert create error spi.CreateError = true con, err = a.GetSpiConnection(busNum, chipNum+2, mode, bits, maxSpeed) - assert.Errorf(t, err, "error while create SPI connection in mock") + assert.Error(t, err, "error while create SPI connection in mock") assert.Nil(t, con) } diff --git a/platforms/audio/audio_adaptor_test.go b/platforms/audio/audio_adaptor_test.go index 42f69549e..4a6778d41 100644 --- a/platforms/audio/audio_adaptor_test.go +++ b/platforms/audio/audio_adaptor_test.go @@ -40,7 +40,7 @@ func TestAudioAdaptorCommandsMp3(t *testing.T) { func TestAudioAdaptorCommandsUnknown(t *testing.T) { cmd, err := CommandName("whatever.unk") assert.NotEqual(t, "mpg123", cmd) - assert.Errorf(t, err, "Unknown filetype for audio file.") + assert.Error(t, err, "Unknown filetype for audio file.") } func TestAudioAdaptorSoundWithNoFilename(t *testing.T) { diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index 55a927a6b..ac420c36b 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -58,7 +58,7 @@ func TestPWM(t *testing.T) { fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents = "0" fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/period"].Contents = "0" - assert.Errorf(t, a.PwmWrite("P9_99", 175), "'P9_99' is not a valid id for a PWM pin") + assert.Error(t, a.PwmWrite("P9_99", 175), "'P9_99' is not a valid id for a PWM pin") _ = a.PwmWrite("P9_21", 175) assert.Equal( t, @@ -99,11 +99,11 @@ func TestAnalog(t *testing.T) { assert.Nil(t, err) _, err = a.AnalogRead("P9_99") - assert.Errorf(t, err, "Not a valid analog pin") + assert.Error(t, err, "Not a valid analog pin") fs.WithReadError = true _, err = a.AnalogRead("P9_40") - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") fs.WithReadError = false assert.Nil(t, a.Finalize()) @@ -138,15 +138,15 @@ func TestDigitalIO(t *testing.T) { // no such LED err := a.DigitalWrite("usr10101", 1) - assert.Errorf(t, err, " : /sys/class/leds/beaglebone:green:usr10101/brightness: no such file") + assert.Error(t, err, " : /sys/class/leds/beaglebone:green:usr10101/brightness: no such file") _ = a.DigitalWrite("P9_12", 1) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio60/value"].Contents) - assert.Errorf(t, a.DigitalWrite("P9_99", 1), "'P9_99' is not a valid id for a digital pin") + assert.Error(t, a.DigitalWrite("P9_99", 1), "'P9_99' is not a valid id for a digital pin") _, err = a.DigitalRead("P9_99") - assert.Errorf(t, err, "'P9_99' is not a valid id for a digital pin") + assert.Error(t, err, "'P9_99' is not a valid id for a digital pin") fs.Files["/sys/class/gpio/gpio66/value"].Contents = "1" i, err := a.DigitalRead("P8_07") diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index f235930a6..3df2bfb67 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -105,7 +105,7 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("TWI2-SDA") assert.Equal(t, 1, i) - assert.Errorf(t, a.DigitalWrite("XIO-P10", 1), "'XIO-P10' is not a valid id for a digital pin") + assert.Error(t, a.DigitalWrite("XIO-P10", 1), "'XIO-P10' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } @@ -120,7 +120,7 @@ func TestProDigitalIO(t *testing.T) { i, _ := a.DigitalRead("TWI2-SDA") assert.Equal(t, 1, i) - assert.Errorf(t, a.DigitalWrite("XIO-P0", 1), "'XIO-P0' is not a valid id for a digital pin") + assert.Error(t, a.DigitalWrite("XIO-P0", 1), "'XIO-P0' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } diff --git a/platforms/digispark/digispark_adaptor_test.go b/platforms/digispark/digispark_adaptor_test.go index 7f5fc36d3..011a8d7e0 100644 --- a/platforms/digispark/digispark_adaptor_test.go +++ b/platforms/digispark/digispark_adaptor_test.go @@ -112,7 +112,7 @@ func TestDigisparkAdaptorDigitalWrite(t *testing.T) { errorFunc = func() error { return errors.New("pin mode error") } err = a.DigitalWrite("0", uint8(1)) - assert.Errorf(t, err, "pin mode error") + assert.Error(t, err, "pin mode error") } func TestDigisparkAdaptorServoWrite(t *testing.T) { @@ -125,7 +125,7 @@ func TestDigisparkAdaptorServoWrite(t *testing.T) { a = initTestAdaptor() errorFunc = func() error { return errors.New("servo error") } err = a.ServoWrite("2", uint8(80)) - assert.Errorf(t, err, "servo error") + assert.Error(t, err, "servo error") } func TestDigisparkAdaptorPwmWrite(t *testing.T) { @@ -138,10 +138,10 @@ func TestDigisparkAdaptorPwmWrite(t *testing.T) { a = initTestAdaptor() pwmInitErrorFunc = func() error { return errors.New("pwminit error") } err = a.PwmWrite("1", uint8(100)) - assert.Errorf(t, err, "pwminit error") + assert.Error(t, err, "pwminit error") a = initTestAdaptor() errorFunc = func() error { return errors.New("pwm error") } err = a.PwmWrite("1", uint8(100)) - assert.Errorf(t, err, "pwm error") + assert.Error(t, err, "pwm error") } diff --git a/platforms/digispark/digispark_i2c_test.go b/platforms/digispark/digispark_i2c_test.go index 9b5ccbeec..bf2a627b6 100644 --- a/platforms/digispark/digispark_i2c_test.go +++ b/platforms/digispark/digispark_i2c_test.go @@ -57,7 +57,7 @@ func TestDigisparkAdaptorI2cGetI2cConnectionFailWithInvalidBus(t *testing.T) { c, err := a.GetI2cConnection(0x40, 1) // assert - assert.Errorf(t, err, "Invalid bus number 1, only 0 is supported") + assert.Error(t, err, "Invalid bus number 1, only 0 is supported") assert.Nil(t, c) } @@ -72,7 +72,7 @@ func TestDigisparkAdaptorI2cStartFailWithWrongAddress(t *testing.T) { // assert assert.Equal(t, 0, count) - assert.Errorf(t, err, "Invalid address, only %d is supported", availableI2cAddress) + assert.Error(t, err, "Invalid address, only %d is supported", availableI2cAddress) assert.Equal(t, maxUint8, a.littleWire.(*i2cMock).direction) } diff --git a/platforms/dragonboard/dragonboard_adaptor_test.go b/platforms/dragonboard/dragonboard_adaptor_test.go index acf7117f4..40215c49b 100644 --- a/platforms/dragonboard/dragonboard_adaptor_test.go +++ b/platforms/dragonboard/dragonboard_adaptor_test.go @@ -54,7 +54,7 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("GPIO_A") assert.Equal(t, 1, i) - assert.Errorf(t, a.DigitalWrite("GPIO_M", 1), "'GPIO_M' is not a valid id for a digital pin") + assert.Error(t, a.DigitalWrite("GPIO_M", 1), "'GPIO_M' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } diff --git a/platforms/firmata/firmata_adaptor_test.go b/platforms/firmata/firmata_adaptor_test.go index f943e57af..091f9b1b6 100644 --- a/platforms/firmata/firmata_adaptor_test.go +++ b/platforms/firmata/firmata_adaptor_test.go @@ -115,7 +115,7 @@ func TestAdaptorFinalize(t *testing.T) { a = initTestAdaptor() a.Board.(*mockFirmataBoard).disconnectError = errors.New("close error") - assert.Errorf(t, a.Finalize(), "close error") + assert.Error(t, a.Finalize(), "close error") } func TestAdaptorConnect(t *testing.T) { @@ -132,7 +132,7 @@ func TestAdaptorConnect(t *testing.T) { a.PortOpener = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - assert.Errorf(t, a.Connect(), "connect error") + assert.Error(t, a.Connect(), "connect error") a = NewAdaptor(&readWriteCloser{}) a.Board = newMockFirmataBoard() diff --git a/platforms/firmata/firmata_i2c_test.go b/platforms/firmata/firmata_i2c_test.go index 4bc3c55fd..f7d758085 100644 --- a/platforms/firmata/firmata_i2c_test.go +++ b/platforms/firmata/firmata_i2c_test.go @@ -243,5 +243,5 @@ func TestDefaultBus(t *testing.T) { func TestGetI2cConnectionInvalidBus(t *testing.T) { a := NewAdaptor() _, err := a.GetI2cConnection(0x01, 99) - assert.Errorf(t, err, "Invalid bus number 99, only 0 is supported") + assert.Error(t, err, "Invalid bus number 99, only 0 is supported") } diff --git a/platforms/intel-iot/curie/imu_driver_test.go b/platforms/intel-iot/curie/imu_driver_test.go index 30eb76413..a7f9c1692 100644 --- a/platforms/intel-iot/curie/imu_driver_test.go +++ b/platforms/intel-iot/curie/imu_driver_test.go @@ -123,7 +123,7 @@ func TestIMUDriverReadAccelerometer(t *testing.T) { func TestIMUDriverReadAccelerometerData(t *testing.T) { _, err := parseAccelerometerData([]byte{}) - assert.Errorf(t, err, "Invalid data") + assert.Error(t, err, "Invalid data") result, err := parseAccelerometerData([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) assert.Nil(t, err) @@ -138,7 +138,7 @@ func TestIMUDriverReadGyroscope(t *testing.T) { func TestIMUDriverReadGyroscopeData(t *testing.T) { _, err := parseGyroscopeData([]byte{}) - assert.Errorf(t, err, "Invalid data") + assert.Error(t, err, "Invalid data") result, err := parseGyroscopeData([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) assert.Nil(t, err) @@ -153,7 +153,7 @@ func TestIMUDriverReadTemperature(t *testing.T) { func TestIMUDriverReadTemperatureData(t *testing.T) { _, err := parseTemperatureData([]byte{}) - assert.Errorf(t, err, "Invalid data") + assert.Error(t, err, "Invalid data") result, err := parseTemperatureData([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7}) assert.Nil(t, err) @@ -168,7 +168,7 @@ func TestIMUDriverEnableShockDetection(t *testing.T) { func TestIMUDriverShockDetectData(t *testing.T) { _, err := parseShockData([]byte{}) - assert.Errorf(t, err, "Invalid data") + assert.Error(t, err, "Invalid data") result, err := parseShockData([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7}) assert.Nil(t, err) @@ -183,7 +183,7 @@ func TestIMUDriverEnableStepCounter(t *testing.T) { func TestIMUDriverStepCountData(t *testing.T) { _, err := parseStepData([]byte{}) - assert.Errorf(t, err, "Invalid data") + assert.Error(t, err, "Invalid data") result, err := parseStepData([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7}) assert.Nil(t, err) @@ -198,7 +198,7 @@ func TestIMUDriverEnableTapDetection(t *testing.T) { func TestIMUDriverTapDetectData(t *testing.T) { _, err := parseTapData([]byte{}) - assert.Errorf(t, err, "Invalid data") + assert.Error(t, err, "Invalid data") result, err := parseTapData([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7}) assert.Nil(t, err) @@ -213,7 +213,7 @@ func TestIMUDriverEnableReadMotion(t *testing.T) { func TestIMUDriverReadMotionData(t *testing.T) { _, err := parseMotionData([]byte{}) - assert.Errorf(t, err, "Invalid data") + assert.Error(t, err, "Invalid data") result, err := parseMotionData([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) assert.Nil(t, err) diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index d27024a4d..8b4af0a2c 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -276,7 +276,7 @@ func TestArduinoI2CSetupFailTristate(t *testing.T) { fs.WithWriteError = true err := a.arduinoI2CSetup() - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestArduinoI2CSetupFail14(t *testing.T) { @@ -453,7 +453,7 @@ func TestDigitalWriteError(t *testing.T) { fs.WithWriteError = true err := a.DigitalWrite("13", 1) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestDigitalReadWriteError(t *testing.T) { @@ -461,7 +461,7 @@ func TestDigitalReadWriteError(t *testing.T) { fs.WithWriteError = true _, err := a.DigitalRead("13") - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestPwm(t *testing.T) { @@ -472,7 +472,7 @@ func TestPwm(t *testing.T) { assert.Equal(t, "1960", fs.Files["/sys/class/pwm/pwmchip0/pwm1/duty_cycle"].Contents) err = a.PwmWrite("7", 100) - assert.Errorf(t, err, "'7' is not a valid id for a PWM pin") + assert.Error(t, err, "'7' is not a valid id for a PWM pin") } func TestPwmExportError(t *testing.T) { @@ -501,7 +501,7 @@ func TestPwmWritePinError(t *testing.T) { fs.WithWriteError = true err := a.PwmWrite("5", 100) - assert.Errorf(t, err, "write error") + assert.Error(t, err, "write error") } func TestPwmWriteError(t *testing.T) { @@ -533,7 +533,7 @@ func TestAnalogError(t *testing.T) { fs.WithReadError = true _, err := a.AnalogRead("0") - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } func TestI2cWorkflow(t *testing.T) { diff --git a/platforms/intel-iot/joule/joule_adaptor_test.go b/platforms/intel-iot/joule/joule_adaptor_test.go index 3ef493fb1..b629d0203 100644 --- a/platforms/intel-iot/joule/joule_adaptor_test.go +++ b/platforms/intel-iot/joule/joule_adaptor_test.go @@ -133,7 +133,7 @@ func TestDigitalIO(t *testing.T) { assert.Equal(t, 0, i) _, err = a.DigitalRead("P9_99") - assert.Errorf(t, err, "'P9_99' is not a valid id for a digital pin") + assert.Error(t, err, "'P9_99' is not a valid id for a digital pin") } func TestPwm(t *testing.T) { @@ -144,10 +144,10 @@ func TestPwm(t *testing.T) { assert.Equal(t, "3921568", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) err = a.PwmWrite("4", 100) - assert.Errorf(t, err, "'4' is not a valid id for a pin") + assert.Error(t, err, "'4' is not a valid id for a pin") err = a.PwmWrite("J12_1", 100) - assert.Errorf(t, err, "'J12_1' is not a valid id for a PWM pin") + assert.Error(t, err, "'J12_1' is not a valid id for a PWM pin") } func TestPwmPinExportError(t *testing.T) { diff --git a/platforms/jetson/jetson_adaptor_test.go b/platforms/jetson/jetson_adaptor_test.go index 6ba241227..69a4f55f8 100644 --- a/platforms/jetson/jetson_adaptor_test.go +++ b/platforms/jetson/jetson_adaptor_test.go @@ -67,7 +67,7 @@ func TestPWMPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) err := a.PwmWrite("33", 1) - assert.Errorf(t, err, "not connected") + assert.Error(t, err, "not connected") err = a.Connect() assert.Nil(t, err) @@ -117,7 +117,7 @@ func TestDigitalIO(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 1, i) - assert.Errorf(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid id for a digital pin") + assert.Error(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } diff --git a/platforms/jetson/pwm_pin_test.go b/platforms/jetson/pwm_pin_test.go index 1c9cede1e..f379c99a6 100644 --- a/platforms/jetson/pwm_pin_test.go +++ b/platforms/jetson/pwm_pin_test.go @@ -4,6 +4,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) @@ -12,18 +14,35 @@ var _ gobot.PWMPinner = (*PWMPin)(nil) func TestPwmPin(t *testing.T) { a := system.NewAccesser() + const ( + exportPath = "/sys/class/pwm/pwmchip0/export" + unexportPath = "/sys/class/pwm/pwmchip0/unexport" + enablePath = "/sys/class/pwm/pwmchip0/pwm3/enable" + periodPath = "/sys/class/pwm/pwmchip0/pwm3/period" + dutyCyclePath = "/sys/class/pwm/pwmchip0/pwm3/duty_cycle" + ) mockPaths := []string{ - "/sys/class/pwm/pwmchip0/export", - "/sys/class/pwm/pwmchip0/unexport", - "/sys/class/pwm/pwmchip0/pwm0/enable", - "/sys/class/pwm/pwmchip0/pwm0/period", - "/sys/class/pwm/pwmchip0/pwm0/duty_cycle", + exportPath, + unexportPath, + enablePath, + periodPath, + dutyCyclePath, } - a.UseMockFilesystem(mockPaths) + fs := a.UseMockFilesystem(mockPaths) + + pin := NewPWMPin(a, "/sys/class/pwm/pwmchip0", "3") + require.Equal(t, "", fs.Files[exportPath].Contents) + require.Equal(t, "", fs.Files[unexportPath].Contents) + require.Equal(t, "", fs.Files[enablePath].Contents) + require.Equal(t, "", fs.Files[periodPath].Contents) + require.Equal(t, "", fs.Files[dutyCyclePath].Contents) - pin := NewPWMPin(a, "/sys/class/pwm/pwmchip0", "0") assert.Nil(t, pin.Export()) + assert.Equal(t, "3", fs.Files[exportPath].Contents) + assert.Nil(t, pin.SetEnabled(true)) + assert.Equal(t, "1", fs.Files[enablePath].Contents) + val, _ := pin.Polarity() assert.True(t, val) assert.Nil(t, pin.SetPolarity(false)) @@ -31,24 +50,30 @@ func TestPwmPin(t *testing.T) { assert.True(t, val) _, err := pin.Period() - assert.Errorf(t, err, "Jetson PWM pin period not set") - assert.Errorf(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") + assert.Error(t, err, "Jetson PWM pin period not set") + assert.Error(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") + assert.Equal(t, "", fs.Files[dutyCyclePath].Contents) assert.Nil(t, pin.SetPeriod(20000000)) + // TODO: see PR #990 assert.Equal(t, "20000000", fs.Files[periodPath].Contents) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) - assert.Errorf(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") + assert.Error(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") + // TODO: see PR #990 assert.Equal(t, "20000000", fs.Files[periodPath].Contents) dc, _ := pin.DutyCycle() assert.Equal(t, uint32(0), dc) assert.Nil(t, pin.SetDutyCycle(10000)) + assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) - assert.Errorf(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") + assert.Error(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") dc, _ = pin.DutyCycle() + assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) assert.Equal(t, uint32(10000), dc) assert.Nil(t, pin.Unexport()) + assert.Equal(t, "3", fs.Files[unexportPath].Contents) } diff --git a/platforms/leap/leap_motion_adaptor_test.go b/platforms/leap/leap_motion_adaptor_test.go index 0b4ef1c9e..7b4211bd7 100644 --- a/platforms/leap/leap_motion_adaptor_test.go +++ b/platforms/leap/leap_motion_adaptor_test.go @@ -37,7 +37,7 @@ func TestLeapMotionAdaptorConnect(t *testing.T) { a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") } - assert.Errorf(t, a.Connect(), "connection error") + assert.Error(t, a.Connect(), "connection error") } func TestLeapMotionAdaptorFinalize(t *testing.T) { diff --git a/platforms/mavlink/mavlink_adaptor_test.go b/platforms/mavlink/mavlink_adaptor_test.go index 91408b295..5c2784e55 100644 --- a/platforms/mavlink/mavlink_adaptor_test.go +++ b/platforms/mavlink/mavlink_adaptor_test.go @@ -69,7 +69,7 @@ func TestMavlinkAdaptorConnect(t *testing.T) { assert.Nil(t, a.Connect()) a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - assert.Errorf(t, a.Connect(), "connect error") + assert.Error(t, a.Connect(), "connect error") } func TestMavlinkAdaptorFinalize(t *testing.T) { @@ -79,5 +79,5 @@ func TestMavlinkAdaptorFinalize(t *testing.T) { testAdaptorClose = func() error { return errors.New("close error") } - assert.Errorf(t, a.Finalize(), "close error") + assert.Error(t, a.Finalize(), "close error") } diff --git a/platforms/mavlink/mavlink_udp_adaptor_test.go b/platforms/mavlink/mavlink_udp_adaptor_test.go index 0bec533c8..18a181fcd 100644 --- a/platforms/mavlink/mavlink_udp_adaptor_test.go +++ b/platforms/mavlink/mavlink_udp_adaptor_test.go @@ -136,5 +136,5 @@ func TestMavlinkReadMAVLinkPacketReadError(t *testing.T) { a.sock = m _, err := a.ReadMAVLinkPacket() - assert.Errorf(t, err, "read error") + assert.Error(t, err, "read error") } diff --git a/platforms/microbit/io_pin_driver_test.go b/platforms/microbit/io_pin_driver_test.go index e04eb1faa..193828a76 100644 --- a/platforms/microbit/io_pin_driver_test.go +++ b/platforms/microbit/io_pin_driver_test.go @@ -49,7 +49,7 @@ func TestIOPinDriverStartError(t *testing.T) { a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { return nil, errors.New("read error") }) - assert.Errorf(t, d.Start(), "read error") + assert.Error(t, d.Start(), "read error") } func TestIOPinDriverDigitalRead(t *testing.T) { @@ -74,7 +74,7 @@ func TestIOPinDriverDigitalReadInvalidPin(t *testing.T) { assert.NotNil(t, err) _, err = d.DigitalRead("6") - assert.Errorf(t, err, "Invalid pin.") + assert.Error(t, err, "Invalid pin.") } func TestIOPinDriverDigitalWrite(t *testing.T) { @@ -90,7 +90,7 @@ func TestIOPinDriverDigitalWriteInvalidPin(t *testing.T) { d := NewIOPinDriver(a) assert.NotNil(t, d.DigitalWrite("A3", 1)) - assert.Errorf(t, d.DigitalWrite("6", 1), "Invalid pin.") + assert.Error(t, d.DigitalWrite("6", 1), "Invalid pin.") } func TestIOPinDriverAnalogRead(t *testing.T) { @@ -115,7 +115,7 @@ func TestIOPinDriverAnalogReadInvalidPin(t *testing.T) { assert.NotNil(t, err) _, err = d.AnalogRead("6") - assert.Errorf(t, err, "Invalid pin.") + assert.Error(t, err, "Invalid pin.") } func TestIOPinDriverDigitalAnalogRead(t *testing.T) { diff --git a/platforms/mqtt/mqtt_adaptor_test.go b/platforms/mqtt/mqtt_adaptor_test.go index b36a4e4eb..b04e99d6c 100644 --- a/platforms/mqtt/mqtt_adaptor_test.go +++ b/platforms/mqtt/mqtt_adaptor_test.go @@ -85,7 +85,7 @@ func TestMqttAdaptorConnectSSLError(t *testing.T) { func TestMqttAdaptorConnectWithAuthError(t *testing.T) { a := NewAdaptorWithAuth("xyz://localhost:1883", "client", "user", "pass") - assert.Errorf(t, a.Connect(), "network Error : unknown protocol") + assert.Error(t, a.Connect(), "network Error : unknown protocol") } func TestMqttAdaptorFinalize(t *testing.T) { diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index 3953b6189..8955cb039 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -92,7 +92,7 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("10") assert.Equal(t, 1, i) - assert.Errorf(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.Error(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } @@ -101,16 +101,16 @@ func TestInvalidPWMPin(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("666", 42) - assert.Errorf(t, err, "'666' is not a valid id for a PWM pin") + assert.Error(t, err, "'666' is not a valid id for a PWM pin") err = a.ServoWrite("666", 120) - assert.Errorf(t, err, "'666' is not a valid id for a PWM pin") + assert.Error(t, err, "'666' is not a valid id for a PWM pin") err = a.PwmWrite("3", 42) - assert.Errorf(t, err, "'3' is not a valid id for a PWM pin") + assert.Error(t, err, "'3' is not a valid id for a PWM pin") err = a.ServoWrite("3", 120) - assert.Errorf(t, err, "'3' is not a valid id for a PWM pin") + assert.Error(t, err, "'3' is not a valid id for a PWM pin") } func TestPwmWrite(t *testing.T) { diff --git a/platforms/nats/nats_adaptor_test.go b/platforms/nats/nats_adaptor_test.go index 9ab2dcbde..1b095f1ed 100644 --- a/platforms/nats/nats_adaptor_test.go +++ b/platforms/nats/nats_adaptor_test.go @@ -148,7 +148,7 @@ func TestNatsAdaptorFailedConnect(t *testing.T) { if err != nil && strings.Contains(err.Error(), "cannot assign requested address") { t.Skip("FLAKY: Can not test, because IP or port is in use.") } - assert.Errorf(t, err, "nats: no servers available for connection") + assert.Error(t, err, "nats: no servers available for connection") } func TestNatsAdaptorFinalize(t *testing.T) { diff --git a/platforms/neurosky/neurosky_adaptor_test.go b/platforms/neurosky/neurosky_adaptor_test.go index 2089d16d4..4ef684a4a 100644 --- a/platforms/neurosky/neurosky_adaptor_test.go +++ b/platforms/neurosky/neurosky_adaptor_test.go @@ -74,7 +74,7 @@ func TestNeuroskyAdaptorConnect(t *testing.T) { a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") } - assert.Errorf(t, a.Connect(), "connection error") + assert.Error(t, a.Connect(), "connection error") } func TestNeuroskyAdaptorFinalize(t *testing.T) { @@ -88,5 +88,5 @@ func TestNeuroskyAdaptorFinalize(t *testing.T) { rwc.CloseError(errors.New("close error")) _ = a.Connect() - assert.Errorf(t, a.Finalize(), "close error") + assert.Error(t, a.Finalize(), "close error") } diff --git a/platforms/parrot/ardrone/ardrone_adaptor_test.go b/platforms/parrot/ardrone/ardrone_adaptor_test.go index bcfd75357..79893577f 100644 --- a/platforms/parrot/ardrone/ardrone_adaptor_test.go +++ b/platforms/parrot/ardrone/ardrone_adaptor_test.go @@ -34,7 +34,7 @@ func TestArdroneAdaptorConnect(t *testing.T) { a.connect = func(a *Adaptor) (drone, error) { return nil, errors.New("connection error") } - assert.Errorf(t, a.Connect(), "connection error") + assert.Error(t, a.Connect(), "connection error") } func TestArdroneAdaptorName(t *testing.T) { diff --git a/platforms/parrot/bebop/bebop_adaptor_test.go b/platforms/parrot/bebop/bebop_adaptor_test.go index a2ebba5ef..061ee871a 100644 --- a/platforms/parrot/bebop/bebop_adaptor_test.go +++ b/platforms/parrot/bebop/bebop_adaptor_test.go @@ -34,7 +34,7 @@ func TestBebopAdaptorConnect(t *testing.T) { a.connect = func(a *Adaptor) error { return errors.New("connection error") } - assert.Errorf(t, a.Connect(), "connection error") + assert.Error(t, a.Connect(), "connection error") } func TestBebopAdaptorFinalize(t *testing.T) { diff --git a/platforms/particle/adaptor_test.go b/platforms/particle/adaptor_test.go index e1e028a53..e9f4de075 100644 --- a/platforms/particle/adaptor_test.go +++ b/platforms/particle/adaptor_test.go @@ -254,7 +254,7 @@ func TestAdaptorFunction(t *testing.T) { a.setAPIServer(testServer.URL) _, err := a.Function("hello", "") - assert.Errorf(t, err, "timeout") + assert.Error(t, err, "timeout") testServer.Close() } @@ -309,7 +309,7 @@ func TestAdaptorVariable(t *testing.T) { a.setAPIServer(testServer.URL) _, err := a.Variable("not_existent") - assert.Errorf(t, err, "Variable not found") + assert.Error(t, err, "Variable not found") testServer.Close() } @@ -386,14 +386,14 @@ func TestAdaptorEventStream(t *testing.T) { assert.Equal(t, "https://api.particle.io/v1/devices/myDevice/events/ping?access_token=token", url) _, err := a.EventStream("nothing", "ping") - assert.Errorf(t, err, "source param should be: all, devices or device") + assert.Error(t, err, "source param should be: all, devices or device") eventSource = func(u string) (chan eventsource.Event, chan error, error) { return nil, nil, errors.New("error connecting sse") } _, err = a.EventStream("devices", "") - assert.Errorf(t, err, "error connecting sse") + assert.Error(t, err, "error connecting sse") eventChan := make(chan eventsource.Event) errorChan := make(chan error) diff --git a/platforms/raspi/pwm_pin_test.go b/platforms/raspi/pwm_pin_test.go index 080d4a862..9823b6120 100644 --- a/platforms/raspi/pwm_pin_test.go +++ b/platforms/raspi/pwm_pin_test.go @@ -29,13 +29,13 @@ func TestPwmPin(t *testing.T) { assert.True(t, val) _, err := pin.Period() - assert.Errorf(t, err, "Raspi PWM pin period not set") - assert.Errorf(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") + assert.Error(t, err, "Raspi PWM pin period not set") + assert.Error(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") assert.Nil(t, pin.SetPeriod(20000000)) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) - assert.Errorf(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") + assert.Error(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") dc, _ := pin.DutyCycle() assert.Equal(t, uint32(0), dc) @@ -45,7 +45,7 @@ func TestPwmPin(t *testing.T) { dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) - assert.Errorf(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") + assert.Error(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index 17cbb5b03..8c8444fe8 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -125,8 +125,8 @@ func TestDigitalPWM(t *testing.T) { assert.Equal(t, "17=0.5", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - assert.Errorf(t, a.PwmWrite("notexist", 1), "Not a valid pin") - assert.Errorf(t, a.ServoWrite("notexist", 1), "Not a valid pin") + assert.Error(t, a.PwmWrite("notexist", 1), "Not a valid pin") + assert.Error(t, a.ServoWrite("notexist", 1), "Not a valid pin") pin, _ = a.PWMPin("12") period, _ = pin.Period() @@ -160,7 +160,7 @@ func TestDigitalIO(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 1, i) - assert.Errorf(t, a.DigitalWrite("notexist", 1), "Not a valid pin") + assert.Error(t, a.DigitalWrite("notexist", 1), "Not a valid pin") assert.Nil(t, a.Finalize()) } diff --git a/platforms/sphero/sphero_adaptor_test.go b/platforms/sphero/sphero_adaptor_test.go index ea9224a9f..d57ca05b7 100644 --- a/platforms/sphero/sphero_adaptor_test.go +++ b/platforms/sphero/sphero_adaptor_test.go @@ -89,7 +89,7 @@ func TestSpheroAdaptorFinalize(t *testing.T) { } a.connected = true - assert.Errorf(t, a.Finalize(), "close error") + assert.Error(t, a.Finalize(), "close error") } func TestSpheroAdaptorConnect(t *testing.T) { @@ -100,5 +100,5 @@ func TestSpheroAdaptorConnect(t *testing.T) { return nil, errors.New("connect error") } - assert.Errorf(t, a.Connect(), "connect error") + assert.Error(t, a.Connect(), "connect error") } diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 02ce04c1d..0f77be93a 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -92,7 +92,7 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("10") assert.Equal(t, 1, i) - assert.Errorf(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.Error(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } @@ -101,16 +101,16 @@ func TestInvalidPWMPin(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("666", 42) - assert.Errorf(t, err, "'666' is not a valid id for a PWM pin") + assert.Error(t, err, "'666' is not a valid id for a PWM pin") err = a.ServoWrite("666", 120) - assert.Errorf(t, err, "'666' is not a valid id for a PWM pin") + assert.Error(t, err, "'666' is not a valid id for a PWM pin") err = a.PwmWrite("3", 42) - assert.Errorf(t, err, "'3' is not a valid id for a PWM pin") + assert.Error(t, err, "'3' is not a valid id for a PWM pin") err = a.ServoWrite("3", 120) - assert.Errorf(t, err, "'3' is not a valid id for a PWM pin") + assert.Error(t, err, "'3' is not a valid id for a PWM pin") } func TestPwmWrite(t *testing.T) { diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index d81836dcc..b1a7b5f26 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -77,7 +77,7 @@ func TestDigitalIO(t *testing.T) { fs.Files["/sys/class/leds/upboard:green:/brightness"].Contents, ) - assert.Errorf(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.Error(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index 4079a45da..c5f35cd37 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -57,10 +57,10 @@ func TestDigitalPin(t *testing.T) { pin2 := newDigitalPinSysfs(fs, "30") err = pin2.Write(1) - assert.Errorf(t, err, "pin has not been exported") + assert.Error(t, err, "pin has not been exported") data, err = pin2.Read() - assert.Errorf(t, err, "pin has not been exported") + assert.Error(t, err, "pin has not been exported") assert.Equal(t, 0, data) writeFile = func(File, []byte) (int, error) { @@ -75,7 +75,7 @@ func TestDigitalPin(t *testing.T) { } err = pin.Unexport() - assert.Errorf(t, err.(*os.PathError).Err, "write error") + assert.Error(t, err.(*os.PathError).Err, "write error") // assert a busy error is dropped (just means "already exported") cnt := 0 @@ -94,7 +94,7 @@ func TestDigitalPin(t *testing.T) { return 0, &os.PathError{Err: errors.New("write error")} } err = pin.Export() - assert.Errorf(t, err.(*os.PathError).Err, "write error") + assert.Error(t, err.(*os.PathError).Err, "write error") } func TestDigitalPinExportError(t *testing.T) { @@ -109,7 +109,7 @@ func TestDigitalPinExportError(t *testing.T) { } err := pin.Export() - assert.Errorf(t, err, " : /sys/class/gpio/gpio10/direction: no such file") + assert.Error(t, err, " : /sys/class/gpio/gpio10/direction: no such file") } func TestDigitalPinUnexportError(t *testing.T) { @@ -123,5 +123,5 @@ func TestDigitalPinUnexportError(t *testing.T) { } err := pin.Unexport() - assert.Errorf(t, err, " : device or resource busy") + assert.Error(t, err, " : device or resource busy") } diff --git a/system/fs_mock_test.go b/system/fs_mock_test.go index dca212b19..7e48cb24c 100644 --- a/system/fs_mock_test.go +++ b/system/fs_mock_test.go @@ -20,7 +20,7 @@ func TestMockFilesystemOpen(t *testing.T) { assert.Nil(t, err) _, err = fs.openFile("bar", 0, 0o666) - assert.Errorf(t, err, " : bar: no such file") + assert.Error(t, err, " : bar: no such file") fs.Add("bar") f4, _ := fs.openFile("bar", 0, 0o666) @@ -39,7 +39,7 @@ func TestMockFilesystemStat(t *testing.T) { assert.True(t, dirStat.IsDir()) _, err = fs.stat("plonk") - assert.Errorf(t, err, " : plonk: no such file") + assert.Error(t, err, " : plonk: no such file") } func TestMockFilesystemFind(t *testing.T) { diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index 78682ec40..1e41a83a1 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -79,7 +79,7 @@ func TestNewI2cDevice(t *testing.T) { d, err := a.NewI2cDevice(tc.dev) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) assert.Equal(t, (*i2cDevice)(nil), d) } else { var _ gobot.I2cSystemDevicer = d @@ -142,7 +142,7 @@ func TestReadByte(t *testing.T) { got, err := d.ReadByte(2) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, want, got) @@ -189,7 +189,7 @@ func TestReadByteData(t *testing.T) { got, err := d.ReadByteData(3, reg) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, want, got) @@ -239,7 +239,7 @@ func TestReadWordData(t *testing.T) { got, err := d.ReadWordData(4, reg) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, want, got) @@ -297,7 +297,7 @@ func TestReadBlockData(t *testing.T) { err := d.ReadBlockData(5, reg, buf) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, msc.dataSlice, buf) @@ -341,7 +341,7 @@ func TestWriteByte(t *testing.T) { err := d.WriteByte(6, val) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, d.file, msc.lastFile) @@ -386,7 +386,7 @@ func TestWriteByteData(t *testing.T) { err := d.WriteByteData(7, reg, val) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, d.file, msc.lastFile) @@ -435,7 +435,7 @@ func TestWriteWordData(t *testing.T) { err := d.WriteWordData(8, reg, val) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, d.file, msc.lastFile) @@ -492,7 +492,7 @@ func TestWriteBlockData(t *testing.T) { err := d.WriteBlockData(9, reg, data) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, d.file, msc.lastFile) @@ -514,7 +514,7 @@ func TestWriteBlockDataTooMuch(t *testing.T) { // act err := d.WriteBlockData(10, 0x01, make([]byte, 33)) // assert - assert.Errorf(t, err, "Writing blocks larger than 32 bytes (33) not supported") + assert.Error(t, err, "Writing blocks larger than 32 bytes (33) not supported") } func Test_setAddress(t *testing.T) { @@ -565,7 +565,7 @@ func Test_queryFunctionality(t *testing.T) { err := d.queryFunctionality(tc.requested, "test"+name) // assert if tc.wantErr != "" { - assert.Errorf(t, err, tc.wantErr) + assert.Error(t, err, tc.wantErr) } else { assert.Nil(t, err) } diff --git a/system/pwmpin_sysfs_test.go b/system/pwmpin_sysfs_test.go index ba3a84c48..ebc901333 100644 --- a/system/pwmpin_sysfs_test.go +++ b/system/pwmpin_sysfs_test.go @@ -56,7 +56,7 @@ func TestPwmPin(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents) err = pin.SetPolarity(true) - assert.Errorf(t, err, "Cannot set PWM polarity when enabled") + assert.Error(t, err, "Cannot set PWM polarity when enabled") fs.Files["/sys/class/pwm/pwmchip0/pwm10/period"].Contents = "6" data, _ := pin.Period() @@ -107,7 +107,7 @@ func TestPwmPinExportError(t *testing.T) { // no error indicates that the pin was already exported err := pin.Export() - assert.Errorf(t, err, "Export() failed for id 10 with : bad address") + assert.Error(t, err, "Export() failed for id 10 with : bad address") } func TestPwmPinUnxportError(t *testing.T) { @@ -125,7 +125,7 @@ func TestPwmPinUnxportError(t *testing.T) { } err := pin.Unexport() - assert.Errorf(t, err, "Unexport() failed for id 10 with : device or resource busy") + assert.Error(t, err, "Unexport() failed for id 10 with : device or resource busy") } func TestPwmPinPeriodError(t *testing.T) { @@ -143,7 +143,7 @@ func TestPwmPinPeriodError(t *testing.T) { } _, err := pin.Period() - assert.Errorf(t, err, "Period() failed for id 10 with : device or resource busy") + assert.Error(t, err, "Period() failed for id 10 with : device or resource busy") } func TestPwmPinPolarityError(t *testing.T) { @@ -161,7 +161,7 @@ func TestPwmPinPolarityError(t *testing.T) { } _, err := pin.Polarity() - assert.Errorf(t, err, "Polarity() failed for id 10 with : device or resource busy") + assert.Error(t, err, "Polarity() failed for id 10 with : device or resource busy") } func TestPwmPinDutyCycleError(t *testing.T) { @@ -179,5 +179,5 @@ func TestPwmPinDutyCycleError(t *testing.T) { } _, err := pin.DutyCycle() - assert.Errorf(t, err, "DutyCycle() failed for id 10 with : device or resource busy") + assert.Error(t, err, "DutyCycle() failed for id 10 with : device or resource busy") } From f9950e247d1481dae4814bb5b57f0535ddd7a1ae Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Wed, 25 Oct 2023 20:21:18 +0200 Subject: [PATCH 12/57] test(all): substitude assert.Error by assert.ErrorContains (#1014) --- drivers/gpio/buzzer_driver_test.go | 6 ++--- drivers/gpio/direct_pin_driver_test.go | 18 +++++++-------- drivers/gpio/hd44780_driver_test.go | 18 +++++++-------- drivers/gpio/led_driver_test.go | 10 ++++----- drivers/gpio/rgb_led_driver_test.go | 10 ++++----- drivers/gpio/servo_driver_test.go | 8 +++---- drivers/gpio/stepper_driver_test.go | 2 +- drivers/i2c/adafruit1109_driver_test.go | 4 ++-- drivers/i2c/adafruit_driver_test.go | 18 +++++++-------- drivers/i2c/ads1x15_driver_1015_test.go | 18 +++++++-------- drivers/i2c/ads1x15_driver_1115_test.go | 18 +++++++-------- drivers/i2c/ads1x15_driver_test.go | 2 +- drivers/i2c/adxl345_driver_test.go | 4 ++-- drivers/i2c/bh1750_driver_test.go | 4 ++-- drivers/i2c/blinkm_driver_test.go | 8 +++---- drivers/i2c/bme280_driver_test.go | 10 ++++----- drivers/i2c/bmp180_driver_test.go | 6 ++--- drivers/i2c/bmp280_driver_test.go | 8 +++---- drivers/i2c/bmp388_driver_test.go | 8 +++---- drivers/i2c/drv2605l_driver_test.go | 4 ++-- drivers/i2c/hmc6352_driver_test.go | 4 ++-- drivers/i2c/i2c_connection_test.go | 18 +++++++-------- drivers/i2c/i2c_driver_test.go | 2 +- drivers/i2c/ina3221_driver_test.go | 8 +++---- drivers/i2c/jhd1313m1_driver_test.go | 16 +++++++------- drivers/i2c/l3gd20h_driver_test.go | 4 ++-- drivers/i2c/lidarlite_driver_test.go | 8 +++---- drivers/i2c/mcp23017_driver_test.go | 18 +++++++-------- drivers/i2c/mma7660_driver_test.go | 2 +- drivers/i2c/mpl115a2_driver_test.go | 2 +- drivers/i2c/mpu6050_driver_test.go | 4 ++-- drivers/i2c/pca9685_driver_test.go | 6 ++--- drivers/i2c/sht2x_driver_test.go | 4 ++-- drivers/i2c/ssd1306_driver_test.go | 4 ++-- drivers/i2c/tsl2561_driver_test.go | 10 ++++----- drivers/spi/mcp3002_test.go | 2 +- drivers/spi/mcp3004_test.go | 2 +- drivers/spi/mcp3008_test.go | 2 +- drivers/spi/mcp3202_test.go | 2 +- drivers/spi/mcp3204_test.go | 2 +- drivers/spi/mcp3208_test.go | 2 +- drivers/spi/mcp3304_test.go | 2 +- drivers/spi/ssd1306_driver_test.go | 2 +- platforms/adaptors/digitalpinsadaptor_test.go | 12 +++++----- platforms/adaptors/i2cbusadaptor_test.go | 4 ++-- platforms/adaptors/pwmpinsadaptor_test.go | 8 +++---- platforms/adaptors/spibusadaptor_test.go | 6 ++--- platforms/audio/audio_adaptor_test.go | 2 +- .../beaglebone/beaglebone_adaptor_test.go | 12 +++++----- platforms/chip/chip_adaptor_test.go | 4 ++-- platforms/digispark/digispark_adaptor_test.go | 8 +++---- platforms/digispark/digispark_i2c_test.go | 4 ++-- .../dragonboard/dragonboard_adaptor_test.go | 2 +- platforms/firmata/firmata_adaptor_test.go | 4 ++-- platforms/firmata/firmata_i2c_test.go | 2 +- platforms/intel-iot/curie/imu_driver_test.go | 14 ++++++------ .../intel-iot/edison/edison_adaptor_test.go | 12 +++++----- .../intel-iot/joule/joule_adaptor_test.go | 6 ++--- platforms/jetson/jetson_adaptor_test.go | 4 ++-- platforms/jetson/pwm_pin_test.go | 8 +++---- platforms/leap/leap_motion_adaptor_test.go | 2 +- platforms/mavlink/mavlink_adaptor_test.go | 4 ++-- platforms/mavlink/mavlink_udp_adaptor_test.go | 2 +- platforms/microbit/io_pin_driver_test.go | 8 +++---- platforms/mqtt/mqtt_adaptor_test.go | 2 +- platforms/nanopi/nanopi_adaptor_test.go | 10 ++++----- platforms/nats/nats_adaptor_test.go | 2 +- platforms/neurosky/neurosky_adaptor_test.go | 4 ++-- .../parrot/ardrone/ardrone_adaptor_test.go | 2 +- platforms/parrot/bebop/bebop_adaptor_test.go | 2 +- platforms/particle/adaptor_test.go | 8 +++---- platforms/raspi/pwm_pin_test.go | 8 +++---- platforms/raspi/raspi_adaptor_test.go | 6 ++--- platforms/sphero/sphero_adaptor_test.go | 4 ++-- platforms/tinkerboard/adaptor_test.go | 10 ++++----- platforms/upboard/up2/adaptor_test.go | 2 +- system/digitalpin_sysfs_test.go | 12 +++++----- system/fs_mock_test.go | 4 ++-- system/i2c_device_test.go | 22 +++++++++---------- system/pwmpin_sysfs_test.go | 12 +++++----- 80 files changed, 274 insertions(+), 274 deletions(-) diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index a6c371800..db2fd8ba4 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -57,7 +57,7 @@ func TestBuzzerDriverOnError(t *testing.T) { return errors.New("write error") }) - assert.Error(t, d.On(), "write error") + assert.ErrorContains(t, d.On(), "write error") } func TestBuzzerDriverOffError(t *testing.T) { @@ -67,7 +67,7 @@ func TestBuzzerDriverOffError(t *testing.T) { return errors.New("write error") }) - assert.Error(t, d.Off(), "write error") + assert.ErrorContains(t, d.Off(), "write error") } func TestBuzzerDriverToneError(t *testing.T) { @@ -77,5 +77,5 @@ func TestBuzzerDriverToneError(t *testing.T) { return errors.New("write error") }) - assert.Error(t, d.Tone(100, 0.01), "write error") + assert.ErrorContains(t, d.Tone(100, 0.01), "write error") } diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index 5aeeec020..90252f682 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -43,13 +43,13 @@ func TestDirectPinDriver(t *testing.T) { assert.Nil(t, ret["err"]) err = d.Command("DigitalWrite")(map[string]interface{}{"level": "1"}) - assert.Error(t, err.(error), "write error") + assert.ErrorContains(t, err.(error), "write error") err = d.Command("PwmWrite")(map[string]interface{}{"level": "1"}) - assert.Error(t, err.(error), "write error") + assert.ErrorContains(t, err.(error), "write error") err = d.Command("ServoWrite")(map[string]interface{}{"level": "1"}) - assert.Error(t, err.(error), "write error") + assert.ErrorContains(t, err.(error), "write error") } func TestDirectPinDriverStart(t *testing.T) { @@ -74,7 +74,7 @@ func TestDirectPinDriverOff(t *testing.T) { func TestDirectPinDriverOffNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Error(t, d.Off(), "DigitalWrite is not supported by this platform") + assert.ErrorContains(t, d.Off(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverOn(t *testing.T) { @@ -91,7 +91,7 @@ func TestDirectPinDriverOnError(t *testing.T) { func TestDirectPinDriverOnNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Error(t, d.On(), "DigitalWrite is not supported by this platform") + assert.ErrorContains(t, d.On(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWrite(t *testing.T) { @@ -103,7 +103,7 @@ func TestDirectPinDriverDigitalWrite(t *testing.T) { func TestDirectPinDriverDigitalWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Error(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") + assert.ErrorContains(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWriteError(t *testing.T) { @@ -122,7 +122,7 @@ func TestDirectPinDriverDigitalReadNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") _, e := d.DigitalRead() - assert.Error(t, e, "DigitalRead is not supported by this platform") + assert.ErrorContains(t, e, "DigitalRead is not supported by this platform") } func TestDirectPinDriverPwmWrite(t *testing.T) { @@ -134,7 +134,7 @@ func TestDirectPinDriverPwmWrite(t *testing.T) { func TestDirectPinDriverPwmWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Error(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") + assert.ErrorContains(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") } func TestDirectPinDriverPwmWriteError(t *testing.T) { @@ -151,7 +151,7 @@ func TestDirectPinDriverServoWrite(t *testing.T) { func TestDirectPinDriverServoWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.Error(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") + assert.ErrorContains(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") } func TestDirectPinDriverServoWriteError(t *testing.T) { diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index 4ac7ad98c..91f0541be 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -93,7 +93,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_4BITMODE, "13", "15", pins) - assert.Error(t, d.Start(), "Initialization error") + assert.ErrorContains(t, d.Start(), "Initialization error") pins = HD44780DataPin{ D0: "31", @@ -106,7 +106,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_8BITMODE, "13", "15", pins) - assert.Error(t, d.Start(), "Initialization error") + assert.ErrorContains(t, d.Start(), "Initialization error") } func TestHD44780DriverWrite(t *testing.T) { @@ -130,14 +130,14 @@ func TestHD44780DriverWriteError(t *testing.T) { return errors.New("write error") } _ = d.Start() - assert.Error(t, d.Write("hello gobot"), "write error") + assert.ErrorContains(t, d.Write("hello gobot"), "write error") d, a = initTestHD44780Driver8BitModeWithStubbedAdaptor() a.testAdaptorDigitalWrite = func(string, byte) (err error) { return errors.New("write error") } _ = d.Start() - assert.Error(t, d.Write("hello gobot"), "write error") + assert.ErrorContains(t, d.Write("hello gobot"), "write error") } func TestHD44780DriverClear(t *testing.T) { @@ -158,10 +158,10 @@ func TestHD44780DriverSetCursor(t *testing.T) { func TestHD44780DriverSetCursorInvalid(t *testing.T) { d := initTestHD44780Driver() - assert.Error(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") - assert.Error(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") - assert.Error(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") - assert.Error(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") + assert.ErrorContains(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") + assert.ErrorContains(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") + assert.ErrorContains(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") + assert.ErrorContains(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") } func TestHD44780DriverDisplayOn(t *testing.T) { @@ -233,5 +233,5 @@ func TestHD44780DriverCreateChar(t *testing.T) { func TestHD44780DriverCreateCharError(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - assert.Error(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") + assert.ErrorContains(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") } diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index 3d1877575..c3e7c2c48 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -38,16 +38,16 @@ func TestLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - assert.Error(t, err.(error), "write error") + assert.ErrorContains(t, err.(error), "write error") err = d.Command("On")(nil) - assert.Error(t, err.(error), "write error") + assert.ErrorContains(t, err.(error), "write error") err = d.Command("Off")(nil) - assert.Error(t, err.(error), "write error") + assert.ErrorContains(t, err.(error), "write error") err = d.Command("Brightness")(map[string]interface{}{"level": 100.0}) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") } func TestLedDriverStart(t *testing.T) { @@ -76,7 +76,7 @@ func TestLedDriverBrightness(t *testing.T) { err = errors.New("pwm error") return } - assert.Error(t, d.Brightness(150), "pwm error") + assert.ErrorContains(t, d.Brightness(150), "pwm error") } func TestLEDDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index dcae08b36..3aa0cc387 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -42,16 +42,16 @@ func TestRgbLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") err = d.Command("On")(nil) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") err = d.Command("Off")(nil) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") err = d.Command("SetRGB")(map[string]interface{}{"r": 0xff, "g": 0xff, "b": 0xff}) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") } func TestRgbLedDriverStart(t *testing.T) { @@ -83,7 +83,7 @@ func TestRgbLedDriverSetLevel(t *testing.T) { err = errors.New("pwm error") return } - assert.Error(t, d.SetLevel("1", 150), "pwm error") + assert.ErrorContains(t, d.SetLevel("1", 150), "pwm error") } func TestRgbLedDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index e93a7c3db..684646bf8 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -29,16 +29,16 @@ func TestServoDriver(t *testing.T) { } err = d.Command("Min")(nil) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") err = d.Command("Center")(nil) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") err = d.Command("Max")(nil) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") err = d.Command("Move")(map[string]interface{}{"angle": 100.0}) - assert.Error(t, err.(error), "pwm error") + assert.ErrorContains(t, err.(error), "pwm error") } func TestServoDriverStart(t *testing.T) { diff --git a/drivers/gpio/stepper_driver_test.go b/drivers/gpio/stepper_driver_test.go index 78aceef98..4c3271b6b 100644 --- a/drivers/gpio/stepper_driver_test.go +++ b/drivers/gpio/stepper_driver_test.go @@ -57,7 +57,7 @@ func TestStepperDriverDefaultDirection(t *testing.T) { func TestStepperDriverInvalidDirection(t *testing.T) { d := initStepperMotorDriver() err := d.SetDirection("reverse") - assert.Error(t, err, "Invalid direction. Value should be forward or backward") + assert.ErrorContains(t, err, "Invalid direction. Value should be forward or backward") } func TestStepperDriverMoveForward(t *testing.T) { diff --git a/drivers/i2c/adafruit1109_driver_test.go b/drivers/i2c/adafruit1109_driver_test.go index d9d812343..c3176beb0 100644 --- a/drivers/i2c/adafruit1109_driver_test.go +++ b/drivers/i2c/adafruit1109_driver_test.go @@ -73,7 +73,7 @@ func TestAdafruit1109StartWriteErr(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.Start(), "write error") + assert.ErrorContains(t, d.Start(), "write error") } func TestAdafruit1109StartReadErr(t *testing.T) { @@ -81,7 +81,7 @@ func TestAdafruit1109StartReadErr(t *testing.T) { adaptor.i2cReadImpl = func([]byte) (int, error) { return 0, errors.New("read error") } - assert.Error(t, d.Start(), "MCP write-read: MCP write-ReadByteData(reg=0): read error") + assert.ErrorContains(t, d.Start(), "MCP write-read: MCP write-ReadByteData(reg=0): read error") } func TestAdafruit1109Halt(t *testing.T) { diff --git a/drivers/i2c/adafruit_driver_test.go b/drivers/i2c/adafruit_driver_test.go index 0d94cffff..0835422f4 100644 --- a/drivers/i2c/adafruit_driver_test.go +++ b/drivers/i2c/adafruit_driver_test.go @@ -45,7 +45,7 @@ func TestAdafruitMotorHatDriverStartWriteError(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.Start(), "write error") + assert.ErrorContains(t, d.Start(), "write error") } func TestAdafruitMotorHatDriverStartReadError(t *testing.T) { @@ -53,13 +53,13 @@ func TestAdafruitMotorHatDriverStartReadError(t *testing.T) { adaptor.i2cReadImpl = func([]byte) (int, error) { return 0, errors.New("read error") } - assert.Error(t, d.Start(), "read error") + assert.ErrorContains(t, d.Start(), "read error") } func TestAdafruitMotorHatDriverStartConnectError(t *testing.T) { d, adaptor := initTestAdafruitMotorHatDriverWithStubbedAdaptor() adaptor.Testi2cConnectErr(true) - assert.Error(t, d.Start(), "Invalid i2c connection") + assert.ErrorContains(t, d.Start(), "Invalid i2c connection") } func TestAdafruitMotorHatDriverHalt(t *testing.T) { @@ -96,7 +96,7 @@ func TestAdafruitMotorHatDriverSetServoMotorFreqError(t *testing.T) { } freq := 60.0 - assert.Error(t, ada.SetServoMotorFreq(freq), "write error") + assert.ErrorContains(t, ada.SetServoMotorFreq(freq), "write error") } func TestAdafruitMotorHatDriverSetServoMotorPulse(t *testing.T) { @@ -122,7 +122,7 @@ func TestAdafruitMotorHatDriverSetServoMotorPulseError(t *testing.T) { var channel byte = 7 var on int32 = 1234 var off int32 = 4321 - assert.Error(t, ada.SetServoMotorPulse(channel, on, off), "write error") + assert.ErrorContains(t, ada.SetServoMotorPulse(channel, on, off), "write error") } func TestAdafruitMotorHatDriverSetDCMotorSpeed(t *testing.T) { @@ -144,7 +144,7 @@ func TestAdafruitMotorHatDriverSetDCMotorSpeedError(t *testing.T) { return 0, errors.New("write error") } - assert.Error(t, ada.SetDCMotorSpeed(1, 255), "write error") + assert.ErrorContains(t, ada.SetDCMotorSpeed(1, 255), "write error") } func TestAdafruitMotorHatDriverRunDCMotor(t *testing.T) { @@ -166,9 +166,9 @@ func TestAdafruitMotorHatDriverRunDCMotorError(t *testing.T) { } dcMotor := 1 - assert.Error(t, ada.RunDCMotor(dcMotor, AdafruitForward), "write error") - assert.Error(t, ada.RunDCMotor(dcMotor, AdafruitBackward), "write error") - assert.Error(t, ada.RunDCMotor(dcMotor, AdafruitRelease), "write error") + assert.ErrorContains(t, ada.RunDCMotor(dcMotor, AdafruitForward), "write error") + assert.ErrorContains(t, ada.RunDCMotor(dcMotor, AdafruitBackward), "write error") + assert.ErrorContains(t, ada.RunDCMotor(dcMotor, AdafruitRelease), "write error") } func TestAdafruitMotorHatDriverSetStepperMotorSpeed(t *testing.T) { diff --git a/drivers/i2c/ads1x15_driver_1015_test.go b/drivers/i2c/ads1x15_driver_1015_test.go index 285c5c499..66e772935 100644 --- a/drivers/i2c/ads1x15_driver_1015_test.go +++ b/drivers/i2c/ads1x15_driver_1015_test.go @@ -115,14 +115,14 @@ func TestADS1x15AnalogReadError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestADS1x15AnalogReadInvalidPin(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.AnalogRead("99") - assert.Error(t, err, "Invalid channel (99), must be between 0 and 3") + assert.ErrorContains(t, err, "Invalid channel (99), must be between 0 and 3") } func TestADS1x15AnalogReadWriteError(t *testing.T) { @@ -133,41 +133,41 @@ func TestADS1x15AnalogReadWriteError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") _, err = d.AnalogRead("0-1") - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") _, err = d.AnalogRead("2-3") - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestADS1x15ReadInvalidChannel(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(9, 1, 1600) - assert.Error(t, err, "Invalid channel (9), must be between 0 and 3") + assert.ErrorContains(t, err, "Invalid channel (9), must be between 0 and 3") } func TestADS1x15ReadInvalidGain(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(0, 8, 1600) - assert.Error(t, err, "Gain (8) must be one of: [0 1 2 3 4 5 6 7]") + assert.ErrorContains(t, err, "Gain (8) must be one of: [0 1 2 3 4 5 6 7]") } func TestADS1x15ReadInvalidDataRate(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(0, 1, 321) - assert.Error(t, err, "Invalid data rate (321). Accepted values: [128 250 490 920 1600 2400 3300]") + assert.ErrorContains(t, err, "Invalid data rate (321). Accepted values: [128 250 490 920 1600 2400 3300]") } func TestADS1x15ReadDifferenceInvalidChannel(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.ReadDifference(9, 1, 1600) - assert.Error(t, err, "Invalid channel (9), must be between 0 and 3") + assert.ErrorContains(t, err, "Invalid channel (9), must be between 0 and 3") } func TestADS1015_rawRead(t *testing.T) { diff --git a/drivers/i2c/ads1x15_driver_1115_test.go b/drivers/i2c/ads1x15_driver_1115_test.go index 9b2b6b478..0db0efd0a 100644 --- a/drivers/i2c/ads1x15_driver_1115_test.go +++ b/drivers/i2c/ads1x15_driver_1115_test.go @@ -115,14 +115,14 @@ func TestADS1115AnalogReadError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestADS1115AnalogReadInvalidPin(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.AnalogRead("98") - assert.Error(t, err, "Invalid channel (98), must be between 0 and 3") + assert.ErrorContains(t, err, "Invalid channel (98), must be between 0 and 3") } func TestADS1115AnalogReadWriteError(t *testing.T) { @@ -133,41 +133,41 @@ func TestADS1115AnalogReadWriteError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") _, err = d.AnalogRead("0-1") - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") _, err = d.AnalogRead("2-3") - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestADS1115ReadInvalidChannel(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(7, 1, 1600) - assert.Error(t, err, "Invalid channel (7), must be between 0 and 3") + assert.ErrorContains(t, err, "Invalid channel (7), must be between 0 and 3") } func TestADS1115ReadInvalidGain(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(0, 21, 1600) - assert.Error(t, err, "Gain (21) must be one of: [0 1 2 3 4 5 6 7]") + assert.ErrorContains(t, err, "Gain (21) must be one of: [0 1 2 3 4 5 6 7]") } func TestADS1115ReadInvalidDataRate(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(0, 1, 678) - assert.Error(t, err, "Invalid data rate (678). Accepted values: [8 16 32 64 128 250 475 860]") + assert.ErrorContains(t, err, "Invalid data rate (678). Accepted values: [8 16 32 64 128 250 475 860]") } func TestADS1115ReadDifferenceInvalidChannel(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.ReadDifference(5, 1, 1600) - assert.Error(t, err, "Invalid channel (5), must be between 0 and 3") + assert.ErrorContains(t, err, "Invalid channel (5), must be between 0 and 3") } func TestADS1115_rawRead(t *testing.T) { diff --git a/drivers/i2c/ads1x15_driver_test.go b/drivers/i2c/ads1x15_driver_test.go index 23df9842e..d88f46cab 100644 --- a/drivers/i2c/ads1x15_driver_test.go +++ b/drivers/i2c/ads1x15_driver_test.go @@ -99,5 +99,5 @@ func TestADS1x15_ads1x15BestGainForVoltage(t *testing.T) { assert.Equal(t, 2, g) _, err := ads1x15BestGainForVoltage(20.0) - assert.Error(t, err, "The maximum voltage which can be read is 6.144000") + assert.ErrorContains(t, err, "The maximum voltage which can be read is 6.144000") } diff --git a/drivers/i2c/adxl345_driver_test.go b/drivers/i2c/adxl345_driver_test.go index 8f905802c..dce07fecd 100644 --- a/drivers/i2c/adxl345_driver_test.go +++ b/drivers/i2c/adxl345_driver_test.go @@ -205,7 +205,7 @@ func TestADXL345RawXYZError(t *testing.T) { // act _, _, _, err := d.RawXYZ() // assert - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestADXL345XYZ(t *testing.T) { @@ -269,7 +269,7 @@ func TestADXL345XYZError(t *testing.T) { // act _, _, _, err := d.XYZ() // assert - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestADXL345_initialize(t *testing.T) { diff --git a/drivers/i2c/bh1750_driver_test.go b/drivers/i2c/bh1750_driver_test.go index 9ff8703fa..bb0fa1872 100644 --- a/drivers/i2c/bh1750_driver_test.go +++ b/drivers/i2c/bh1750_driver_test.go @@ -96,7 +96,7 @@ func TestBH1750LuxError(t *testing.T) { } _, err := d.Lux() - assert.Error(t, err, "wrong number of bytes read") + assert.ErrorContains(t, err, "wrong number of bytes read") } func TestBH1750RawSensorDataError(t *testing.T) { @@ -106,5 +106,5 @@ func TestBH1750RawSensorDataError(t *testing.T) { } _, err := d.RawSensorData() - assert.Error(t, err, "wrong number of bytes read") + assert.ErrorContains(t, err, "wrong number of bytes read") } diff --git a/drivers/i2c/blinkm_driver_test.go b/drivers/i2c/blinkm_driver_test.go index c3ed3a5f0..e88fb4f7c 100644 --- a/drivers/i2c/blinkm_driver_test.go +++ b/drivers/i2c/blinkm_driver_test.go @@ -125,7 +125,7 @@ func TestBlinkMFirmwareVersion(t *testing.T) { } _, err := d.FirmwareVersion() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestBlinkMColor(t *testing.T) { @@ -153,7 +153,7 @@ func TestBlinkMColor(t *testing.T) { } _, err := d.Color() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestBlinkMFade(t *testing.T) { @@ -163,7 +163,7 @@ func TestBlinkMFade(t *testing.T) { } err := d.Fade(100, 100, 100) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestBlinkMRGB(t *testing.T) { @@ -173,5 +173,5 @@ func TestBlinkMRGB(t *testing.T) { } err := d.Rgb(100, 100, 100) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } diff --git a/drivers/i2c/bme280_driver_test.go b/drivers/i2c/bme280_driver_test.go index 77147cc25..9be6ef97a 100644 --- a/drivers/i2c/bme280_driver_test.go +++ b/drivers/i2c/bme280_driver_test.go @@ -92,7 +92,7 @@ func TestBME280InitH1Error(t *testing.T) { return buf.Len(), nil } - assert.Error(t, bme280.Start(), "h1 read error") + assert.ErrorContains(t, bme280.Start(), "h1 read error") } func TestBME280InitH2Error(t *testing.T) { @@ -111,7 +111,7 @@ func TestBME280InitH2Error(t *testing.T) { return buf.Len(), nil } - assert.Error(t, bme280.Start(), "h2 read error") + assert.ErrorContains(t, bme280.Start(), "h2 read error") } func TestBME280HumidityWriteError(t *testing.T) { @@ -122,7 +122,7 @@ func TestBME280HumidityWriteError(t *testing.T) { return 0, errors.New("write error") } hum, err := bme280.Humidity() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") assert.Equal(t, float32(0.0), hum) } @@ -134,7 +134,7 @@ func TestBME280HumidityReadError(t *testing.T) { return 0, errors.New("read error") } hum, err := bme280.Humidity() - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") assert.Equal(t, float32(0.0), hum) } @@ -159,7 +159,7 @@ func TestBME280HumidityNotEnabled(t *testing.T) { } _ = bme280.Start() hum, err := bme280.Humidity() - assert.Error(t, err, "Humidity disabled") + assert.ErrorContains(t, err, "Humidity disabled") assert.Equal(t, float32(0.0), hum) } diff --git a/drivers/i2c/bmp180_driver_test.go b/drivers/i2c/bmp180_driver_test.go index 610b67c8c..0c4648131 100644 --- a/drivers/i2c/bmp180_driver_test.go +++ b/drivers/i2c/bmp180_driver_test.go @@ -108,7 +108,7 @@ func TestBMP180TemperatureError(t *testing.T) { } _ = bmp180.Start() _, err := bmp180.Temperature() - assert.Error(t, err, "temp error") + assert.ErrorContains(t, err, "temp error") } func TestBMP180PressureError(t *testing.T) { @@ -138,7 +138,7 @@ func TestBMP180PressureError(t *testing.T) { } _ = bmp180.Start() _, err := bmp180.Pressure() - assert.Error(t, err, "press error") + assert.ErrorContains(t, err, "press error") } func TestBMP180PressureWriteError(t *testing.T) { @@ -150,7 +150,7 @@ func TestBMP180PressureWriteError(t *testing.T) { } _, err := bmp180.Pressure() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestBMP180_initialization(t *testing.T) { diff --git a/drivers/i2c/bmp280_driver_test.go b/drivers/i2c/bmp280_driver_test.go index 2dc45298b..b83e3ea6c 100644 --- a/drivers/i2c/bmp280_driver_test.go +++ b/drivers/i2c/bmp280_driver_test.go @@ -106,7 +106,7 @@ func TestBMP280TemperatureWriteError(t *testing.T) { return 0, errors.New("write error") } temp, err := d.Temperature() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") assert.Equal(t, float32(0.0), temp) } @@ -118,7 +118,7 @@ func TestBMP280TemperatureReadError(t *testing.T) { return 0, errors.New("read error") } temp, err := d.Temperature() - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") assert.Equal(t, float32(0.0), temp) } @@ -130,7 +130,7 @@ func TestBMP280PressureWriteError(t *testing.T) { return 0, errors.New("write error") } press, err := d.Pressure() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") assert.Equal(t, float32(0.0), press) } @@ -142,7 +142,7 @@ func TestBMP280PressureReadError(t *testing.T) { return 0, errors.New("read error") } press, err := d.Pressure() - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") assert.Equal(t, float32(0.0), press) } diff --git a/drivers/i2c/bmp388_driver_test.go b/drivers/i2c/bmp388_driver_test.go index 8053710f5..7222fd301 100644 --- a/drivers/i2c/bmp388_driver_test.go +++ b/drivers/i2c/bmp388_driver_test.go @@ -102,7 +102,7 @@ func TestBMP388TemperatureWriteError(t *testing.T) { return 0, errors.New("write error") } temp, err := d.Temperature(2) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") assert.Equal(t, float32(0.0), temp) } @@ -114,7 +114,7 @@ func TestBMP388TemperatureReadError(t *testing.T) { return 0, errors.New("read error") } temp, err := d.Temperature(2) - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") assert.Equal(t, float32(0.0), temp) } @@ -126,7 +126,7 @@ func TestBMP388PressureWriteError(t *testing.T) { return 0, errors.New("write error") } press, err := d.Pressure(2) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") assert.Equal(t, float32(0.0), press) } @@ -138,7 +138,7 @@ func TestBMP388PressureReadError(t *testing.T) { return 0, errors.New("read error") } press, err := d.Pressure(2) - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") assert.Equal(t, float32(0.0), press) } diff --git a/drivers/i2c/drv2605l_driver_test.go b/drivers/i2c/drv2605l_driver_test.go index afeb1ce6a..7e534b3f7 100644 --- a/drivers/i2c/drv2605l_driver_test.go +++ b/drivers/i2c/drv2605l_driver_test.go @@ -110,7 +110,7 @@ func TestDRV2605LSetModeReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - assert.Error(t, d.SetMode(DRV2605ModeIntTrig), "read error") + assert.ErrorContains(t, d.SetMode(DRV2605ModeIntTrig), "read error") } func TestDRV2605LSetStandbyMode(t *testing.T) { @@ -123,7 +123,7 @@ func TestDRV2605LSetStandbyModeReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - assert.Error(t, d.SetStandbyMode(true), "read error") + assert.ErrorContains(t, d.SetStandbyMode(true), "read error") } func TestDRV2605LSelectLibrary(t *testing.T) { diff --git a/drivers/i2c/hmc6352_driver_test.go b/drivers/i2c/hmc6352_driver_test.go index dee1b487e..c46af3bf2 100644 --- a/drivers/i2c/hmc6352_driver_test.go +++ b/drivers/i2c/hmc6352_driver_test.go @@ -80,7 +80,7 @@ func TestHMC6352Heading(t *testing.T) { heading, err = d.Heading() assert.Equal(t, uint16(0), heading) - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") // when write error d, a = initTestHMC6352DriverWithStubbedAdaptor() @@ -90,5 +90,5 @@ func TestHMC6352Heading(t *testing.T) { heading, err = d.Heading() assert.Equal(t, uint16(0), heading) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index fe9efaa70..cee0917f0 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -87,7 +87,7 @@ func TestI2CRead(t *testing.T) { func TestI2CReadAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.Read([]byte{}) - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWrite(t *testing.T) { @@ -99,7 +99,7 @@ func TestI2CWrite(t *testing.T) { func TestI2CWriteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.Write([]byte{0x01}) - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadByte(t *testing.T) { @@ -111,7 +111,7 @@ func TestI2CReadByte(t *testing.T) { func TestI2CReadByteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadByte() - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadByteData(t *testing.T) { @@ -123,7 +123,7 @@ func TestI2CReadByteData(t *testing.T) { func TestI2CReadByteDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadByteData(0x01) - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadWordData(t *testing.T) { @@ -135,7 +135,7 @@ func TestI2CReadWordData(t *testing.T) { func TestI2CReadWordDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadWordData(0x01) - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteByte(t *testing.T) { @@ -147,7 +147,7 @@ func TestI2CWriteByte(t *testing.T) { func TestI2CWriteByteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteByte(0x01) - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteByteData(t *testing.T) { @@ -159,7 +159,7 @@ func TestI2CWriteByteData(t *testing.T) { func TestI2CWriteByteDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteByteData(0x01, 0x01) - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteWordData(t *testing.T) { @@ -171,7 +171,7 @@ func TestI2CWriteWordData(t *testing.T) { func TestI2CWriteWordDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteWordData(0x01, 0x01) - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteBlockData(t *testing.T) { @@ -183,7 +183,7 @@ func TestI2CWriteBlockData(t *testing.T) { func TestI2CWriteBlockDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteBlockData(0x01, []byte{0x01, 0x02}) - assert.Error(t, err, "Setting address failed with syscall.Errno operation not permitted") + assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func Test_setBit(t *testing.T) { diff --git a/drivers/i2c/i2c_driver_test.go b/drivers/i2c/i2c_driver_test.go index e2317e035..bdd115f6d 100644 --- a/drivers/i2c/i2c_driver_test.go +++ b/drivers/i2c/i2c_driver_test.go @@ -70,7 +70,7 @@ func TestStartConnectError(t *testing.T) { d, a := initDriverWithStubbedAdaptor() a.Testi2cConnectErr(true) // act, assert - assert.Error(t, d.Start(), "Invalid i2c connection") + assert.ErrorContains(t, d.Start(), "Invalid i2c connection") } func TestHalt(t *testing.T) { diff --git a/drivers/i2c/ina3221_driver_test.go b/drivers/i2c/ina3221_driver_test.go index 3650dec9f..5987ccb8c 100644 --- a/drivers/i2c/ina3221_driver_test.go +++ b/drivers/i2c/ina3221_driver_test.go @@ -70,7 +70,7 @@ func TestINA3221GetBusVoltageReadError(t *testing.T) { } _, err := d.GetBusVoltage(INA3221Channel1) - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestINA3221GetShuntVoltage(t *testing.T) { @@ -93,7 +93,7 @@ func TestINA3221GetShuntVoltageReadError(t *testing.T) { } _, err := d.GetShuntVoltage(INA3221Channel1) - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestINA3221GetCurrent(t *testing.T) { @@ -116,7 +116,7 @@ func TestINA3221CurrentReadError(t *testing.T) { } _, err := d.GetCurrent(INA3221Channel1) - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestINA3221GetLoadVoltage(t *testing.T) { @@ -141,5 +141,5 @@ func TestINA3221GetLoadVoltageReadError(t *testing.T) { } _, err := d.GetLoadVoltage(INA3221Channel2) - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } diff --git a/drivers/i2c/jhd1313m1_driver_test.go b/drivers/i2c/jhd1313m1_driver_test.go index eef00c036..12531d03c 100644 --- a/drivers/i2c/jhd1313m1_driver_test.go +++ b/drivers/i2c/jhd1313m1_driver_test.go @@ -60,7 +60,7 @@ func TestJHD1313MDriverStart(t *testing.T) { func TestJHD1313MStartConnectError(t *testing.T) { d, adaptor := initTestJHD1313M1DriverWithStubbedAdaptor() adaptor.Testi2cConnectErr(true) - assert.Error(t, d.Start(), "Invalid i2c connection") + assert.ErrorContains(t, d.Start(), "Invalid i2c connection") } func TestJHD1313MDriverStartWriteError(t *testing.T) { @@ -68,7 +68,7 @@ func TestJHD1313MDriverStartWriteError(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.Start(), "write error") + assert.ErrorContains(t, d.Start(), "write error") } func TestJHD1313MDriverHalt(t *testing.T) { @@ -90,7 +90,7 @@ func TestJHD1313MDriverSetRgbError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.SetRGB(0x00, 0x00, 0x00), "write error") + assert.ErrorContains(t, d.SetRGB(0x00, 0x00, 0x00), "write error") } func TestJHD1313MDriverClear(t *testing.T) { @@ -106,7 +106,7 @@ func TestJHD1313MDriverClearError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.Clear(), "write error") + assert.ErrorContains(t, d.Clear(), "write error") } func TestJHD1313MDriverHome(t *testing.T) { @@ -128,7 +128,7 @@ func TestJHD1313MDriverWriteError(t *testing.T) { return 0, errors.New("write error") } - assert.Error(t, d.Write("Hello"), "write error") + assert.ErrorContains(t, d.Write("Hello"), "write error") } func TestJHD1313MDriverWriteTwoLines(t *testing.T) { @@ -144,7 +144,7 @@ func TestJHD1313MDriverWriteTwoLinesError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.Write("Hello\nthere"), "write error") + assert.ErrorContains(t, d.Write("Hello\nthere"), "write error") } func TestJHD1313MDriverSetPosition(t *testing.T) { @@ -189,7 +189,7 @@ func TestJHD1313MDriverSetCustomCharError(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} _ = d.Start() - assert.Error(t, d.SetCustomChar(10, data), "can't set a custom character at a position greater than 7") + assert.ErrorContains(t, d.SetCustomChar(10, data), "can't set a custom character at a position greater than 7") } func TestJHD1313MDriverSetCustomCharWriteError(t *testing.T) { @@ -200,7 +200,7 @@ func TestJHD1313MDriverSetCustomCharWriteError(t *testing.T) { return 0, errors.New("write error") } data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - assert.Error(t, d.SetCustomChar(0, data), "write error") + assert.ErrorContains(t, d.SetCustomChar(0, data), "write error") } func TestJHD1313MDriverCommands(t *testing.T) { diff --git a/drivers/i2c/l3gd20h_driver_test.go b/drivers/i2c/l3gd20h_driver_test.go index 5dcb88fda..e6a9402d4 100644 --- a/drivers/i2c/l3gd20h_driver_test.go +++ b/drivers/i2c/l3gd20h_driver_test.go @@ -214,7 +214,7 @@ func TestL3GD20HMeasurementError(t *testing.T) { _ = d.Start() _, _, _, err := d.XYZ() - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestL3GD20HMeasurementWriteError(t *testing.T) { @@ -223,7 +223,7 @@ func TestL3GD20HMeasurementWriteError(t *testing.T) { return 0, errors.New("write error") } _, _, _, err := d.XYZ() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestL3GD20H_initialize(t *testing.T) { diff --git a/drivers/i2c/lidarlite_driver_test.go b/drivers/i2c/lidarlite_driver_test.go index 4050dc832..9d61eb147 100644 --- a/drivers/i2c/lidarlite_driver_test.go +++ b/drivers/i2c/lidarlite_driver_test.go @@ -93,7 +93,7 @@ func TestLIDARLiteDriverDistance(t *testing.T) { distance, err = d.Distance() assert.Equal(t, int(0), distance) - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestLIDARLiteDriverDistanceError1(t *testing.T) { @@ -104,7 +104,7 @@ func TestLIDARLiteDriverDistanceError1(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestLIDARLiteDriverDistanceError2(t *testing.T) { @@ -118,7 +118,7 @@ func TestLIDARLiteDriverDistanceError2(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestLIDARLiteDriverDistanceError3(t *testing.T) { @@ -138,5 +138,5 @@ func TestLIDARLiteDriverDistanceError3(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index bdb263951..961669fa3 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -241,7 +241,7 @@ func TestMCP23017CommandsWriteGPIOErrIODIR(t *testing.T) { // act err := d.WriteGPIO(7, "A", 0) // assert - assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") + assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") } func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { @@ -258,7 +258,7 @@ func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { // act err := d.WriteGPIO(7, "A", 0) // assert - assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=20): write error") + assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=20): write error") } func TestMCP23017ReadGPIO(t *testing.T) { @@ -381,7 +381,7 @@ func TestMCP23017ReadGPIOErr(t *testing.T) { // act _, err := d.ReadGPIO(7, "A") // assert - assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): read error") + assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): read error") } func TestMCP23017SetPinMode(t *testing.T) { @@ -431,7 +431,7 @@ func TestMCP23017SetPinModeErr(t *testing.T) { // act err := d.SetPinMode(7, "A", 0) // assert - assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") + assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") } func TestMCP23017SetPullUp(t *testing.T) { @@ -481,7 +481,7 @@ func TestMCP23017SetPullUpErr(t *testing.T) { // act err := d.SetPullUp(7, "A", 0) // assert - assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=12): write error") + assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=12): write error") } func TestMCP23017SetGPIOPolarity(t *testing.T) { @@ -531,7 +531,7 @@ func TestMCP23017SetGPIOPolarityErr(t *testing.T) { // act err := d.SetGPIOPolarity(7, "A", 0) // assert - assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=2): write error") + assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=2): write error") } func TestMCP23017_write(t *testing.T) { @@ -553,7 +553,7 @@ func TestMCP23017_write(t *testing.T) { return 0, errors.New("write error") } err = d.write(port.IODIR, uint8(7), 0) - assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): write error") + assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): write error") // read error d, a = initTestMCP23017WithStubbedAdaptor(0) @@ -561,7 +561,7 @@ func TestMCP23017_write(t *testing.T) { return len(b), errors.New("read error") } err = d.write(port.IODIR, uint8(7), 0) - assert.Error(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): read error") + assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): read error") a.i2cReadImpl = func(b []byte) (int, error) { return len(b), nil } @@ -588,7 +588,7 @@ func TestMCP23017_read(t *testing.T) { val, err := d.read(port.IODIR) assert.Equal(t, uint8(0), val) - assert.Error(t, err, "MCP write-ReadByteData(reg=0): read error") + assert.ErrorContains(t, err, "MCP write-ReadByteData(reg=0): read error") // read d, a = initTestMCP23017WithStubbedAdaptor(0) diff --git a/drivers/i2c/mma7660_driver_test.go b/drivers/i2c/mma7660_driver_test.go index 1553218c4..2824e13b3 100644 --- a/drivers/i2c/mma7660_driver_test.go +++ b/drivers/i2c/mma7660_driver_test.go @@ -90,7 +90,7 @@ func TestMMA7660XYZError(t *testing.T) { } _, _, _, err := d.XYZ() - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestMMA7660XYZNotReady(t *testing.T) { diff --git a/drivers/i2c/mpl115a2_driver_test.go b/drivers/i2c/mpl115a2_driver_test.go index d7517197c..27ef1c9b3 100644 --- a/drivers/i2c/mpl115a2_driver_test.go +++ b/drivers/i2c/mpl115a2_driver_test.go @@ -101,7 +101,7 @@ func TestMPL115A2ReadDataError(t *testing.T) { } _, err := d.Pressure() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestMPL115A2_initialization(t *testing.T) { diff --git a/drivers/i2c/mpu6050_driver_test.go b/drivers/i2c/mpu6050_driver_test.go index 94c9efb4e..1663658eb 100644 --- a/drivers/i2c/mpu6050_driver_test.go +++ b/drivers/i2c/mpu6050_driver_test.go @@ -124,7 +124,7 @@ func TestMPU6050GetDataReadError(t *testing.T) { return 0, errors.New("read error") } - assert.Error(t, d.GetData(), "read error") + assert.ErrorContains(t, d.GetData(), "read error") } func TestMPU6050GetDataWriteError(t *testing.T) { @@ -135,7 +135,7 @@ func TestMPU6050GetDataWriteError(t *testing.T) { return 0, errors.New("write error") } - assert.Error(t, d.GetData(), "write error") + assert.ErrorContains(t, d.GetData(), "write error") } func TestMPU6050_initialize(t *testing.T) { diff --git a/drivers/i2c/pca9685_driver_test.go b/drivers/i2c/pca9685_driver_test.go index 5d1b3fee5..73a3bed89 100644 --- a/drivers/i2c/pca9685_driver_test.go +++ b/drivers/i2c/pca9685_driver_test.go @@ -87,7 +87,7 @@ func TestPCA9685SetPWMError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.SetPWM(0, 0, 256), "write error") + assert.ErrorContains(t, d.SetPWM(0, 0, 256), "write error") } func TestPCA9685SetPWMFreq(t *testing.T) { @@ -116,7 +116,7 @@ func TestPCA9685SetPWMFreqReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - assert.Error(t, d.SetPWMFreq(60), "read error") + assert.ErrorContains(t, d.SetPWMFreq(60), "read error") } func TestPCA9685SetPWMFreqWriteError(t *testing.T) { @@ -130,7 +130,7 @@ func TestPCA9685SetPWMFreqWriteError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.SetPWMFreq(60), "write error") + assert.ErrorContains(t, d.SetPWMFreq(60), "write error") } func TestPCA9685Commands(t *testing.T) { diff --git a/drivers/i2c/sht2x_driver_test.go b/drivers/i2c/sht2x_driver_test.go index 0fd369b79..3640a18be 100644 --- a/drivers/i2c/sht2x_driver_test.go +++ b/drivers/i2c/sht2x_driver_test.go @@ -116,7 +116,7 @@ func TestSHT2xTemperatureCrcError(t *testing.T) { return buf.Len(), nil } temp, err := d.Temperature() - assert.Error(t, err, "Invalid crc") + assert.ErrorContains(t, err, "Invalid crc") assert.Equal(t, float32(0.0), temp) } @@ -133,7 +133,7 @@ func TestSHT2xHumidityCrcError(t *testing.T) { return buf.Len(), nil } hum, err := d.Humidity() - assert.Error(t, err, "Invalid crc") + assert.ErrorContains(t, err, "Invalid crc") assert.Equal(t, float32(0.0), hum) } diff --git a/drivers/i2c/ssd1306_driver_test.go b/drivers/i2c/ssd1306_driver_test.go index 28941e6c7..53cce321e 100644 --- a/drivers/i2c/ssd1306_driver_test.go +++ b/drivers/i2c/ssd1306_driver_test.go @@ -91,7 +91,7 @@ func TestSSD1306StartSizeError(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.Error(t, d.Start(), "128x54 resolution is unsupported, supported resolutions: 128x64, 128x32, 96x16") + assert.ErrorContains(t, d.Start(), "128x54 resolution is unsupported, supported resolutions: 128x64, 128x32, 96x16") } func TestSSD1306Halt(t *testing.T) { @@ -116,7 +116,7 @@ func TestSSD1306ShowImage(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) _ = s.Start() img := image.NewRGBA(image.Rect(0, 0, 640, 480)) - assert.Error(t, s.ShowImage(img), "image must match display width and height: 128x64") + assert.ErrorContains(t, s.ShowImage(img), "image must match display width and height: 128x64") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) assert.Nil(t, s.ShowImage(img)) diff --git a/drivers/i2c/tsl2561_driver_test.go b/drivers/i2c/tsl2561_driver_test.go index b719b3b53..bd6342e6d 100644 --- a/drivers/i2c/tsl2561_driver_test.go +++ b/drivers/i2c/tsl2561_driver_test.go @@ -72,7 +72,7 @@ func TestTSL2561DriverStartNotFound(t *testing.T) { copy(b, buf.Bytes()) return buf.Len(), nil } - assert.Error(t, d.Start(), "TSL2561 device not found (0x1)") + assert.ErrorContains(t, d.Start(), "TSL2561 device not found (0x1)") } func TestTSL2561DriverHalt(t *testing.T) { @@ -157,7 +157,7 @@ func TestTSL2561DriverGetDataWriteError(t *testing.T) { } _, _, err := d.getData() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestTSL2561DriverGetDataReadError(t *testing.T) { @@ -167,7 +167,7 @@ func TestTSL2561DriverGetDataReadError(t *testing.T) { } _, _, err := d.getData() - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestTSL2561DriverGetLuminocity(t *testing.T) { @@ -213,7 +213,7 @@ func TestTSL2561SetIntegrationTimeError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.SetIntegrationTime(TSL2561IntegrationTime101MS), "write error") + assert.ErrorContains(t, d.SetIntegrationTime(TSL2561IntegrationTime101MS), "write error") } func TestTSL2561SetGainError(t *testing.T) { @@ -221,7 +221,7 @@ func TestTSL2561SetGainError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.Error(t, d.SetGain(TSL2561Gain16X), "write error") + assert.ErrorContains(t, d.SetGain(TSL2561Gain16X), "write error") } func TestTSL2561getHiLo13MS(t *testing.T) { diff --git a/drivers/spi/mcp3002_test.go b/drivers/spi/mcp3002_test.go index 560d1fbca..af328c9c6 100644 --- a/drivers/spi/mcp3002_test.go +++ b/drivers/spi/mcp3002_test.go @@ -87,6 +87,6 @@ func TestMCP3002ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Error(t, err, "error while SPI read in mock") + assert.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3004_test.go b/drivers/spi/mcp3004_test.go index b5db2db55..adba27edf 100644 --- a/drivers/spi/mcp3004_test.go +++ b/drivers/spi/mcp3004_test.go @@ -93,6 +93,6 @@ func TestMCP3004ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Error(t, err, "error while SPI read in mock") + assert.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3008_test.go b/drivers/spi/mcp3008_test.go index 10cbf5113..095e8c3b0 100644 --- a/drivers/spi/mcp3008_test.go +++ b/drivers/spi/mcp3008_test.go @@ -93,6 +93,6 @@ func TestMCP3008ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Error(t, err, "error while SPI read in mock") + assert.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3202_test.go b/drivers/spi/mcp3202_test.go index 570f4ac8b..e580a91b7 100644 --- a/drivers/spi/mcp3202_test.go +++ b/drivers/spi/mcp3202_test.go @@ -87,6 +87,6 @@ func TestMCP3202ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Error(t, err, "error while SPI read in mock") + assert.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3204_test.go b/drivers/spi/mcp3204_test.go index a2b223e05..967043983 100644 --- a/drivers/spi/mcp3204_test.go +++ b/drivers/spi/mcp3204_test.go @@ -93,6 +93,6 @@ func TestMCP3204ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Error(t, err, "error while SPI read in mock") + assert.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3208_test.go b/drivers/spi/mcp3208_test.go index e28383a47..81d59ff70 100644 --- a/drivers/spi/mcp3208_test.go +++ b/drivers/spi/mcp3208_test.go @@ -93,6 +93,6 @@ func TestMCP3208ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Error(t, err, "error while SPI read in mock") + assert.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3304_test.go b/drivers/spi/mcp3304_test.go index 1535771d9..f8bf8e4ba 100644 --- a/drivers/spi/mcp3304_test.go +++ b/drivers/spi/mcp3304_test.go @@ -93,6 +93,6 @@ func TestMCP3304ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.Error(t, err, "error while SPI read in mock") + assert.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/ssd1306_driver_test.go b/drivers/spi/ssd1306_driver_test.go index ff12e966b..79f010a59 100644 --- a/drivers/spi/ssd1306_driver_test.go +++ b/drivers/spi/ssd1306_driver_test.go @@ -38,7 +38,7 @@ func TestSSD1306DriverShowImage(t *testing.T) { d := initTestSSDDriver() _ = d.Start() img := image.NewRGBA(image.Rect(0, 0, 640, 480)) - assert.Error(t, d.ShowImage(img), "Image must match the display width and height") + assert.ErrorContains(t, d.ShowImage(img), "Image must match the display width and height") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) assert.Nil(t, d.ShowImage(img)) diff --git a/platforms/adaptors/digitalpinsadaptor_test.go b/platforms/adaptors/digitalpinsadaptor_test.go index 3441b4e1c..01b911c18 100644 --- a/platforms/adaptors/digitalpinsadaptor_test.go +++ b/platforms/adaptors/digitalpinsadaptor_test.go @@ -60,10 +60,10 @@ func TestDigitalPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.DigitalPinner)(nil), a.pins) _, err := a.DigitalRead("13") - assert.Error(t, err, "not connected for pin 13") + assert.ErrorContains(t, err, "not connected for pin 13") err = a.DigitalWrite("7", 1) - assert.Error(t, err, "not connected for pin 7") + assert.ErrorContains(t, err, "not connected for pin 7") err = a.Connect() assert.Nil(t, err) @@ -159,12 +159,12 @@ func TestDigitalRead(t *testing.T) { // assert error bubbling for read errors fs.WithReadError = true _, err = a.DigitalRead("13") - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") // assert error bubbling for write errors fs.WithWriteError = true _, err = a.DigitalRead("7") - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestDigitalReadWithGpiosActiveLow(t *testing.T) { @@ -228,12 +228,12 @@ func TestDigitalWrite(t *testing.T) { assert.Nil(t, err) // assert error on bad id - assert.Error(t, a.DigitalWrite("notexist", 1), "not a valid pin") + assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "not a valid pin") // assert error bubbling fs.WithWriteError = true err = a.DigitalWrite("7", 0) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestDigitalWriteWithGpiosActiveLow(t *testing.T) { diff --git a/platforms/adaptors/i2cbusadaptor_test.go b/platforms/adaptors/i2cbusadaptor_test.go index 543d77056..05042fd3d 100644 --- a/platforms/adaptors/i2cbusadaptor_test.go +++ b/platforms/adaptors/i2cbusadaptor_test.go @@ -61,13 +61,13 @@ func TestI2cGetI2cConnection(t *testing.T) { assert.Equal(t, 1, len(a.buses)) // assert invalid bus gets error c2, e2 := a.GetI2cConnection(0x01, 99) - assert.Error(t, e2, "99 not valid") + assert.ErrorContains(t, e2, "99 not valid") assert.Nil(t, c2) assert.Equal(t, 1, len(a.buses)) // assert unconnected gets error assert.Nil(t, a.Finalize()) c3, e3 := a.GetI2cConnection(0x01, 99) - assert.Error(t, e3, "not connected") + assert.ErrorContains(t, e3, "not connected") assert.Nil(t, c3) assert.Equal(t, 0, len(a.buses)) } diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index 6c98c4214..c78223d66 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -117,7 +117,7 @@ func TestPWMPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.PWMPinner)(nil), a.pins) err := a.PwmWrite("33", 1) - assert.Error(t, err, "not connected") + assert.ErrorContains(t, err, "not connected") err = a.Connect() assert.Nil(t, err) @@ -186,7 +186,7 @@ func TestPwmWrite(t *testing.T) { assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.PwmWrite("notexist", 42) - assert.Error(t, err, "'notexist' is not a valid id of a PWM pin") + assert.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") fs.WithWriteError = true err = a.PwmWrite("33", 100) @@ -214,7 +214,7 @@ func TestServoWrite(t *testing.T) { assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("notexist", 42) - assert.Error(t, err, "'notexist' is not a valid id of a PWM pin") + assert.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") fs.WithWriteError = true err = a.ServoWrite("33", 100) @@ -266,7 +266,7 @@ func TestSetPeriod(t *testing.T) { // act err = a.SetPeriod("not_exist", newPeriod) // assert - assert.Error(t, err, "'not_exist' is not a valid id of a PWM pin") + assert.ErrorContains(t, err, "'not_exist' is not a valid id of a PWM pin") } func Test_PWMPin(t *testing.T) { diff --git a/platforms/adaptors/spibusadaptor_test.go b/platforms/adaptors/spibusadaptor_test.go index 20ed11605..80864de86 100644 --- a/platforms/adaptors/spibusadaptor_test.go +++ b/platforms/adaptors/spibusadaptor_test.go @@ -40,7 +40,7 @@ func TestNewSpiAdaptor(t *testing.T) { assert.Equal(t, 4, a.SpiDefaultBitCount()) assert.Equal(t, int64(5), a.SpiDefaultMaxSpeed()) _, err := a.GetSpiConnection(10, 0, 0, 8, 10000000) - assert.Error(t, err, "not connected") + assert.ErrorContains(t, err, "not connected") } func TestGetSpiConnection(t *testing.T) { @@ -73,12 +73,12 @@ func TestGetSpiConnection(t *testing.T) { assert.Equal(t, 2, len(a.connections)) // assert bus validation error con, err := a.GetSpiConnection(busNum+1, chipNum, mode, bits, maxSpeed) - assert.Error(t, err, "16 not valid") + assert.ErrorContains(t, err, "16 not valid") assert.Nil(t, con) // assert create error spi.CreateError = true con, err = a.GetSpiConnection(busNum, chipNum+2, mode, bits, maxSpeed) - assert.Error(t, err, "error while create SPI connection in mock") + assert.ErrorContains(t, err, "error while create SPI connection in mock") assert.Nil(t, con) } diff --git a/platforms/audio/audio_adaptor_test.go b/platforms/audio/audio_adaptor_test.go index 4a6778d41..4e20511af 100644 --- a/platforms/audio/audio_adaptor_test.go +++ b/platforms/audio/audio_adaptor_test.go @@ -40,7 +40,7 @@ func TestAudioAdaptorCommandsMp3(t *testing.T) { func TestAudioAdaptorCommandsUnknown(t *testing.T) { cmd, err := CommandName("whatever.unk") assert.NotEqual(t, "mpg123", cmd) - assert.Error(t, err, "Unknown filetype for audio file.") + assert.ErrorContains(t, err, "Unknown filetype for audio file.") } func TestAudioAdaptorSoundWithNoFilename(t *testing.T) { diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index ac420c36b..b615c68dc 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -58,7 +58,7 @@ func TestPWM(t *testing.T) { fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents = "0" fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/period"].Contents = "0" - assert.Error(t, a.PwmWrite("P9_99", 175), "'P9_99' is not a valid id for a PWM pin") + assert.ErrorContains(t, a.PwmWrite("P9_99", 175), "'P9_99' is not a valid id for a PWM pin") _ = a.PwmWrite("P9_21", 175) assert.Equal( t, @@ -99,11 +99,11 @@ func TestAnalog(t *testing.T) { assert.Nil(t, err) _, err = a.AnalogRead("P9_99") - assert.Error(t, err, "Not a valid analog pin") + assert.ErrorContains(t, err, "Not a valid analog pin") fs.WithReadError = true _, err = a.AnalogRead("P9_40") - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") fs.WithReadError = false assert.Nil(t, a.Finalize()) @@ -138,15 +138,15 @@ func TestDigitalIO(t *testing.T) { // no such LED err := a.DigitalWrite("usr10101", 1) - assert.Error(t, err, " : /sys/class/leds/beaglebone:green:usr10101/brightness: no such file") + assert.ErrorContains(t, err, " : /sys/class/leds/beaglebone:green:usr10101/brightness: no such file") _ = a.DigitalWrite("P9_12", 1) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio60/value"].Contents) - assert.Error(t, a.DigitalWrite("P9_99", 1), "'P9_99' is not a valid id for a digital pin") + assert.ErrorContains(t, a.DigitalWrite("P9_99", 1), "'P9_99' is not a valid id for a digital pin") _, err = a.DigitalRead("P9_99") - assert.Error(t, err, "'P9_99' is not a valid id for a digital pin") + assert.ErrorContains(t, err, "'P9_99' is not a valid id for a digital pin") fs.Files["/sys/class/gpio/gpio66/value"].Contents = "1" i, err := a.DigitalRead("P8_07") diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index 3df2bfb67..b090a8920 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -105,7 +105,7 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("TWI2-SDA") assert.Equal(t, 1, i) - assert.Error(t, a.DigitalWrite("XIO-P10", 1), "'XIO-P10' is not a valid id for a digital pin") + assert.ErrorContains(t, a.DigitalWrite("XIO-P10", 1), "'XIO-P10' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } @@ -120,7 +120,7 @@ func TestProDigitalIO(t *testing.T) { i, _ := a.DigitalRead("TWI2-SDA") assert.Equal(t, 1, i) - assert.Error(t, a.DigitalWrite("XIO-P0", 1), "'XIO-P0' is not a valid id for a digital pin") + assert.ErrorContains(t, a.DigitalWrite("XIO-P0", 1), "'XIO-P0' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } diff --git a/platforms/digispark/digispark_adaptor_test.go b/platforms/digispark/digispark_adaptor_test.go index 011a8d7e0..de9ccf6b5 100644 --- a/platforms/digispark/digispark_adaptor_test.go +++ b/platforms/digispark/digispark_adaptor_test.go @@ -112,7 +112,7 @@ func TestDigisparkAdaptorDigitalWrite(t *testing.T) { errorFunc = func() error { return errors.New("pin mode error") } err = a.DigitalWrite("0", uint8(1)) - assert.Error(t, err, "pin mode error") + assert.ErrorContains(t, err, "pin mode error") } func TestDigisparkAdaptorServoWrite(t *testing.T) { @@ -125,7 +125,7 @@ func TestDigisparkAdaptorServoWrite(t *testing.T) { a = initTestAdaptor() errorFunc = func() error { return errors.New("servo error") } err = a.ServoWrite("2", uint8(80)) - assert.Error(t, err, "servo error") + assert.ErrorContains(t, err, "servo error") } func TestDigisparkAdaptorPwmWrite(t *testing.T) { @@ -138,10 +138,10 @@ func TestDigisparkAdaptorPwmWrite(t *testing.T) { a = initTestAdaptor() pwmInitErrorFunc = func() error { return errors.New("pwminit error") } err = a.PwmWrite("1", uint8(100)) - assert.Error(t, err, "pwminit error") + assert.ErrorContains(t, err, "pwminit error") a = initTestAdaptor() errorFunc = func() error { return errors.New("pwm error") } err = a.PwmWrite("1", uint8(100)) - assert.Error(t, err, "pwm error") + assert.ErrorContains(t, err, "pwm error") } diff --git a/platforms/digispark/digispark_i2c_test.go b/platforms/digispark/digispark_i2c_test.go index bf2a627b6..549d70547 100644 --- a/platforms/digispark/digispark_i2c_test.go +++ b/platforms/digispark/digispark_i2c_test.go @@ -57,7 +57,7 @@ func TestDigisparkAdaptorI2cGetI2cConnectionFailWithInvalidBus(t *testing.T) { c, err := a.GetI2cConnection(0x40, 1) // assert - assert.Error(t, err, "Invalid bus number 1, only 0 is supported") + assert.ErrorContains(t, err, "Invalid bus number 1, only 0 is supported") assert.Nil(t, c) } @@ -72,7 +72,7 @@ func TestDigisparkAdaptorI2cStartFailWithWrongAddress(t *testing.T) { // assert assert.Equal(t, 0, count) - assert.Error(t, err, "Invalid address, only %d is supported", availableI2cAddress) + assert.ErrorContains(t, err, fmt.Sprintf("Invalid address, only %d is supported", availableI2cAddress)) assert.Equal(t, maxUint8, a.littleWire.(*i2cMock).direction) } diff --git a/platforms/dragonboard/dragonboard_adaptor_test.go b/platforms/dragonboard/dragonboard_adaptor_test.go index 40215c49b..bde2e27ec 100644 --- a/platforms/dragonboard/dragonboard_adaptor_test.go +++ b/platforms/dragonboard/dragonboard_adaptor_test.go @@ -54,7 +54,7 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("GPIO_A") assert.Equal(t, 1, i) - assert.Error(t, a.DigitalWrite("GPIO_M", 1), "'GPIO_M' is not a valid id for a digital pin") + assert.ErrorContains(t, a.DigitalWrite("GPIO_M", 1), "'GPIO_M' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } diff --git a/platforms/firmata/firmata_adaptor_test.go b/platforms/firmata/firmata_adaptor_test.go index 091f9b1b6..fbfd956d1 100644 --- a/platforms/firmata/firmata_adaptor_test.go +++ b/platforms/firmata/firmata_adaptor_test.go @@ -115,7 +115,7 @@ func TestAdaptorFinalize(t *testing.T) { a = initTestAdaptor() a.Board.(*mockFirmataBoard).disconnectError = errors.New("close error") - assert.Error(t, a.Finalize(), "close error") + assert.ErrorContains(t, a.Finalize(), "close error") } func TestAdaptorConnect(t *testing.T) { @@ -132,7 +132,7 @@ func TestAdaptorConnect(t *testing.T) { a.PortOpener = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - assert.Error(t, a.Connect(), "connect error") + assert.ErrorContains(t, a.Connect(), "connect error") a = NewAdaptor(&readWriteCloser{}) a.Board = newMockFirmataBoard() diff --git a/platforms/firmata/firmata_i2c_test.go b/platforms/firmata/firmata_i2c_test.go index f7d758085..e9d467b23 100644 --- a/platforms/firmata/firmata_i2c_test.go +++ b/platforms/firmata/firmata_i2c_test.go @@ -243,5 +243,5 @@ func TestDefaultBus(t *testing.T) { func TestGetI2cConnectionInvalidBus(t *testing.T) { a := NewAdaptor() _, err := a.GetI2cConnection(0x01, 99) - assert.Error(t, err, "Invalid bus number 99, only 0 is supported") + assert.ErrorContains(t, err, "Invalid bus number 99, only 0 is supported") } diff --git a/platforms/intel-iot/curie/imu_driver_test.go b/platforms/intel-iot/curie/imu_driver_test.go index a7f9c1692..f1e455921 100644 --- a/platforms/intel-iot/curie/imu_driver_test.go +++ b/platforms/intel-iot/curie/imu_driver_test.go @@ -123,7 +123,7 @@ func TestIMUDriverReadAccelerometer(t *testing.T) { func TestIMUDriverReadAccelerometerData(t *testing.T) { _, err := parseAccelerometerData([]byte{}) - assert.Error(t, err, "Invalid data") + assert.ErrorContains(t, err, "Invalid data") result, err := parseAccelerometerData([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) assert.Nil(t, err) @@ -138,7 +138,7 @@ func TestIMUDriverReadGyroscope(t *testing.T) { func TestIMUDriverReadGyroscopeData(t *testing.T) { _, err := parseGyroscopeData([]byte{}) - assert.Error(t, err, "Invalid data") + assert.ErrorContains(t, err, "Invalid data") result, err := parseGyroscopeData([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) assert.Nil(t, err) @@ -153,7 +153,7 @@ func TestIMUDriverReadTemperature(t *testing.T) { func TestIMUDriverReadTemperatureData(t *testing.T) { _, err := parseTemperatureData([]byte{}) - assert.Error(t, err, "Invalid data") + assert.ErrorContains(t, err, "Invalid data") result, err := parseTemperatureData([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7}) assert.Nil(t, err) @@ -168,7 +168,7 @@ func TestIMUDriverEnableShockDetection(t *testing.T) { func TestIMUDriverShockDetectData(t *testing.T) { _, err := parseShockData([]byte{}) - assert.Error(t, err, "Invalid data") + assert.ErrorContains(t, err, "Invalid data") result, err := parseShockData([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7}) assert.Nil(t, err) @@ -183,7 +183,7 @@ func TestIMUDriverEnableStepCounter(t *testing.T) { func TestIMUDriverStepCountData(t *testing.T) { _, err := parseStepData([]byte{}) - assert.Error(t, err, "Invalid data") + assert.ErrorContains(t, err, "Invalid data") result, err := parseStepData([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7}) assert.Nil(t, err) @@ -198,7 +198,7 @@ func TestIMUDriverEnableTapDetection(t *testing.T) { func TestIMUDriverTapDetectData(t *testing.T) { _, err := parseTapData([]byte{}) - assert.Error(t, err, "Invalid data") + assert.ErrorContains(t, err, "Invalid data") result, err := parseTapData([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7}) assert.Nil(t, err) @@ -213,7 +213,7 @@ func TestIMUDriverEnableReadMotion(t *testing.T) { func TestIMUDriverReadMotionData(t *testing.T) { _, err := parseMotionData([]byte{}) - assert.Error(t, err, "Invalid data") + assert.ErrorContains(t, err, "Invalid data") result, err := parseMotionData([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) assert.Nil(t, err) diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index 8b4af0a2c..cd85a3c3b 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -276,7 +276,7 @@ func TestArduinoI2CSetupFailTristate(t *testing.T) { fs.WithWriteError = true err := a.arduinoI2CSetup() - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestArduinoI2CSetupFail14(t *testing.T) { @@ -453,7 +453,7 @@ func TestDigitalWriteError(t *testing.T) { fs.WithWriteError = true err := a.DigitalWrite("13", 1) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestDigitalReadWriteError(t *testing.T) { @@ -461,7 +461,7 @@ func TestDigitalReadWriteError(t *testing.T) { fs.WithWriteError = true _, err := a.DigitalRead("13") - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestPwm(t *testing.T) { @@ -472,7 +472,7 @@ func TestPwm(t *testing.T) { assert.Equal(t, "1960", fs.Files["/sys/class/pwm/pwmchip0/pwm1/duty_cycle"].Contents) err = a.PwmWrite("7", 100) - assert.Error(t, err, "'7' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'7' is not a valid id for a PWM pin") } func TestPwmExportError(t *testing.T) { @@ -501,7 +501,7 @@ func TestPwmWritePinError(t *testing.T) { fs.WithWriteError = true err := a.PwmWrite("5", 100) - assert.Error(t, err, "write error") + assert.ErrorContains(t, err, "write error") } func TestPwmWriteError(t *testing.T) { @@ -533,7 +533,7 @@ func TestAnalogError(t *testing.T) { fs.WithReadError = true _, err := a.AnalogRead("0") - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } func TestI2cWorkflow(t *testing.T) { diff --git a/platforms/intel-iot/joule/joule_adaptor_test.go b/platforms/intel-iot/joule/joule_adaptor_test.go index b629d0203..edd88ac9e 100644 --- a/platforms/intel-iot/joule/joule_adaptor_test.go +++ b/platforms/intel-iot/joule/joule_adaptor_test.go @@ -133,7 +133,7 @@ func TestDigitalIO(t *testing.T) { assert.Equal(t, 0, i) _, err = a.DigitalRead("P9_99") - assert.Error(t, err, "'P9_99' is not a valid id for a digital pin") + assert.ErrorContains(t, err, "'P9_99' is not a valid id for a digital pin") } func TestPwm(t *testing.T) { @@ -144,10 +144,10 @@ func TestPwm(t *testing.T) { assert.Equal(t, "3921568", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) err = a.PwmWrite("4", 100) - assert.Error(t, err, "'4' is not a valid id for a pin") + assert.ErrorContains(t, err, "'4' is not a valid id for a pin") err = a.PwmWrite("J12_1", 100) - assert.Error(t, err, "'J12_1' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'J12_1' is not a valid id for a PWM pin") } func TestPwmPinExportError(t *testing.T) { diff --git a/platforms/jetson/jetson_adaptor_test.go b/platforms/jetson/jetson_adaptor_test.go index 69a4f55f8..cb4cdba2c 100644 --- a/platforms/jetson/jetson_adaptor_test.go +++ b/platforms/jetson/jetson_adaptor_test.go @@ -67,7 +67,7 @@ func TestPWMPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) err := a.PwmWrite("33", 1) - assert.Error(t, err, "not connected") + assert.ErrorContains(t, err, "not connected") err = a.Connect() assert.Nil(t, err) @@ -117,7 +117,7 @@ func TestDigitalIO(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 1, i) - assert.Error(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid id for a digital pin") + assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } diff --git a/platforms/jetson/pwm_pin_test.go b/platforms/jetson/pwm_pin_test.go index f379c99a6..3fd971f5b 100644 --- a/platforms/jetson/pwm_pin_test.go +++ b/platforms/jetson/pwm_pin_test.go @@ -50,15 +50,15 @@ func TestPwmPin(t *testing.T) { assert.True(t, val) _, err := pin.Period() - assert.Error(t, err, "Jetson PWM pin period not set") - assert.Error(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") + assert.ErrorContains(t, err, "Jetson PWM pin period not set") + assert.ErrorContains(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") assert.Equal(t, "", fs.Files[dutyCyclePath].Contents) assert.Nil(t, pin.SetPeriod(20000000)) // TODO: see PR #990 assert.Equal(t, "20000000", fs.Files[periodPath].Contents) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) - assert.Error(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") + assert.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") // TODO: see PR #990 assert.Equal(t, "20000000", fs.Files[periodPath].Contents) dc, _ := pin.DutyCycle() @@ -69,7 +69,7 @@ func TestPwmPin(t *testing.T) { dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) - assert.Error(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") + assert.ErrorContains(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") dc, _ = pin.DutyCycle() assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) assert.Equal(t, uint32(10000), dc) diff --git a/platforms/leap/leap_motion_adaptor_test.go b/platforms/leap/leap_motion_adaptor_test.go index 7b4211bd7..a7f8f8a5b 100644 --- a/platforms/leap/leap_motion_adaptor_test.go +++ b/platforms/leap/leap_motion_adaptor_test.go @@ -37,7 +37,7 @@ func TestLeapMotionAdaptorConnect(t *testing.T) { a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") } - assert.Error(t, a.Connect(), "connection error") + assert.ErrorContains(t, a.Connect(), "connection error") } func TestLeapMotionAdaptorFinalize(t *testing.T) { diff --git a/platforms/mavlink/mavlink_adaptor_test.go b/platforms/mavlink/mavlink_adaptor_test.go index 5c2784e55..6a921515c 100644 --- a/platforms/mavlink/mavlink_adaptor_test.go +++ b/platforms/mavlink/mavlink_adaptor_test.go @@ -69,7 +69,7 @@ func TestMavlinkAdaptorConnect(t *testing.T) { assert.Nil(t, a.Connect()) a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - assert.Error(t, a.Connect(), "connect error") + assert.ErrorContains(t, a.Connect(), "connect error") } func TestMavlinkAdaptorFinalize(t *testing.T) { @@ -79,5 +79,5 @@ func TestMavlinkAdaptorFinalize(t *testing.T) { testAdaptorClose = func() error { return errors.New("close error") } - assert.Error(t, a.Finalize(), "close error") + assert.ErrorContains(t, a.Finalize(), "close error") } diff --git a/platforms/mavlink/mavlink_udp_adaptor_test.go b/platforms/mavlink/mavlink_udp_adaptor_test.go index 18a181fcd..1dffd7cd6 100644 --- a/platforms/mavlink/mavlink_udp_adaptor_test.go +++ b/platforms/mavlink/mavlink_udp_adaptor_test.go @@ -136,5 +136,5 @@ func TestMavlinkReadMAVLinkPacketReadError(t *testing.T) { a.sock = m _, err := a.ReadMAVLinkPacket() - assert.Error(t, err, "read error") + assert.ErrorContains(t, err, "read error") } diff --git a/platforms/microbit/io_pin_driver_test.go b/platforms/microbit/io_pin_driver_test.go index 193828a76..582d3452b 100644 --- a/platforms/microbit/io_pin_driver_test.go +++ b/platforms/microbit/io_pin_driver_test.go @@ -49,7 +49,7 @@ func TestIOPinDriverStartError(t *testing.T) { a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { return nil, errors.New("read error") }) - assert.Error(t, d.Start(), "read error") + assert.ErrorContains(t, d.Start(), "read error") } func TestIOPinDriverDigitalRead(t *testing.T) { @@ -74,7 +74,7 @@ func TestIOPinDriverDigitalReadInvalidPin(t *testing.T) { assert.NotNil(t, err) _, err = d.DigitalRead("6") - assert.Error(t, err, "Invalid pin.") + assert.ErrorContains(t, err, "Invalid pin.") } func TestIOPinDriverDigitalWrite(t *testing.T) { @@ -90,7 +90,7 @@ func TestIOPinDriverDigitalWriteInvalidPin(t *testing.T) { d := NewIOPinDriver(a) assert.NotNil(t, d.DigitalWrite("A3", 1)) - assert.Error(t, d.DigitalWrite("6", 1), "Invalid pin.") + assert.ErrorContains(t, d.DigitalWrite("6", 1), "Invalid pin.") } func TestIOPinDriverAnalogRead(t *testing.T) { @@ -115,7 +115,7 @@ func TestIOPinDriverAnalogReadInvalidPin(t *testing.T) { assert.NotNil(t, err) _, err = d.AnalogRead("6") - assert.Error(t, err, "Invalid pin.") + assert.ErrorContains(t, err, "Invalid pin.") } func TestIOPinDriverDigitalAnalogRead(t *testing.T) { diff --git a/platforms/mqtt/mqtt_adaptor_test.go b/platforms/mqtt/mqtt_adaptor_test.go index b04e99d6c..3da5833c7 100644 --- a/platforms/mqtt/mqtt_adaptor_test.go +++ b/platforms/mqtt/mqtt_adaptor_test.go @@ -85,7 +85,7 @@ func TestMqttAdaptorConnectSSLError(t *testing.T) { func TestMqttAdaptorConnectWithAuthError(t *testing.T) { a := NewAdaptorWithAuth("xyz://localhost:1883", "client", "user", "pass") - assert.Error(t, a.Connect(), "network Error : unknown protocol") + assert.ErrorContains(t, a.Connect(), "network Error : unknown protocol") } func TestMqttAdaptorFinalize(t *testing.T) { diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index 8955cb039..9c120b5d7 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -92,7 +92,7 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("10") assert.Equal(t, 1, i) - assert.Error(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } @@ -101,16 +101,16 @@ func TestInvalidPWMPin(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("666", 42) - assert.Error(t, err, "'666' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") err = a.ServoWrite("666", 120) - assert.Error(t, err, "'666' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") err = a.PwmWrite("3", 42) - assert.Error(t, err, "'3' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") err = a.ServoWrite("3", 120) - assert.Error(t, err, "'3' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") } func TestPwmWrite(t *testing.T) { diff --git a/platforms/nats/nats_adaptor_test.go b/platforms/nats/nats_adaptor_test.go index 1b095f1ed..e0dbd6bea 100644 --- a/platforms/nats/nats_adaptor_test.go +++ b/platforms/nats/nats_adaptor_test.go @@ -148,7 +148,7 @@ func TestNatsAdaptorFailedConnect(t *testing.T) { if err != nil && strings.Contains(err.Error(), "cannot assign requested address") { t.Skip("FLAKY: Can not test, because IP or port is in use.") } - assert.Error(t, err, "nats: no servers available for connection") + assert.ErrorContains(t, err, "nats: no servers available for connection") } func TestNatsAdaptorFinalize(t *testing.T) { diff --git a/platforms/neurosky/neurosky_adaptor_test.go b/platforms/neurosky/neurosky_adaptor_test.go index 4ef684a4a..b52bfddaa 100644 --- a/platforms/neurosky/neurosky_adaptor_test.go +++ b/platforms/neurosky/neurosky_adaptor_test.go @@ -74,7 +74,7 @@ func TestNeuroskyAdaptorConnect(t *testing.T) { a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") } - assert.Error(t, a.Connect(), "connection error") + assert.ErrorContains(t, a.Connect(), "connection error") } func TestNeuroskyAdaptorFinalize(t *testing.T) { @@ -88,5 +88,5 @@ func TestNeuroskyAdaptorFinalize(t *testing.T) { rwc.CloseError(errors.New("close error")) _ = a.Connect() - assert.Error(t, a.Finalize(), "close error") + assert.ErrorContains(t, a.Finalize(), "close error") } diff --git a/platforms/parrot/ardrone/ardrone_adaptor_test.go b/platforms/parrot/ardrone/ardrone_adaptor_test.go index 79893577f..bfaf830f1 100644 --- a/platforms/parrot/ardrone/ardrone_adaptor_test.go +++ b/platforms/parrot/ardrone/ardrone_adaptor_test.go @@ -34,7 +34,7 @@ func TestArdroneAdaptorConnect(t *testing.T) { a.connect = func(a *Adaptor) (drone, error) { return nil, errors.New("connection error") } - assert.Error(t, a.Connect(), "connection error") + assert.ErrorContains(t, a.Connect(), "connection error") } func TestArdroneAdaptorName(t *testing.T) { diff --git a/platforms/parrot/bebop/bebop_adaptor_test.go b/platforms/parrot/bebop/bebop_adaptor_test.go index 061ee871a..7d31d9fcf 100644 --- a/platforms/parrot/bebop/bebop_adaptor_test.go +++ b/platforms/parrot/bebop/bebop_adaptor_test.go @@ -34,7 +34,7 @@ func TestBebopAdaptorConnect(t *testing.T) { a.connect = func(a *Adaptor) error { return errors.New("connection error") } - assert.Error(t, a.Connect(), "connection error") + assert.ErrorContains(t, a.Connect(), "connection error") } func TestBebopAdaptorFinalize(t *testing.T) { diff --git a/platforms/particle/adaptor_test.go b/platforms/particle/adaptor_test.go index e9f4de075..43e2d6c39 100644 --- a/platforms/particle/adaptor_test.go +++ b/platforms/particle/adaptor_test.go @@ -254,7 +254,7 @@ func TestAdaptorFunction(t *testing.T) { a.setAPIServer(testServer.URL) _, err := a.Function("hello", "") - assert.Error(t, err, "timeout") + assert.ErrorContains(t, err, "timeout") testServer.Close() } @@ -309,7 +309,7 @@ func TestAdaptorVariable(t *testing.T) { a.setAPIServer(testServer.URL) _, err := a.Variable("not_existent") - assert.Error(t, err, "Variable not found") + assert.ErrorContains(t, err, "Variable not found") testServer.Close() } @@ -386,14 +386,14 @@ func TestAdaptorEventStream(t *testing.T) { assert.Equal(t, "https://api.particle.io/v1/devices/myDevice/events/ping?access_token=token", url) _, err := a.EventStream("nothing", "ping") - assert.Error(t, err, "source param should be: all, devices or device") + assert.ErrorContains(t, err, "source param should be: all, devices or device") eventSource = func(u string) (chan eventsource.Event, chan error, error) { return nil, nil, errors.New("error connecting sse") } _, err = a.EventStream("devices", "") - assert.Error(t, err, "error connecting sse") + assert.ErrorContains(t, err, "error connecting sse") eventChan := make(chan eventsource.Event) errorChan := make(chan error) diff --git a/platforms/raspi/pwm_pin_test.go b/platforms/raspi/pwm_pin_test.go index 9823b6120..06e842cd4 100644 --- a/platforms/raspi/pwm_pin_test.go +++ b/platforms/raspi/pwm_pin_test.go @@ -29,13 +29,13 @@ func TestPwmPin(t *testing.T) { assert.True(t, val) _, err := pin.Period() - assert.Error(t, err, "Raspi PWM pin period not set") - assert.Error(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") + assert.ErrorContains(t, err, "Raspi PWM pin period not set") + assert.ErrorContains(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") assert.Nil(t, pin.SetPeriod(20000000)) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) - assert.Error(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") + assert.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") dc, _ := pin.DutyCycle() assert.Equal(t, uint32(0), dc) @@ -45,7 +45,7 @@ func TestPwmPin(t *testing.T) { dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) - assert.Error(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") + assert.ErrorContains(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index 8c8444fe8..cba65d377 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -125,8 +125,8 @@ func TestDigitalPWM(t *testing.T) { assert.Equal(t, "17=0.5", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - assert.Error(t, a.PwmWrite("notexist", 1), "Not a valid pin") - assert.Error(t, a.ServoWrite("notexist", 1), "Not a valid pin") + assert.ErrorContains(t, a.PwmWrite("notexist", 1), "Not a valid pin") + assert.ErrorContains(t, a.ServoWrite("notexist", 1), "Not a valid pin") pin, _ = a.PWMPin("12") period, _ = pin.Period() @@ -160,7 +160,7 @@ func TestDigitalIO(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 1, i) - assert.Error(t, a.DigitalWrite("notexist", 1), "Not a valid pin") + assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "Not a valid pin") assert.Nil(t, a.Finalize()) } diff --git a/platforms/sphero/sphero_adaptor_test.go b/platforms/sphero/sphero_adaptor_test.go index d57ca05b7..e51aa2775 100644 --- a/platforms/sphero/sphero_adaptor_test.go +++ b/platforms/sphero/sphero_adaptor_test.go @@ -89,7 +89,7 @@ func TestSpheroAdaptorFinalize(t *testing.T) { } a.connected = true - assert.Error(t, a.Finalize(), "close error") + assert.ErrorContains(t, a.Finalize(), "close error") } func TestSpheroAdaptorConnect(t *testing.T) { @@ -100,5 +100,5 @@ func TestSpheroAdaptorConnect(t *testing.T) { return nil, errors.New("connect error") } - assert.Error(t, a.Connect(), "connect error") + assert.ErrorContains(t, a.Connect(), "connect error") } diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 0f77be93a..4e3abed6b 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -92,7 +92,7 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("10") assert.Equal(t, 1, i) - assert.Error(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } @@ -101,16 +101,16 @@ func TestInvalidPWMPin(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("666", 42) - assert.Error(t, err, "'666' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") err = a.ServoWrite("666", 120) - assert.Error(t, err, "'666' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") err = a.PwmWrite("3", 42) - assert.Error(t, err, "'3' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") err = a.ServoWrite("3", 120) - assert.Error(t, err, "'3' is not a valid id for a PWM pin") + assert.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") } func TestPwmWrite(t *testing.T) { diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index b1a7b5f26..88ace4597 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -77,7 +77,7 @@ func TestDigitalIO(t *testing.T) { fs.Files["/sys/class/leds/upboard:green:/brightness"].Contents, ) - assert.Error(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") assert.Nil(t, a.Finalize()) } diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index c5f35cd37..1c16c518b 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -57,10 +57,10 @@ func TestDigitalPin(t *testing.T) { pin2 := newDigitalPinSysfs(fs, "30") err = pin2.Write(1) - assert.Error(t, err, "pin has not been exported") + assert.ErrorContains(t, err, "pin has not been exported") data, err = pin2.Read() - assert.Error(t, err, "pin has not been exported") + assert.ErrorContains(t, err, "pin has not been exported") assert.Equal(t, 0, data) writeFile = func(File, []byte) (int, error) { @@ -75,7 +75,7 @@ func TestDigitalPin(t *testing.T) { } err = pin.Unexport() - assert.Error(t, err.(*os.PathError).Err, "write error") + assert.ErrorContains(t, err.(*os.PathError).Err, "write error") // assert a busy error is dropped (just means "already exported") cnt := 0 @@ -94,7 +94,7 @@ func TestDigitalPin(t *testing.T) { return 0, &os.PathError{Err: errors.New("write error")} } err = pin.Export() - assert.Error(t, err.(*os.PathError).Err, "write error") + assert.ErrorContains(t, err.(*os.PathError).Err, "write error") } func TestDigitalPinExportError(t *testing.T) { @@ -109,7 +109,7 @@ func TestDigitalPinExportError(t *testing.T) { } err := pin.Export() - assert.Error(t, err, " : /sys/class/gpio/gpio10/direction: no such file") + assert.ErrorContains(t, err, " : /sys/class/gpio/gpio10/direction: no such file") } func TestDigitalPinUnexportError(t *testing.T) { @@ -123,5 +123,5 @@ func TestDigitalPinUnexportError(t *testing.T) { } err := pin.Unexport() - assert.Error(t, err, " : device or resource busy") + assert.ErrorContains(t, err, " : device or resource busy") } diff --git a/system/fs_mock_test.go b/system/fs_mock_test.go index 7e48cb24c..35762890a 100644 --- a/system/fs_mock_test.go +++ b/system/fs_mock_test.go @@ -20,7 +20,7 @@ func TestMockFilesystemOpen(t *testing.T) { assert.Nil(t, err) _, err = fs.openFile("bar", 0, 0o666) - assert.Error(t, err, " : bar: no such file") + assert.ErrorContains(t, err, " : bar: no such file") fs.Add("bar") f4, _ := fs.openFile("bar", 0, 0o666) @@ -39,7 +39,7 @@ func TestMockFilesystemStat(t *testing.T) { assert.True(t, dirStat.IsDir()) _, err = fs.stat("plonk") - assert.Error(t, err, " : plonk: no such file") + assert.ErrorContains(t, err, " : plonk: no such file") } func TestMockFilesystemFind(t *testing.T) { diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index 1e41a83a1..4993a628c 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -79,7 +79,7 @@ func TestNewI2cDevice(t *testing.T) { d, err := a.NewI2cDevice(tc.dev) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) assert.Equal(t, (*i2cDevice)(nil), d) } else { var _ gobot.I2cSystemDevicer = d @@ -142,7 +142,7 @@ func TestReadByte(t *testing.T) { got, err := d.ReadByte(2) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, want, got) @@ -189,7 +189,7 @@ func TestReadByteData(t *testing.T) { got, err := d.ReadByteData(3, reg) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, want, got) @@ -239,7 +239,7 @@ func TestReadWordData(t *testing.T) { got, err := d.ReadWordData(4, reg) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, want, got) @@ -297,7 +297,7 @@ func TestReadBlockData(t *testing.T) { err := d.ReadBlockData(5, reg, buf) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, msc.dataSlice, buf) @@ -341,7 +341,7 @@ func TestWriteByte(t *testing.T) { err := d.WriteByte(6, val) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, d.file, msc.lastFile) @@ -386,7 +386,7 @@ func TestWriteByteData(t *testing.T) { err := d.WriteByteData(7, reg, val) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, d.file, msc.lastFile) @@ -435,7 +435,7 @@ func TestWriteWordData(t *testing.T) { err := d.WriteWordData(8, reg, val) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, d.file, msc.lastFile) @@ -492,7 +492,7 @@ func TestWriteBlockData(t *testing.T) { err := d.WriteBlockData(9, reg, data) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) assert.Equal(t, d.file, msc.lastFile) @@ -514,7 +514,7 @@ func TestWriteBlockDataTooMuch(t *testing.T) { // act err := d.WriteBlockData(10, 0x01, make([]byte, 33)) // assert - assert.Error(t, err, "Writing blocks larger than 32 bytes (33) not supported") + assert.ErrorContains(t, err, "Writing blocks larger than 32 bytes (33) not supported") } func Test_setAddress(t *testing.T) { @@ -565,7 +565,7 @@ func Test_queryFunctionality(t *testing.T) { err := d.queryFunctionality(tc.requested, "test"+name) // assert if tc.wantErr != "" { - assert.Error(t, err, tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { assert.Nil(t, err) } diff --git a/system/pwmpin_sysfs_test.go b/system/pwmpin_sysfs_test.go index ebc901333..d5c9509fb 100644 --- a/system/pwmpin_sysfs_test.go +++ b/system/pwmpin_sysfs_test.go @@ -56,7 +56,7 @@ func TestPwmPin(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents) err = pin.SetPolarity(true) - assert.Error(t, err, "Cannot set PWM polarity when enabled") + assert.ErrorContains(t, err, "Cannot set PWM polarity when enabled") fs.Files["/sys/class/pwm/pwmchip0/pwm10/period"].Contents = "6" data, _ := pin.Period() @@ -107,7 +107,7 @@ func TestPwmPinExportError(t *testing.T) { // no error indicates that the pin was already exported err := pin.Export() - assert.Error(t, err, "Export() failed for id 10 with : bad address") + assert.ErrorContains(t, err, "Export() failed for id 10 with : bad address") } func TestPwmPinUnxportError(t *testing.T) { @@ -125,7 +125,7 @@ func TestPwmPinUnxportError(t *testing.T) { } err := pin.Unexport() - assert.Error(t, err, "Unexport() failed for id 10 with : device or resource busy") + assert.ErrorContains(t, err, "Unexport() failed for id 10 with : device or resource busy") } func TestPwmPinPeriodError(t *testing.T) { @@ -143,7 +143,7 @@ func TestPwmPinPeriodError(t *testing.T) { } _, err := pin.Period() - assert.Error(t, err, "Period() failed for id 10 with : device or resource busy") + assert.ErrorContains(t, err, "Period() failed for id 10 with : device or resource busy") } func TestPwmPinPolarityError(t *testing.T) { @@ -161,7 +161,7 @@ func TestPwmPinPolarityError(t *testing.T) { } _, err := pin.Polarity() - assert.Error(t, err, "Polarity() failed for id 10 with : device or resource busy") + assert.ErrorContains(t, err, "Polarity() failed for id 10 with : device or resource busy") } func TestPwmPinDutyCycleError(t *testing.T) { @@ -179,5 +179,5 @@ func TestPwmPinDutyCycleError(t *testing.T) { } _, err := pin.DutyCycle() - assert.Error(t, err, "DutyCycle() failed for id 10 with : device or resource busy") + assert.ErrorContains(t, err, "DutyCycle() failed for id 10 with : device or resource busy") } From 002c75ce882c704db257b2bec4fd38f92691ed02 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Thu, 26 Oct 2023 20:34:19 +0200 Subject: [PATCH 13/57] test(all): substitude assert.Nil by assert.NoError if useful (#1016) --- drivers/aio/analog_actuator_driver_test.go | 10 +- drivers/aio/analog_sensor_driver_test.go | 8 +- drivers/aio/grove_drivers_test.go | 2 +- .../grove_temperature_sensor_driver_test.go | 4 +- drivers/aio/temperature_sensor_driver_test.go | 10 +- drivers/common/mfrc522/mfrc522_pcd_test.go | 16 ++-- drivers/gpio/aip1640_driver_test.go | 4 +- drivers/gpio/button_driver_test.go | 6 +- drivers/gpio/buzzer_driver_test.go | 6 +- drivers/gpio/direct_pin_driver_test.go | 16 ++-- drivers/gpio/grove_drivers_test.go | 2 +- drivers/gpio/hd44780_driver_test.go | 40 ++++---- drivers/gpio/led_driver_test.go | 4 +- drivers/gpio/makey_button_driver_test.go | 4 +- drivers/gpio/max7219_driver_test.go | 4 +- drivers/gpio/motor_driver_test.go | 4 +- drivers/gpio/pir_motion_driver_test.go | 4 +- drivers/gpio/relay_driver_test.go | 4 +- drivers/gpio/rgb_led_driver_test.go | 6 +- drivers/gpio/servo_driver_test.go | 4 +- drivers/gpio/tm1638_driver_test.go | 4 +- drivers/i2c/adafruit1109_driver_test.go | 20 ++-- drivers/i2c/adafruit_driver_test.go | 56 +++++------ drivers/i2c/ads1x15_driver_1015_test.go | 18 ++-- drivers/i2c/ads1x15_driver_1115_test.go | 18 ++-- drivers/i2c/adxl345_driver_test.go | 12 +-- drivers/i2c/bh1750_driver_test.go | 4 +- drivers/i2c/blinkm_driver_test.go | 4 +- drivers/i2c/bme280_driver_test.go | 4 +- drivers/i2c/bmp180_driver_test.go | 6 +- drivers/i2c/bmp280_driver_test.go | 8 +- drivers/i2c/bmp388_driver_test.go | 8 +- drivers/i2c/ccs811_driver_test.go | 2 +- drivers/i2c/drv2605l_driver_test.go | 16 ++-- drivers/i2c/grovepi_driver_test.go | 2 +- drivers/i2c/hmc5883l_driver_test.go | 6 +- drivers/i2c/hmc6352_driver_test.go | 4 +- drivers/i2c/i2c_connection_test.go | 10 +- drivers/i2c/i2c_driver_test.go | 12 +-- drivers/i2c/ina3221_driver_test.go | 12 +-- drivers/i2c/jhd1313m1_driver_test.go | 24 ++--- drivers/i2c/l3gd20h_driver_test.go | 4 +- drivers/i2c/lidarlite_driver_test.go | 6 +- drivers/i2c/mcp23017_driver_test.go | 24 ++--- drivers/i2c/mma7660_driver_test.go | 4 +- drivers/i2c/mpl115a2_driver_test.go | 6 +- drivers/i2c/mpu6050_driver_test.go | 2 +- drivers/i2c/pca9501_driver_test.go | 10 +- drivers/i2c/pca953x_driver_test.go | 10 +- drivers/i2c/pca9685_driver_test.go | 20 ++-- drivers/i2c/pcf8583_driver_test.go | 16 ++-- drivers/i2c/pcf8591_driver_test.go | 12 +-- drivers/i2c/sht2x_driver_test.go | 12 +-- drivers/i2c/sht3x_driver_test.go | 14 +-- drivers/i2c/ssd1306_driver_test.go | 24 ++--- drivers/i2c/th02_driver_test.go | 10 +- drivers/i2c/tsl2561_driver_test.go | 10 +- drivers/i2c/wiichuck_driver_test.go | 4 +- drivers/i2c/yl40_driver_test.go | 22 ++--- drivers/spi/apa102_test.go | 2 +- drivers/spi/mfrc522_driver_test.go | 2 +- drivers/spi/spi_connection_test.go | 14 +-- drivers/spi/spi_driver_test.go | 4 +- drivers/spi/ssd1306_driver_test.go | 8 +- master_test.go | 12 +-- platforms/adaptors/digitalpinsadaptor_test.go | 38 ++++---- platforms/adaptors/i2cbusadaptor_test.go | 26 ++--- platforms/adaptors/pwmpinsadaptor_test.go | 42 ++++---- platforms/adaptors/spibusadaptor_test.go | 16 ++-- platforms/audio/audio_adaptor_test.go | 4 +- platforms/audio/audio_driver_test.go | 4 +- .../beaglebone/beaglebone_adaptor_test.go | 18 ++-- platforms/ble/battery_driver_test.go | 4 +- .../ble/device_information_driver_test.go | 4 +- platforms/ble/generic_access_driver_test.go | 4 +- platforms/chip/chip_adaptor_test.go | 26 ++--- platforms/dexter/gopigo3/driver_test.go | 4 +- platforms/digispark/digispark_adaptor_test.go | 10 +- platforms/digispark/digispark_i2c_test.go | 24 ++--- .../dragonboard/dragonboard_adaptor_test.go | 12 +-- platforms/firmata/client/client_test.go | 28 +++--- platforms/firmata/firmata_adaptor_test.go | 24 ++--- platforms/firmata/firmata_i2c_test.go | 24 ++--- platforms/intel-iot/curie/imu_driver_test.go | 46 ++++----- .../intel-iot/edison/edison_adaptor_test.go | 40 ++++---- .../intel-iot/joule/joule_adaptor_test.go | 16 ++-- platforms/jetson/jetson_adaptor_test.go | 24 ++--- platforms/jetson/pwm_pin_test.go | 12 +-- platforms/joystick/joystick_adaptor_test.go | 4 +- platforms/joystick/joystick_driver_test.go | 4 +- platforms/keyboard/keyboard_driver_test.go | 4 +- platforms/leap/leap_motion_adaptor_test.go | 4 +- platforms/leap/leap_motion_driver_test.go | 4 +- platforms/mavlink/mavlink_adaptor_test.go | 4 +- platforms/mavlink/mavlink_driver_test.go | 6 +- platforms/mavlink/mavlink_udp_adaptor_test.go | 6 +- .../microbit/accelerometer_driver_test.go | 4 +- platforms/microbit/button_driver_test.go | 4 +- platforms/microbit/io_pin_driver_test.go | 10 +- platforms/microbit/led_driver_test.go | 26 ++--- .../microbit/magnetometer_driver_test.go | 4 +- platforms/microbit/temperature_driver_test.go | 4 +- platforms/mqtt/mqtt_adaptor_test.go | 2 +- platforms/mqtt/mqtt_driver_test.go | 4 +- platforms/nanopi/nanopi_adaptor_test.go | 28 +++--- platforms/nats/nats_adaptor_test.go | 8 +- platforms/nats/nats_driver_test.go | 4 +- platforms/neurosky/neurosky_adaptor_test.go | 4 +- platforms/neurosky/neurosky_driver_test.go | 4 +- platforms/opencv/camera_driver_test.go | 6 +- platforms/opencv/window_driver_test.go | 4 +- .../parrot/ardrone/ardrone_adaptor_test.go | 4 +- .../parrot/ardrone/ardrone_driver_test.go | 4 +- platforms/parrot/bebop/bebop_adaptor_test.go | 4 +- .../parrot/minidrone/minidrone_driver_test.go | 96 +++++++++---------- platforms/particle/adaptor_test.go | 6 +- platforms/pebble/pebble_adaptor_test.go | 4 +- platforms/pebble/pebble_driver_test.go | 4 +- platforms/raspi/pwm_pin_test.go | 12 +-- platforms/raspi/raspi_adaptor_test.go | 38 ++++---- platforms/sphero/bb8/bb8_driver_test.go | 4 +- platforms/sphero/ollie/ollie_driver_test.go | 4 +- platforms/sphero/sphero_adaptor_test.go | 4 +- platforms/sphero/sphero_driver_test.go | 4 +- .../sphero/sprkplus/sprkplus_driver_test.go | 4 +- platforms/tinkerboard/adaptor_test.go | 28 +++--- platforms/upboard/up2/adaptor_test.go | 20 ++-- robot_test.go | 8 +- system/digitalpin_gpiod_test.go | 4 +- system/digitalpin_sysfs_test.go | 12 +-- system/fs_mock_test.go | 14 +-- system/fs_test.go | 4 +- system/i2c_device_test.go | 28 +++--- system/pwmpin_sysfs_test.go | 16 ++-- system/system_test.go | 2 +- 135 files changed, 795 insertions(+), 795 deletions(-) diff --git a/drivers/aio/analog_actuator_driver_test.go b/drivers/aio/analog_actuator_driver_test.go index 3508fe720..9124777b0 100644 --- a/drivers/aio/analog_actuator_driver_test.go +++ b/drivers/aio/analog_actuator_driver_test.go @@ -15,12 +15,12 @@ func TestAnalogActuatorDriver(t *testing.T) { assert.Equal(t, "47", d.Pin()) err := d.RawWrite(100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, 100, a.written[0]) err = d.Write(247.0) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(a.written)) assert.Equal(t, 247, a.written[1]) assert.Equal(t, 247, d.RawValue()) @@ -76,7 +76,7 @@ func TestAnalogActuatorDriverLinearScaler(t *testing.T) { // act err := d.Write(tt.input) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, tt.want, a.written[0]) }) @@ -85,12 +85,12 @@ func TestAnalogActuatorDriverLinearScaler(t *testing.T) { func TestAnalogActuatorDriverStart(t *testing.T) { d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestAnalogActuatorDriverHalt(t *testing.T) { d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestAnalogActuatorDriverDefaultName(t *testing.T) { diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index 1b6a048a7..0ed0ddc85 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -48,7 +48,7 @@ func TestAnalogSensorDriver(t *testing.T) { }) assert.Equal(t, 0.0, d.Value()) val, err := d.Read() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 150.0, val) assert.Equal(t, 150.0, d.Value()) assert.Equal(t, 150, d.RawValue()) @@ -84,7 +84,7 @@ func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { // act got, err := d.Read() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.want, got) }) } @@ -113,7 +113,7 @@ func TestAnalogSensorDriverStart(t *testing.T) { return }) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) select { case <-sem: @@ -169,7 +169,7 @@ func TestAnalogSensorDriverHalt(t *testing.T) { <-d.halt close(done) }() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) select { case <-done: case <-time.After(100 * time.Millisecond): diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go index dd7b7b64b..13b1d1bde 100644 --- a/drivers/aio/grove_drivers_test.go +++ b/drivers/aio/grove_drivers_test.go @@ -90,7 +90,7 @@ func TestDriverPublishesError(t *testing.T) { } testAdaptor.TestAdaptorAnalogRead(returnErr) - assert.Nil(t, driver.Start()) + assert.NoError(t, driver.Start()) // expect error _ = driver.Once(driver.Event(Error), func(data interface{}) { diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index c7a3a3070..7d13996e3 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -47,7 +47,7 @@ func TestGroveTemperatureSensorDriverScaling(t *testing.T) { // act got, err := d.Read() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.want, got) }) } @@ -66,7 +66,7 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) select { case <-sem: diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index 1ae246e8f..eaf5e9027 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -48,7 +48,7 @@ func TestTemperatureSensorDriverNtcScaling(t *testing.T) { // act got, err := d.Read() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.want, got) }) } @@ -83,7 +83,7 @@ func TestTemperatureSensorDriverLinearScaling(t *testing.T) { // act got, err := d.Read() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.want, got) }) } @@ -104,7 +104,7 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.T) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) select { case <-sem: @@ -126,7 +126,7 @@ func TestTempSensorPublishesError(t *testing.T) { return }) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) // expect error _ = d.Once(d.Event(Error), func(data interface{}) { @@ -148,7 +148,7 @@ func TestTempSensorHalt(t *testing.T) { <-d.halt close(done) }() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) select { case <-done: case <-time.After(100 * time.Millisecond): diff --git a/drivers/common/mfrc522/mfrc522_pcd_test.go b/drivers/common/mfrc522/mfrc522_pcd_test.go index 045c0e4f4..891d60ea6 100644 --- a/drivers/common/mfrc522/mfrc522_pcd_test.go +++ b/drivers/common/mfrc522/mfrc522_pcd_test.go @@ -63,7 +63,7 @@ func TestInitialize(t *testing.T) { // act err := d.Initialize(c) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, c, d.connection) assert.Equal(t, wantSoftReset, c.written[:3]) assert.Equal(t, wantInit, c.written[3:21]) @@ -80,7 +80,7 @@ func Test_getVersion(t *testing.T) { // act got, err := d.getVersion() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, wantWritten, c.written) } @@ -120,7 +120,7 @@ func Test_switchAntenna(t *testing.T) { // act err := d.switchAntenna(tc.target) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantWritten, c.written) }) } @@ -134,7 +134,7 @@ func Test_stopCrypto1(t *testing.T) { // act err := d.stopCrypto1() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, wantWritten, c.written) } @@ -158,7 +158,7 @@ func Test_communicateWithPICC(t *testing.T) { // transceive, all 8 bits, no CRC err := d.communicateWithPICC(0x0C, dataToFifo, backData, 0x00, false) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, writtenPrepare, c.written[:8]) assert.Equal(t, writtenWriteFifo, c.written[8:12]) assert.Equal(t, writtenTransceive, c.written[12:16]) @@ -181,7 +181,7 @@ func Test_calculateCRC(t *testing.T) { // act err := d.calculateCRC(dataToFifo, gotCrcBack) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, writtenPrepare, c.written[:6]) assert.Equal(t, writtenFifo, c.written[6:10]) assert.Equal(t, writtenCalc, c.written[10:15]) @@ -197,7 +197,7 @@ func Test_writeFifo(t *testing.T) { // act err := d.writeFifo(dataToFifo) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, wantWritten, c.written) } @@ -210,7 +210,7 @@ func Test_readFifo(t *testing.T) { // act _, err := d.readFifo(backData) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, wantWritten, c.written) assert.Equal(t, c.simFifo, backData) } diff --git a/drivers/gpio/aip1640_driver_test.go b/drivers/gpio/aip1640_driver_test.go index 2b63ac39c..d7d8e256b 100644 --- a/drivers/gpio/aip1640_driver_test.go +++ b/drivers/gpio/aip1640_driver_test.go @@ -32,12 +32,12 @@ func TestAIP1640Driver(t *testing.T) { func TestAIP1640DriverStart(t *testing.T) { d := initTestAIP1640Driver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestAIP1640DriverHalt(t *testing.T) { d := initTestAIP1640Driver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestAIP1640DriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/button_driver_test.go b/drivers/gpio/button_driver_test.go index 7910bc7bc..03d07e105 100644 --- a/drivers/gpio/button_driver_test.go +++ b/drivers/gpio/button_driver_test.go @@ -23,7 +23,7 @@ func TestButtonDriverHalt(t *testing.T) { go func() { <-d.halt }() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestButtonDriver(t *testing.T) { @@ -49,7 +49,7 @@ func TestButtonDriverStart(t *testing.T) { return }) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) select { case <-sem: @@ -122,7 +122,7 @@ func TestButtonDriverDefaultState(t *testing.T) { return }) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) select { case <-sem: diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index db2fd8ba4..8fcd5ddff 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -28,12 +28,12 @@ func TestBuzzerDriverSetName(t *testing.T) { func TestBuzzerDriverStart(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestBuzzerDriverHalt(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestBuzzerDriverToggle(t *testing.T) { @@ -47,7 +47,7 @@ func TestBuzzerDriverToggle(t *testing.T) { func TestBuzzerDriverTone(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - assert.Nil(t, d.Tone(100, 0.01)) + assert.NoError(t, d.Tone(100, 0.01)) } func TestBuzzerDriverOnError(t *testing.T) { diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index 90252f682..59e78a414 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -54,12 +54,12 @@ func TestDirectPinDriver(t *testing.T) { func TestDirectPinDriverStart(t *testing.T) { d := initTestDirectPinDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestDirectPinDriverHalt(t *testing.T) { d := initTestDirectPinDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestDirectPinDriverOff(t *testing.T) { @@ -68,7 +68,7 @@ func TestDirectPinDriverOff(t *testing.T) { a := newGpioTestAdaptor() d = NewDirectPinDriver(a, "1") - assert.Nil(t, d.Off()) + assert.NoError(t, d.Off()) } func TestDirectPinDriverOffNotSupported(t *testing.T) { @@ -80,7 +80,7 @@ func TestDirectPinDriverOffNotSupported(t *testing.T) { func TestDirectPinDriverOn(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - assert.Nil(t, d.On()) + assert.NoError(t, d.On()) } func TestDirectPinDriverOnError(t *testing.T) { @@ -97,7 +97,7 @@ func TestDirectPinDriverOnNotSupported(t *testing.T) { func TestDirectPinDriverDigitalWrite(t *testing.T) { adaptor := newGpioTestAdaptor() d := NewDirectPinDriver(adaptor, "1") - assert.Nil(t, d.DigitalWrite(1)) + assert.NoError(t, d.DigitalWrite(1)) } func TestDirectPinDriverDigitalWriteNotSupported(t *testing.T) { @@ -115,7 +115,7 @@ func TestDirectPinDriverDigitalRead(t *testing.T) { d := initTestDirectPinDriver() ret, err := d.DigitalRead() assert.Equal(t, 1, ret) - assert.Nil(t, err) + assert.NoError(t, err) } func TestDirectPinDriverDigitalReadNotSupported(t *testing.T) { @@ -128,7 +128,7 @@ func TestDirectPinDriverDigitalReadNotSupported(t *testing.T) { func TestDirectPinDriverPwmWrite(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - assert.Nil(t, d.PwmWrite(1)) + assert.NoError(t, d.PwmWrite(1)) } func TestDirectPinDriverPwmWriteNotSupported(t *testing.T) { @@ -145,7 +145,7 @@ func TestDirectPinDriverPwmWriteError(t *testing.T) { func TestDirectPinDriverServoWrite(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - assert.Nil(t, d.ServoWrite(1)) + assert.NoError(t, d.ServoWrite(1)) } func TestDirectPinDriverServoWriteNotSupported(t *testing.T) { diff --git a/drivers/gpio/grove_drivers_test.go b/drivers/gpio/grove_drivers_test.go index d201a41a3..19ee99eb4 100644 --- a/drivers/gpio/grove_drivers_test.go +++ b/drivers/gpio/grove_drivers_test.go @@ -91,7 +91,7 @@ func TestDriverPublishesError(t *testing.T) { } testAdaptor.testAdaptorDigitalRead = returnErr - assert.Nil(t, driver.Start()) + assert.NoError(t, driver.Start()) // expect error _ = driver.Once(driver.Event(Error), func(data interface{}) { diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index 91f0541be..6bc2b1592 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -61,7 +61,7 @@ func TestHD44780Driver(t *testing.T) { func TestHD44780DriverHalt(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestHD44780DriverDefaultName(t *testing.T) { @@ -77,7 +77,7 @@ func TestHD44780DriverSetName(t *testing.T) { func TestHD44780DriverStart(t *testing.T) { d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestHD44780DriverStartError(t *testing.T) { @@ -114,11 +114,11 @@ func TestHD44780DriverWrite(t *testing.T) { d, _ = initTestHD44780Driver4BitModeWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Write("hello gobot")) + assert.NoError(t, d.Write("hello gobot")) d, _ = initTestHD44780Driver8BitModeWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Write("hello gobot")) + assert.NoError(t, d.Write("hello gobot")) } func TestHD44780DriverWriteError(t *testing.T) { @@ -142,17 +142,17 @@ func TestHD44780DriverWriteError(t *testing.T) { func TestHD44780DriverClear(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Clear()) + assert.NoError(t, d.Clear()) } func TestHD44780DriverHome(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Home()) + assert.NoError(t, d.Home()) } func TestHD44780DriverSetCursor(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.SetCursor(0, 3)) + assert.NoError(t, d.SetCursor(0, 3)) } func TestHD44780DriverSetCursorInvalid(t *testing.T) { @@ -166,68 +166,68 @@ func TestHD44780DriverSetCursorInvalid(t *testing.T) { func TestHD44780DriverDisplayOn(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Display(true)) + assert.NoError(t, d.Display(true)) } func TestHD44780DriverDisplayOff(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Display(false)) + assert.NoError(t, d.Display(false)) } func TestHD44780DriverCursorOn(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Cursor(true)) + assert.NoError(t, d.Cursor(true)) } func TestHD44780DriverCursorOff(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Cursor(false)) + assert.NoError(t, d.Cursor(false)) } func TestHD44780DriverBlinkOn(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Blink(true)) + assert.NoError(t, d.Blink(true)) } func TestHD44780DriverBlinkOff(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.Blink(false)) + assert.NoError(t, d.Blink(false)) } func TestHD44780DriverScrollLeft(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.ScrollLeft()) + assert.NoError(t, d.ScrollLeft()) } func TestHD44780DriverScrollRight(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.ScrollRight()) + assert.NoError(t, d.ScrollRight()) } func TestHD44780DriverLeftToRight(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.LeftToRight()) + assert.NoError(t, d.LeftToRight()) } func TestHD44780DriverRightToLeft(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.RightToLeft()) + assert.NoError(t, d.RightToLeft()) } func TestHD44780DriverSendCommand(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.SendCommand(0x33)) + assert.NoError(t, d.SendCommand(0x33)) } func TestHD44780DriverWriteChar(t *testing.T) { d := initTestHD44780Driver() - assert.Nil(t, d.WriteChar(0x41)) + assert.NoError(t, d.WriteChar(0x41)) } func TestHD44780DriverCreateChar(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - assert.Nil(t, d.CreateChar(0, charMap)) + assert.NoError(t, d.CreateChar(0, charMap)) } func TestHD44780DriverCreateCharError(t *testing.T) { diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index c3e7c2c48..b05a10522 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -52,12 +52,12 @@ func TestLedDriver(t *testing.T) { func TestLedDriverStart(t *testing.T) { d := initTestLedDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestLedDriverHalt(t *testing.T) { d := initTestLedDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestLedDriverToggle(t *testing.T) { diff --git a/drivers/gpio/makey_button_driver_test.go b/drivers/gpio/makey_button_driver_test.go index c810f767b..ef3711135 100644 --- a/drivers/gpio/makey_button_driver_test.go +++ b/drivers/gpio/makey_button_driver_test.go @@ -24,7 +24,7 @@ func TestMakeyButtonDriverHalt(t *testing.T) { <-d.halt close(done) }() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) select { case <-done: case <-time.After(makeyTestDelay * time.Millisecond): @@ -47,7 +47,7 @@ func TestMakeyButtonDriverStart(t *testing.T) { a := newGpioTestAdaptor() d := NewMakeyButtonDriver(a, "1") - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) _ = d.Once(ButtonPush, func(data interface{}) { assert.True(t, d.Active) diff --git a/drivers/gpio/max7219_driver_test.go b/drivers/gpio/max7219_driver_test.go index 22e92efbb..9fab6bd22 100644 --- a/drivers/gpio/max7219_driver_test.go +++ b/drivers/gpio/max7219_driver_test.go @@ -32,12 +32,12 @@ func TestMAX7219Driver(t *testing.T) { func TestMAX7219DriverStart(t *testing.T) { d := initTestMAX7219Driver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestMAX7219DriverHalt(t *testing.T) { d := initTestMAX7219Driver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestMAX7219DriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/motor_driver_test.go b/drivers/gpio/motor_driver_test.go index 749cba7b8..6ec1c9142 100644 --- a/drivers/gpio/motor_driver_test.go +++ b/drivers/gpio/motor_driver_test.go @@ -21,12 +21,12 @@ func TestMotorDriver(t *testing.T) { func TestMotorDriverStart(t *testing.T) { d := initTestMotorDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestMotorDriverHalt(t *testing.T) { d := initTestMotorDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestMotorDriverIsOn(t *testing.T) { diff --git a/drivers/gpio/pir_motion_driver_test.go b/drivers/gpio/pir_motion_driver_test.go index b7a7e87bc..9d83d70fd 100644 --- a/drivers/gpio/pir_motion_driver_test.go +++ b/drivers/gpio/pir_motion_driver_test.go @@ -23,7 +23,7 @@ func TestPIRMotionDriverHalt(t *testing.T) { go func() { <-d.halt }() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestPIRMotionDriver(t *testing.T) { @@ -39,7 +39,7 @@ func TestPIRMotionDriverStart(t *testing.T) { a := newGpioTestAdaptor() d := NewPIRMotionDriver(a, "1") - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) _ = d.Once(MotionDetected, func(data interface{}) { assert.True(t, d.Active) diff --git a/drivers/gpio/relay_driver_test.go b/drivers/gpio/relay_driver_test.go index c920871f0..3abae423f 100644 --- a/drivers/gpio/relay_driver_test.go +++ b/drivers/gpio/relay_driver_test.go @@ -38,12 +38,12 @@ func TestRelayDriverSetName(t *testing.T) { func TestRelayDriverStart(t *testing.T) { d, _ := initTestRelayDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestRelayDriverHalt(t *testing.T) { d, _ := initTestRelayDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestRelayDriverToggle(t *testing.T) { diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index 3aa0cc387..e66fa0e7e 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -56,12 +56,12 @@ func TestRgbLedDriver(t *testing.T) { func TestRgbLedDriverStart(t *testing.T) { d := initTestRgbLedDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestRgbLedDriverHalt(t *testing.T) { d := initTestRgbLedDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestRgbLedDriverToggle(t *testing.T) { @@ -76,7 +76,7 @@ func TestRgbLedDriverToggle(t *testing.T) { func TestRgbLedDriverSetLevel(t *testing.T) { a := newGpioTestAdaptor() d := NewRgbLedDriver(a, "1", "2", "3") - assert.Nil(t, d.SetLevel("1", 150)) + assert.NoError(t, d.SetLevel("1", 150)) d = NewRgbLedDriver(a, "1", "2", "3") a.testAdaptorPwmWrite = func(string, byte) (err error) { diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index 684646bf8..a3ac2b2ac 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -43,12 +43,12 @@ func TestServoDriver(t *testing.T) { func TestServoDriverStart(t *testing.T) { d := initTestServoDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestServoDriverHalt(t *testing.T) { d := initTestServoDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestServoDriverMove(t *testing.T) { diff --git a/drivers/gpio/tm1638_driver_test.go b/drivers/gpio/tm1638_driver_test.go index e7e5b7682..dc5ce2718 100644 --- a/drivers/gpio/tm1638_driver_test.go +++ b/drivers/gpio/tm1638_driver_test.go @@ -32,12 +32,12 @@ func TestTM1638Driver(t *testing.T) { func TestTM1638DriverStart(t *testing.T) { d := initTestTM1638Driver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestTM1638DriverHalt(t *testing.T) { d := initTestTM1638Driver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestTM1638DriverDefaultName(t *testing.T) { diff --git a/drivers/i2c/adafruit1109_driver_test.go b/drivers/i2c/adafruit1109_driver_test.go index c3176beb0..bea0e179f 100644 --- a/drivers/i2c/adafruit1109_driver_test.go +++ b/drivers/i2c/adafruit1109_driver_test.go @@ -49,12 +49,12 @@ func TestNewAdafruit1109Driver(t *testing.T) { func TestAdafruit1109Connect(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - assert.Nil(t, d.Connect()) + assert.NoError(t, d.Connect()) } func TestAdafruit1109Finalize(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - assert.Nil(t, d.Finalize()) + assert.NoError(t, d.Finalize()) } func TestAdafruit1109SetName(t *testing.T) { @@ -65,7 +65,7 @@ func TestAdafruit1109SetName(t *testing.T) { func TestAdafruit1109Start(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestAdafruit1109StartWriteErr(t *testing.T) { @@ -87,7 +87,7 @@ func TestAdafruit1109StartReadErr(t *testing.T) { func TestAdafruit1109Halt(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestAdafruit1109DigitalRead(t *testing.T) { @@ -128,7 +128,7 @@ func TestAdafruit1109DigitalRead(t *testing.T) { // act got, err := d.DigitalRead(name) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 1, len(a.written)) assert.Equal(t, tc.wantReg, a.written[0]) @@ -160,7 +160,7 @@ func TestAdafruit1109SelectButton(t *testing.T) { // act got, err := d.SelectButton() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) @@ -190,7 +190,7 @@ func TestAdafruit1109UpButton(t *testing.T) { // act got, err := d.UpButton() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) @@ -220,7 +220,7 @@ func TestAdafruit1109DownButton(t *testing.T) { // act got, err := d.DownButton() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) @@ -250,7 +250,7 @@ func TestAdafruit1109LeftButton(t *testing.T) { // act got, err := d.LeftButton() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) @@ -280,7 +280,7 @@ func TestAdafruit1109RightButton(t *testing.T) { // act got, err := d.RightButton() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) diff --git a/drivers/i2c/adafruit_driver_test.go b/drivers/i2c/adafruit_driver_test.go index 0835422f4..e8f2570bb 100644 --- a/drivers/i2c/adafruit_driver_test.go +++ b/drivers/i2c/adafruit_driver_test.go @@ -37,7 +37,7 @@ func TestNewAdafruitMotorHatDriver(t *testing.T) { func TestAdafruitMotorHatDriverStart(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() assert.NotNil(t, ada.Connection()) - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) } func TestAdafruitMotorHatDriverStartWriteError(t *testing.T) { @@ -65,7 +65,7 @@ func TestAdafruitMotorHatDriverStartConnectError(t *testing.T) { func TestAdafruitMotorHatDriverHalt(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Halt()) + assert.NoError(t, ada.Halt()) } func TestSetHatAddresses(t *testing.T) { @@ -73,24 +73,24 @@ func TestSetHatAddresses(t *testing.T) { motorHatAddr := 0x61 servoHatAddr := 0x41 - assert.Nil(t, ada.SetMotorHatAddress(motorHatAddr)) - assert.Nil(t, ada.SetServoHatAddress(servoHatAddr)) + assert.NoError(t, ada.SetMotorHatAddress(motorHatAddr)) + assert.NoError(t, ada.SetServoHatAddress(servoHatAddr)) } func TestAdafruitMotorHatDriverSetServoMotorFreq(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) freq := 60.0 err := ada.SetServoMotorFreq(freq) - assert.Nil(t, err) + assert.NoError(t, err) } func TestAdafruitMotorHatDriverSetServoMotorFreqError(t *testing.T) { ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } @@ -102,19 +102,19 @@ func TestAdafruitMotorHatDriverSetServoMotorFreqError(t *testing.T) { func TestAdafruitMotorHatDriverSetServoMotorPulse(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) var channel byte = 7 var on int32 = 1234 var off int32 = 4321 err := ada.SetServoMotorPulse(channel, on, off) - assert.Nil(t, err) + assert.NoError(t, err) } func TestAdafruitMotorHatDriverSetServoMotorPulseError(t *testing.T) { ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } @@ -128,18 +128,18 @@ func TestAdafruitMotorHatDriverSetServoMotorPulseError(t *testing.T) { func TestAdafruitMotorHatDriverSetDCMotorSpeed(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) dcMotor := 1 var speed int32 = 255 err := ada.SetDCMotorSpeed(dcMotor, speed) - assert.Nil(t, err) + assert.NoError(t, err) } func TestAdafruitMotorHatDriverSetDCMotorSpeedError(t *testing.T) { ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } @@ -150,17 +150,17 @@ func TestAdafruitMotorHatDriverSetDCMotorSpeedError(t *testing.T) { func TestAdafruitMotorHatDriverRunDCMotor(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) dcMotor := 1 - assert.Nil(t, ada.RunDCMotor(dcMotor, AdafruitForward)) - assert.Nil(t, ada.RunDCMotor(dcMotor, AdafruitBackward)) - assert.Nil(t, ada.RunDCMotor(dcMotor, AdafruitRelease)) + assert.NoError(t, ada.RunDCMotor(dcMotor, AdafruitForward)) + assert.NoError(t, ada.RunDCMotor(dcMotor, AdafruitBackward)) + assert.NoError(t, ada.RunDCMotor(dcMotor, AdafruitRelease)) } func TestAdafruitMotorHatDriverRunDCMotorError(t *testing.T) { ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } @@ -174,63 +174,63 @@ func TestAdafruitMotorHatDriverRunDCMotorError(t *testing.T) { func TestAdafruitMotorHatDriverSetStepperMotorSpeed(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) stepperMotor := 1 rpm := 30 - assert.Nil(t, ada.SetStepperMotorSpeed(stepperMotor, rpm)) + assert.NoError(t, ada.SetStepperMotorSpeed(stepperMotor, rpm)) } func TestAdafruitMotorHatDriverStepperMicroStep(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) // NOTE: not using the direction and style constants to prevent importing // the i2c package stepperMotor := 0 steps := 50 err := ada.Step(stepperMotor, steps, 1, 3) - assert.Nil(t, err) + assert.NoError(t, err) } func TestAdafruitMotorHatDriverStepperSingleStep(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) // NOTE: not using the direction and style constants to prevent importing // the i2c package stepperMotor := 0 steps := 50 err := ada.Step(stepperMotor, steps, 1, 0) - assert.Nil(t, err) + assert.NoError(t, err) } func TestAdafruitMotorHatDriverStepperDoubleStep(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) // NOTE: not using the direction and style constants to prevent importing // the i2c package stepperMotor := 0 steps := 50 err := ada.Step(stepperMotor, steps, 1, 1) - assert.Nil(t, err) + assert.NoError(t, err) } func TestAdafruitMotorHatDriverStepperInterleaveStep(t *testing.T) { ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.Nil(t, ada.Start()) + assert.NoError(t, ada.Start()) // NOTE: not using the direction and style constants to prevent importing // the i2c package stepperMotor := 0 steps := 50 err := ada.Step(stepperMotor, steps, 1, 2) - assert.Nil(t, err) + assert.NoError(t, err) } func TestAdafruitMotorHatDriverSetName(t *testing.T) { diff --git a/drivers/i2c/ads1x15_driver_1015_test.go b/drivers/i2c/ads1x15_driver_1015_test.go index 66e772935..be88c09ee 100644 --- a/drivers/i2c/ads1x15_driver_1015_test.go +++ b/drivers/i2c/ads1x15_driver_1015_test.go @@ -73,35 +73,35 @@ func TestADS1015AnalogRead(t *testing.T) { val, err := d.AnalogRead("0") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("1") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("2") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("3") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("0-1") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("0-3") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("1-3") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("2-3") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) _, err = d.AnalogRead("3-2") assert.NotNil(t, err.Error()) @@ -269,7 +269,7 @@ func TestADS1015_rawRead(t *testing.T) { // act got, err := d.rawRead(channel, channelOffset, tt.gain, tt.dataRate) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.want, got) assert.Equal(t, 3, numCallsRead) assert.Equal(t, 6, len(a.written)) diff --git a/drivers/i2c/ads1x15_driver_1115_test.go b/drivers/i2c/ads1x15_driver_1115_test.go index 0db0efd0a..03c7e4b81 100644 --- a/drivers/i2c/ads1x15_driver_1115_test.go +++ b/drivers/i2c/ads1x15_driver_1115_test.go @@ -73,35 +73,35 @@ func TestADS1115AnalogRead(t *testing.T) { val, err := d.AnalogRead("0") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("1") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("2") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("3") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("0-1") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("0-3") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("1-3") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = d.AnalogRead("2-3") assert.Equal(t, 32767, val) - assert.Nil(t, err) + assert.NoError(t, err) _, err = d.AnalogRead("3-2") assert.NotNil(t, err.Error()) @@ -269,7 +269,7 @@ func TestADS1115_rawRead(t *testing.T) { // act got, err := d.rawRead(channel, channelOffset, tt.gain, tt.dataRate) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tt.want, got) assert.Equal(t, 3, numCallsRead) assert.Equal(t, 6, len(a.written)) diff --git a/drivers/i2c/adxl345_driver_test.go b/drivers/i2c/adxl345_driver_test.go index dce07fecd..51e4b287e 100644 --- a/drivers/i2c/adxl345_driver_test.go +++ b/drivers/i2c/adxl345_driver_test.go @@ -85,7 +85,7 @@ func TestADXL345UseLowPower(t *testing.T) { // act err := d.UseLowPower(setVal) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, setVal, d.bwRate.lowPower) assert.Equal(t, 2, len(a.written)) assert.Equal(t, wantReg, a.written[0]) @@ -107,7 +107,7 @@ func TestADXL345SetRate(t *testing.T) { // act err := d.SetRate(setVal) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, setVal, d.bwRate.rate) assert.Equal(t, 2, len(a.written)) assert.Equal(t, wantReg, a.written[0]) @@ -129,7 +129,7 @@ func TestADXL345SetRange(t *testing.T) { // act err := d.SetRange(setVal) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, setVal, d.dataFormat.fullScaleRange) assert.Equal(t, 2, len(a.written)) assert.Equal(t, wantReg, a.written[0]) @@ -184,7 +184,7 @@ func TestADXL345RawXYZ(t *testing.T) { // act gotX, gotY, gotZ, err := d.RawXYZ() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantX, gotX) assert.Equal(t, tc.wantY, gotY) assert.Equal(t, tc.wantZ, gotZ) @@ -292,7 +292,7 @@ func TestADXL345_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 6, len(a.written)) assert.Equal(t, wantRateReg, a.written[0]) assert.Equal(t, wantRateRegVal, a.written[1]) @@ -316,7 +316,7 @@ func TestADXL345_shutdown(t *testing.T) { // act, assert - shutdown() must be called on Halt() err := d.Halt() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(a.written)) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantVal, a.written[1]) diff --git a/drivers/i2c/bh1750_driver_test.go b/drivers/i2c/bh1750_driver_test.go index bb0fa1872..c75f59bd3 100644 --- a/drivers/i2c/bh1750_driver_test.go +++ b/drivers/i2c/bh1750_driver_test.go @@ -43,12 +43,12 @@ func TestBH1750Options(t *testing.T) { func TestBH1750Start(t *testing.T) { d := NewBH1750Driver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestBH1750Halt(t *testing.T) { d, _ := initTestBH1750DriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestBH1750NullLux(t *testing.T) { diff --git a/drivers/i2c/blinkm_driver_test.go b/drivers/i2c/blinkm_driver_test.go index e88fb4f7c..3e0811cc3 100644 --- a/drivers/i2c/blinkm_driver_test.go +++ b/drivers/i2c/blinkm_driver_test.go @@ -42,12 +42,12 @@ func TestBlinkMOptions(t *testing.T) { func TestBlinkMStart(t *testing.T) { d := NewBlinkMDriver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestBlinkMHalt(t *testing.T) { d, _ := initTestBlinkMDriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } // Commands diff --git a/drivers/i2c/bme280_driver_test.go b/drivers/i2c/bme280_driver_test.go index 9be6ef97a..49e049e6c 100644 --- a/drivers/i2c/bme280_driver_test.go +++ b/drivers/i2c/bme280_driver_test.go @@ -72,7 +72,7 @@ func TestBME280Measurements(t *testing.T) { } _ = bme280.Start() hum, err := bme280.Humidity() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(51.20179), hum) } @@ -186,5 +186,5 @@ func TestBME280_initializationBME280(t *testing.T) { } return 0, nil } - assert.Nil(t, bme280.Start()) + assert.NoError(t, bme280.Start()) } diff --git a/drivers/i2c/bmp180_driver_test.go b/drivers/i2c/bmp180_driver_test.go index 0c4648131..39033d9df 100644 --- a/drivers/i2c/bmp180_driver_test.go +++ b/drivers/i2c/bmp180_driver_test.go @@ -72,10 +72,10 @@ func TestBMP180Measurements(t *testing.T) { } _ = bmp180.Start() temp, err := bmp180.Temperature() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(15.0), temp) pressure, err := bmp180.Pressure() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(69964), pressure) } @@ -183,7 +183,7 @@ func TestBMP180_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(0xAA), a.written[0]) diff --git a/drivers/i2c/bmp280_driver_test.go b/drivers/i2c/bmp280_driver_test.go index b83e3ea6c..354e8bae1 100644 --- a/drivers/i2c/bmp280_driver_test.go +++ b/drivers/i2c/bmp280_driver_test.go @@ -88,13 +88,13 @@ func TestBMP280Measurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(25.014637), temp) pressure, err := d.Pressure() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(99545.414), pressure) alt, err := d.Altitude() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(149.22713), alt) } @@ -188,7 +188,7 @@ func TestBMP280_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 5, len(a.written)) assert.Equal(t, wantCalibReg, a.written[0]) diff --git a/drivers/i2c/bmp388_driver_test.go b/drivers/i2c/bmp388_driver_test.go index 7222fd301..59d3f224b 100644 --- a/drivers/i2c/bmp388_driver_test.go +++ b/drivers/i2c/bmp388_driver_test.go @@ -84,13 +84,13 @@ func TestBMP388Measurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature(2) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(22.906143), temp) pressure, err := d.Pressure(2) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(98874.85), pressure) alt, err := d.Altitude(2) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(205.89395), alt) } @@ -176,7 +176,7 @@ func TestBMP388_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, numCallsRead) assert.Equal(t, 6, len(a.written)) assert.Equal(t, wantChipIDReg, a.written[0]) diff --git a/drivers/i2c/ccs811_driver_test.go b/drivers/i2c/ccs811_driver_test.go index 8ac004940..b28a554d5 100644 --- a/drivers/i2c/ccs811_driver_test.go +++ b/drivers/i2c/ccs811_driver_test.go @@ -255,7 +255,7 @@ func TestCCS811_initialize(t *testing.T) { // arrange, act - initialize() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 9, len(a.written)) assert.Equal(t, wantChipIDReg, a.written[0]) diff --git a/drivers/i2c/drv2605l_driver_test.go b/drivers/i2c/drv2605l_driver_test.go index 7e534b3f7..6ec3bda11 100644 --- a/drivers/i2c/drv2605l_driver_test.go +++ b/drivers/i2c/drv2605l_driver_test.go @@ -51,7 +51,7 @@ func TestDRV2605LOptions(t *testing.T) { func TestDRV2605LStart(t *testing.T) { d := NewDRV2605LDriver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestDRV2605LHalt(t *testing.T) { @@ -62,7 +62,7 @@ func TestDRV2605LHalt(t *testing.T) { writeNewStandbyModeData := []byte{drv2605RegMode, 42 | drv2605Standby} d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) assert.Equal(t, append(append(writeStopPlaybackData, readCurrentStandbyModeData), writeNewStandbyModeData...), a.written) } @@ -76,7 +76,7 @@ func TestDRV2605LGetPause(t *testing.T) { func TestDRV2605LSequenceTermination(t *testing.T) { d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - assert.Nil(t, d.SetSequence([]byte{1, 2})) + assert.NoError(t, d.SetSequence([]byte{1, 2})) assert.Equal(t, []byte{ drv2605RegWaveSeq1, 1, drv2605RegWaveSeq2, 2, @@ -87,7 +87,7 @@ func TestDRV2605LSequenceTermination(t *testing.T) { func TestDRV2605LSequenceTruncation(t *testing.T) { d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - assert.Nil(t, d.SetSequence([]byte{1, 2, 3, 4, 5, 6, 7, 8, 99, 100})) + assert.NoError(t, d.SetSequence([]byte{1, 2, 3, 4, 5, 6, 7, 8, 99, 100})) assert.Equal(t, []byte{ drv2605RegWaveSeq1, 1, drv2605RegWaveSeq2, 2, @@ -102,7 +102,7 @@ func TestDRV2605LSequenceTruncation(t *testing.T) { func TestDRV2605LSetMode(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - assert.Nil(t, d.SetMode(DRV2605ModeIntTrig)) + assert.NoError(t, d.SetMode(DRV2605ModeIntTrig)) } func TestDRV2605LSetModeReadError(t *testing.T) { @@ -115,7 +115,7 @@ func TestDRV2605LSetModeReadError(t *testing.T) { func TestDRV2605LSetStandbyMode(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - assert.Nil(t, d.SetStandbyMode(true)) + assert.NoError(t, d.SetStandbyMode(true)) } func TestDRV2605LSetStandbyModeReadError(t *testing.T) { @@ -128,10 +128,10 @@ func TestDRV2605LSetStandbyModeReadError(t *testing.T) { func TestDRV2605LSelectLibrary(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - assert.Nil(t, d.SelectLibrary(1)) + assert.NoError(t, d.SelectLibrary(1)) } func TestDRV2605LGo(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - assert.Nil(t, d.Go()) + assert.NoError(t, d.Go()) } diff --git a/drivers/i2c/grovepi_driver_test.go b/drivers/i2c/grovepi_driver_test.go index db6fd83e9..d50abc707 100644 --- a/drivers/i2c/grovepi_driver_test.go +++ b/drivers/i2c/grovepi_driver_test.go @@ -219,7 +219,7 @@ func TestGrovePiSomeWrite(t *testing.T) { return } // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantWritten, a.written) }) } diff --git a/drivers/i2c/hmc5883l_driver_test.go b/drivers/i2c/hmc5883l_driver_test.go index 890ccefe1..9af18c1c7 100644 --- a/drivers/i2c/hmc5883l_driver_test.go +++ b/drivers/i2c/hmc5883l_driver_test.go @@ -121,7 +121,7 @@ func TestHMC5883LRead(t *testing.T) { // act gotX, gotY, gotZ, err := d.Read() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantX, gotX) assert.Equal(t, tc.wantY, gotY) assert.Equal(t, tc.wantZ, gotZ) @@ -177,7 +177,7 @@ func TestHMC5883L_readRawData(t *testing.T) { // act gotX, gotY, gotZ, err := d.readRawData() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantX, gotX) assert.Equal(t, tc.wantY, gotY) assert.Equal(t, tc.wantZ, gotZ) @@ -203,7 +203,7 @@ func TestHMC5883L_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 6, len(a.written)) assert.Equal(t, uint8(hmc5883lRegA), a.written[0]) assert.Equal(t, wantRegA, a.written[1]) diff --git a/drivers/i2c/hmc6352_driver_test.go b/drivers/i2c/hmc6352_driver_test.go index c46af3bf2..7061a905a 100644 --- a/drivers/i2c/hmc6352_driver_test.go +++ b/drivers/i2c/hmc6352_driver_test.go @@ -42,12 +42,12 @@ func TestHMC6352Options(t *testing.T) { func TestHMC6352Start(t *testing.T) { d := NewHMC6352Driver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestHMC6352Halt(t *testing.T) { d, _ := initTestHMC6352DriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestHMC6352Heading(t *testing.T) { diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index cee0917f0..e4a610e95 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -75,7 +75,7 @@ func TestI2CAddress(t *testing.T) { func TestI2CClose(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) - assert.Nil(t, c.Close()) + assert.NoError(t, c.Close()) } func TestI2CRead(t *testing.T) { @@ -141,7 +141,7 @@ func TestI2CReadWordDataAddressError(t *testing.T) { func TestI2CWriteByte(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteByte(0x01) - assert.Nil(t, err) + assert.NoError(t, err) } func TestI2CWriteByteAddressError(t *testing.T) { @@ -153,7 +153,7 @@ func TestI2CWriteByteAddressError(t *testing.T) { func TestI2CWriteByteData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteByteData(0x01, 0x01) - assert.Nil(t, err) + assert.NoError(t, err) } func TestI2CWriteByteDataAddressError(t *testing.T) { @@ -165,7 +165,7 @@ func TestI2CWriteByteDataAddressError(t *testing.T) { func TestI2CWriteWordData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteWordData(0x01, 0x01) - assert.Nil(t, err) + assert.NoError(t, err) } func TestI2CWriteWordDataAddressError(t *testing.T) { @@ -177,7 +177,7 @@ func TestI2CWriteWordDataAddressError(t *testing.T) { func TestI2CWriteBlockData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteBlockData(0x01, []byte{0x01, 0x02}) - assert.Nil(t, err) + assert.NoError(t, err) } func TestI2CWriteBlockDataAddressError(t *testing.T) { diff --git a/drivers/i2c/i2c_driver_test.go b/drivers/i2c/i2c_driver_test.go index bdd115f6d..dd1addc2f 100644 --- a/drivers/i2c/i2c_driver_test.go +++ b/drivers/i2c/i2c_driver_test.go @@ -34,8 +34,8 @@ func TestNewDriver(t *testing.T) { assert.Equal(t, 0x15, d.defaultAddress) assert.Equal(t, a, d.connector) assert.Nil(t, d.connection) - assert.Nil(t, d.afterStart()) - assert.Nil(t, d.beforeHalt()) + assert.NoError(t, d.afterStart()) + assert.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Config) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) @@ -61,7 +61,7 @@ func TestStart(t *testing.T) { // arrange d, a := initDriverWithStubbedAdaptor() // act, assert - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) assert.Equal(t, a.address, 0x15) } @@ -77,7 +77,7 @@ func TestHalt(t *testing.T) { // arrange d := initTestDriver() // act, assert - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestWrite(t *testing.T) { @@ -98,7 +98,7 @@ func TestWrite(t *testing.T) { // act err := d.Write(address, value) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, wantAddress, a.written[0]) assert.Equal(t, uint8(value), a.written[1]) @@ -129,7 +129,7 @@ func TestRead(t *testing.T) { // act val, err := d.Read(address) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, int(want), val) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, wantAddress, a.written[0]) diff --git a/drivers/i2c/ina3221_driver_test.go b/drivers/i2c/ina3221_driver_test.go index 5987ccb8c..ae044fc9d 100644 --- a/drivers/i2c/ina3221_driver_test.go +++ b/drivers/i2c/ina3221_driver_test.go @@ -42,12 +42,12 @@ func TestINA3221Options(t *testing.T) { func TestINA3221Start(t *testing.T) { d := NewINA3221Driver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestINA3221Halt(t *testing.T) { d, _ := initTestINA3221DriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestINA3221GetBusVoltage(t *testing.T) { @@ -60,7 +60,7 @@ func TestINA3221GetBusVoltage(t *testing.T) { v, err := d.GetBusVoltage(INA3221Channel1) assert.Equal(t, float64(13.928), v) - assert.Nil(t, err) + assert.NoError(t, err) } func TestINA3221GetBusVoltageReadError(t *testing.T) { @@ -83,7 +83,7 @@ func TestINA3221GetShuntVoltage(t *testing.T) { v, err := d.GetShuntVoltage(INA3221Channel1) assert.Equal(t, float64(7.48), v) - assert.Nil(t, err) + assert.NoError(t, err) } func TestINA3221GetShuntVoltageReadError(t *testing.T) { @@ -106,7 +106,7 @@ func TestINA3221GetCurrent(t *testing.T) { v, err := d.GetCurrent(INA3221Channel1) assert.Equal(t, float64(74.8), v) - assert.Nil(t, err) + assert.NoError(t, err) } func TestINA3221CurrentReadError(t *testing.T) { @@ -131,7 +131,7 @@ func TestINA3221GetLoadVoltage(t *testing.T) { v, err := d.GetLoadVoltage(INA3221Channel2) assert.Equal(t, float64(13.935480), v) - assert.Nil(t, err) + assert.NoError(t, err) } func TestINA3221GetLoadVoltageReadError(t *testing.T) { diff --git a/drivers/i2c/jhd1313m1_driver_test.go b/drivers/i2c/jhd1313m1_driver_test.go index 12531d03c..f89efadbc 100644 --- a/drivers/i2c/jhd1313m1_driver_test.go +++ b/drivers/i2c/jhd1313m1_driver_test.go @@ -54,7 +54,7 @@ func TestJHD1313MDriverOptions(t *testing.T) { func TestJHD1313MDriverStart(t *testing.T) { d := initTestJHD1313M1Driver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestJHD1313MStartConnectError(t *testing.T) { @@ -74,13 +74,13 @@ func TestJHD1313MDriverStartWriteError(t *testing.T) { func TestJHD1313MDriverHalt(t *testing.T) { d := initTestJHD1313M1Driver() _ = d.Start() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestJHD1313MDriverSetRgb(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.SetRGB(0x00, 0x00, 0x00)) + assert.NoError(t, d.SetRGB(0x00, 0x00, 0x00)) } func TestJHD1313MDriverSetRgbError(t *testing.T) { @@ -96,7 +96,7 @@ func TestJHD1313MDriverSetRgbError(t *testing.T) { func TestJHD1313MDriverClear(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Clear()) + assert.NoError(t, d.Clear()) } func TestJHD1313MDriverClearError(t *testing.T) { @@ -112,13 +112,13 @@ func TestJHD1313MDriverClearError(t *testing.T) { func TestJHD1313MDriverHome(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Home()) + assert.NoError(t, d.Home()) } func TestJHD1313MDriverWrite(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Write("Hello")) + assert.NoError(t, d.Write("Hello")) } func TestJHD1313MDriverWriteError(t *testing.T) { @@ -134,7 +134,7 @@ func TestJHD1313MDriverWriteError(t *testing.T) { func TestJHD1313MDriverWriteTwoLines(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Write("Hello\nthere")) + assert.NoError(t, d.Write("Hello\nthere")) } func TestJHD1313MDriverWriteTwoLinesError(t *testing.T) { @@ -150,13 +150,13 @@ func TestJHD1313MDriverWriteTwoLinesError(t *testing.T) { func TestJHD1313MDriverSetPosition(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.SetPosition(2)) + assert.NoError(t, d.SetPosition(2)) } func TestJHD1313MDriverSetSecondLinePosition(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.SetPosition(18)) + assert.NoError(t, d.SetPosition(18)) } func TestJHD1313MDriverSetPositionInvalid(t *testing.T) { @@ -169,20 +169,20 @@ func TestJHD1313MDriverSetPositionInvalid(t *testing.T) { func TestJHD1313MDriverScroll(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Scroll(true)) + assert.NoError(t, d.Scroll(true)) } func TestJHD1313MDriverReverseScroll(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.Nil(t, d.Scroll(false)) + assert.NoError(t, d.Scroll(false)) } func TestJHD1313MDriverSetCustomChar(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} _ = d.Start() - assert.Nil(t, d.SetCustomChar(0, data)) + assert.NoError(t, d.SetCustomChar(0, data)) } func TestJHD1313MDriverSetCustomCharError(t *testing.T) { diff --git a/drivers/i2c/l3gd20h_driver_test.go b/drivers/i2c/l3gd20h_driver_test.go index e6a9402d4..9e1bf43f8 100644 --- a/drivers/i2c/l3gd20h_driver_test.go +++ b/drivers/i2c/l3gd20h_driver_test.go @@ -130,7 +130,7 @@ func TestL3GD20HFullScaleRange(t *testing.T) { // act got, err := d.FullScaleRange() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(0x23), a.written[0]) assert.Equal(t, readValue, got) @@ -196,7 +196,7 @@ func TestL3GD20HMeasurement(t *testing.T) { // act x, y, z, err := d.XYZ() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(0xA8), a.written[0]) assert.Equal(t, tc.wantX, x) diff --git a/drivers/i2c/lidarlite_driver_test.go b/drivers/i2c/lidarlite_driver_test.go index 9d61eb147..ecae4a6ab 100644 --- a/drivers/i2c/lidarlite_driver_test.go +++ b/drivers/i2c/lidarlite_driver_test.go @@ -48,12 +48,12 @@ func TestLIDARLiteDriverOptions(t *testing.T) { func TestLIDARLiteDriverStart(t *testing.T) { d := NewLIDARLiteDriver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestLIDARLiteDriverHalt(t *testing.T) { d := initTestLIDARLiteDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestLIDARLiteDriverDistance(t *testing.T) { @@ -72,7 +72,7 @@ func TestLIDARLiteDriverDistance(t *testing.T) { distance, err := d.Distance() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, int(25345), distance) // when insufficient bytes have been read diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index 961669fa3..f05139c6a 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -147,7 +147,7 @@ func TestMCP23017WriteGPIO(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 6, len(a.written)) assert.Equal(t, wantReg1, a.written[0]) assert.Equal(t, wantReg1, a.written[1]) @@ -186,7 +186,7 @@ func TestMCP23017WriteGPIONoRefresh(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(a.written)) assert.Equal(t, wantReg1, a.written[0]) assert.Equal(t, wantReg2, a.written[1]) @@ -223,7 +223,7 @@ func TestMCP23017WriteGPIONoAutoDir(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 3, len(a.written)) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantReg, a.written[1]) @@ -290,7 +290,7 @@ func TestMCP23017ReadGPIO(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, numCallsRead) assert.Equal(t, 4, len(a.written)) assert.Equal(t, wantReg1, a.written[0]) @@ -328,7 +328,7 @@ func TestMCP23017ReadGPIONoRefresh(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, numCallsRead) assert.Equal(t, 2, len(a.written)) assert.Equal(t, wantReg1, a.written[0]) @@ -363,7 +363,7 @@ func TestMCP23017ReadGPIONoAutoDir(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 1, len(a.written)) assert.Equal(t, wantReg2, a.written[0]) @@ -413,7 +413,7 @@ func TestMCP23017SetPinMode(t *testing.T) { // act err := d.SetPinMode(testPin, testPort, uint8(bitState)) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 3, len(a.written)) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantReg, a.written[1]) @@ -463,7 +463,7 @@ func TestMCP23017SetPullUp(t *testing.T) { // act err := d.SetPullUp(testPin, testPort, uint8(bitState)) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 3, len(a.written)) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantReg, a.written[1]) @@ -513,7 +513,7 @@ func TestMCP23017SetGPIOPolarity(t *testing.T) { // act err := d.SetGPIOPolarity(testPin, testPort, uint8(bitState)) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 3, len(a.written)) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantReg, a.written[1]) @@ -539,13 +539,13 @@ func TestMCP23017_write(t *testing.T) { d, _ := initTestMCP23017WithStubbedAdaptor(0) port := d.getPort("A") err := d.write(port.IODIR, uint8(7), 0) - assert.Nil(t, err) + assert.NoError(t, err) // set bit d, _ = initTestMCP23017WithStubbedAdaptor(0) port = d.getPort("B") err = d.write(port.IODIR, uint8(7), 1) - assert.Nil(t, err) + assert.NoError(t, err) // write error d, a := initTestMCP23017WithStubbedAdaptor(0) @@ -566,7 +566,7 @@ func TestMCP23017_write(t *testing.T) { return len(b), nil } err = d.write(port.IODIR, uint8(7), 1) - assert.Nil(t, err) + assert.NoError(t, err) } func TestMCP23017_read(t *testing.T) { diff --git a/drivers/i2c/mma7660_driver_test.go b/drivers/i2c/mma7660_driver_test.go index 2824e13b3..9f6e4b537 100644 --- a/drivers/i2c/mma7660_driver_test.go +++ b/drivers/i2c/mma7660_driver_test.go @@ -43,12 +43,12 @@ func TestMMA7660Options(t *testing.T) { func TestMMA7660Start(t *testing.T) { d := NewMMA7660Driver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestMMA7660Halt(t *testing.T) { d, _ := initTestMMA7660DriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestMMA7660Acceleration(t *testing.T) { diff --git a/drivers/i2c/mpl115a2_driver_test.go b/drivers/i2c/mpl115a2_driver_test.go index 27ef1c9b3..1b885a61d 100644 --- a/drivers/i2c/mpl115a2_driver_test.go +++ b/drivers/i2c/mpl115a2_driver_test.go @@ -78,8 +78,8 @@ func TestMPL115A2ReadData(t *testing.T) { press, errP := d.Pressure() temp, errT := d.Temperature() // assert - assert.Nil(t, errP) - assert.Nil(t, errT) + assert.NoError(t, errP) + assert.NoError(t, errT) assert.Equal(t, 2, readCallCounter) assert.Equal(t, 6, len(a.written)) assert.Equal(t, uint8(0x12), a.written[0]) @@ -124,7 +124,7 @@ func TestMPL115A2_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, readCallCounter) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(0x04), a.written[0]) diff --git a/drivers/i2c/mpu6050_driver_test.go b/drivers/i2c/mpu6050_driver_test.go index 1663658eb..4281dce64 100644 --- a/drivers/i2c/mpu6050_driver_test.go +++ b/drivers/i2c/mpu6050_driver_test.go @@ -172,7 +172,7 @@ func TestMPU6050_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, readCallCounter) assert.Equal(t, 13, len(a.written)) assert.Equal(t, uint8(0x6B), a.written[0]) diff --git a/drivers/i2c/pca9501_driver_test.go b/drivers/i2c/pca9501_driver_test.go index 30e34315b..284600d91 100644 --- a/drivers/i2c/pca9501_driver_test.go +++ b/drivers/i2c/pca9501_driver_test.go @@ -160,7 +160,7 @@ func TestPCA9501WriteGPIO(t *testing.T) { // act err := d.WriteGPIO(tc.pin, tc.setVal) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, numCallsRead) assert.Equal(t, 2, len(a.written)) assert.Equal(t, tc.wantPin, a.written[0]) @@ -254,7 +254,7 @@ func TestPCA9501ReadGPIO(t *testing.T) { // act got, err := d.ReadGPIO(pin) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.want, got) assert.Equal(t, 2, numCallsRead) assert.Equal(t, 1, len(a.written)) @@ -334,7 +334,7 @@ func TestPCA9501WriteEEPROM(t *testing.T) { // act err := d.WriteEEPROM(addressEEPROM, want) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, addressEEPROM, a.written[0]) assert.Equal(t, want, a.written[1]) @@ -363,7 +363,7 @@ func TestPCA9501ReadEEPROM(t *testing.T) { // act val, err := d.ReadEEPROM(addressEEPROM) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, want, val) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, addressEEPROM, a.written[0]) @@ -419,6 +419,6 @@ func TestPCA9501_initialize(t *testing.T) { // act err := d.initialize() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, want, a.address) } diff --git a/drivers/i2c/pca953x_driver_test.go b/drivers/i2c/pca953x_driver_test.go index ab35b8e2f..8aac72dd0 100644 --- a/drivers/i2c/pca953x_driver_test.go +++ b/drivers/i2c/pca953x_driver_test.go @@ -200,7 +200,7 @@ func TestPCA953xWritePeriod(t *testing.T) { // act err := d.WritePeriod(tc.idx, tc.val) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -291,7 +291,7 @@ func TestPCA953xWriteFrequency(t *testing.T) { // act err := d.WriteFrequency(tc.idx, tc.val) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -382,7 +382,7 @@ func TestPCA953xWriteDutyCyclePercent(t *testing.T) { // act err := d.WriteDutyCyclePercent(tc.idx, tc.val) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -465,7 +465,7 @@ func TestPCA953x_readRegister(t *testing.T) { // act val, err := d.readRegister(wantRegAddress) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, wantRegVal, val) @@ -491,7 +491,7 @@ func TestPCA953x_writeRegister(t *testing.T) { // act err := d.writeRegister(wantRegAddress, wantRegVal) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, wantByteCount, len(a.written)) diff --git a/drivers/i2c/pca9685_driver_test.go b/drivers/i2c/pca9685_driver_test.go index 73a3bed89..d4c81c34f 100644 --- a/drivers/i2c/pca9685_driver_test.go +++ b/drivers/i2c/pca9685_driver_test.go @@ -54,7 +54,7 @@ func TestPCA9685Start(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestPCA9685Halt(t *testing.T) { @@ -63,8 +63,8 @@ func TestPCA9685Halt(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestPCA9685SetPWM(t *testing.T) { @@ -73,8 +73,8 @@ func TestPCA9685SetPWM(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - assert.Nil(t, d.Start()) - assert.Nil(t, d.SetPWM(0, 0, 256)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.SetPWM(0, 0, 256)) } func TestPCA9685SetPWMError(t *testing.T) { @@ -83,7 +83,7 @@ func TestPCA9685SetPWMError(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } @@ -96,13 +96,13 @@ func TestPCA9685SetPWMFreq(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) a.i2cReadImpl = func(b []byte) (int, error) { copy(b, []byte{0x01}) return 1, nil } - assert.Nil(t, d.SetPWMFreq(60)) + assert.NoError(t, d.SetPWMFreq(60)) } func TestPCA9685SetPWMFreqReadError(t *testing.T) { @@ -111,7 +111,7 @@ func TestPCA9685SetPWMFreqReadError(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") @@ -125,7 +125,7 @@ func TestPCA9685SetPWMFreqWriteError(t *testing.T) { copy(b, []byte{0x01}) return 1, nil } - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") diff --git a/drivers/i2c/pcf8583_driver_test.go b/drivers/i2c/pcf8583_driver_test.go index a2a4a93ea..e37c26753 100644 --- a/drivers/i2c/pcf8583_driver_test.go +++ b/drivers/i2c/pcf8583_driver_test.go @@ -210,7 +210,7 @@ func TestPCF8583WriteTime(t *testing.T) { // act err := d.WriteTime(initDate) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, initDate.Year(), d.yearOffset) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 11, len(a.written)) @@ -292,7 +292,7 @@ func TestPCF8583ReadTime(t *testing.T) { // act got, err := d.ReadTime() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 2, numCallsRead) @@ -357,7 +357,7 @@ func TestPCF8583WriteCounter(t *testing.T) { // act err := d.WriteCounter(initCount) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 8, len(a.written)) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) @@ -430,7 +430,7 @@ func TestPCF8583ReadCounter(t *testing.T) { // act got, err := d.ReadCounter() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 2, numCallsRead) @@ -480,7 +480,7 @@ func TestPCF8583WriteRam(t *testing.T) { // act err := d.WriteRAM(wantRAMAddress-pcf8583RamOffset, wantRAMValue) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(a.written)) assert.Equal(t, wantRAMAddress, a.written[0]) assert.Equal(t, wantRAMValue, a.written[1]) @@ -521,7 +521,7 @@ func TestPCF8583ReadRam(t *testing.T) { // act got, err := d.ReadRAM(wantRAMAddress - pcf8583RamOffset) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, 1, len(a.written)) assert.Equal(t, wantRAMAddress, a.written[0]) @@ -572,7 +572,7 @@ func TestPCF8583_initializeNoModeSwitch(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) @@ -604,7 +604,7 @@ func TestPCF8583_initializeWithModeSwitch(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 3, len(a.written)) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) diff --git a/drivers/i2c/pcf8591_driver_test.go b/drivers/i2c/pcf8591_driver_test.go index b12032ec3..299d49f2c 100644 --- a/drivers/i2c/pcf8591_driver_test.go +++ b/drivers/i2c/pcf8591_driver_test.go @@ -35,12 +35,12 @@ func TestNewPCF8591Driver(t *testing.T) { func TestPCF8591Start(t *testing.T) { d := NewPCF8591Driver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestPCF8591Halt(t *testing.T) { d := NewPCF8591Driver(newI2cTestAdaptor()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestPCF8591WithPCF8591With400kbitStabilization(t *testing.T) { @@ -78,7 +78,7 @@ func TestPCF8591AnalogReadSingle(t *testing.T) { // act got, err := d.AnalogRead(description) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, ctrlByteOn, a.written[0]) assert.Equal(t, 2, numCallsRead) @@ -120,7 +120,7 @@ func TestPCF8591AnalogReadDiff(t *testing.T) { // act got, err := d.AnalogRead(description) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, ctrlByteOn, a.written[0]) assert.Equal(t, 2, numCallsRead) @@ -146,7 +146,7 @@ func TestPCF8591AnalogWrite(t *testing.T) { // act err := d.AnalogWrite("", int(want)) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(a.written)) assert.Equal(t, ctrlByteOn, a.written[0]) assert.Equal(t, want, a.written[1]) @@ -171,7 +171,7 @@ func TestPCF8591AnalogOutputState(t *testing.T) { // act err := d.AnalogOutputState(bitState == 1) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, wantCtrlByteVal, a.written[0]) } diff --git a/drivers/i2c/sht2x_driver_test.go b/drivers/i2c/sht2x_driver_test.go index 3640a18be..a71509b0e 100644 --- a/drivers/i2c/sht2x_driver_test.go +++ b/drivers/i2c/sht2x_driver_test.go @@ -42,12 +42,12 @@ func TestSHT2xOptions(t *testing.T) { func TestSHT2xStart(t *testing.T) { d := NewSHT2xDriver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestSHT2xHalt(t *testing.T) { d, _ := initTestSHT2xDriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestSHT2xReset(t *testing.T) { @@ -57,7 +57,7 @@ func TestSHT2xReset(t *testing.T) { } _ = d.Start() err := d.Reset() - assert.Nil(t, err) + assert.NoError(t, err) } func TestSHT2xMeasurements(t *testing.T) { @@ -75,10 +75,10 @@ func TestSHT2xMeasurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(18.809052), temp) hum, err := d.Humidity() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(40.279907), hum) } @@ -100,7 +100,7 @@ func TestSHT2xAccuracy(t *testing.T) { _ = d.SetAccuracy(SHT2xAccuracyLow) assert.Equal(t, SHT2xAccuracyLow, d.Accuracy()) err := d.sendAccuracy() - assert.Nil(t, err) + assert.NoError(t, err) } func TestSHT2xTemperatureCrcError(t *testing.T) { diff --git a/drivers/i2c/sht3x_driver_test.go b/drivers/i2c/sht3x_driver_test.go index 15a0e64bd..29144a957 100644 --- a/drivers/i2c/sht3x_driver_test.go +++ b/drivers/i2c/sht3x_driver_test.go @@ -42,12 +42,12 @@ func TestSHT3xOptions(t *testing.T) { func TestSHT3xStart(t *testing.T) { d := NewSHT3xDriver(newI2cTestAdaptor()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestSHT3xHalt(t *testing.T) { d, _ := initTestSHT3xDriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestSHT3xSampleNormal(t *testing.T) { @@ -155,7 +155,7 @@ func TestSHT3xHeater(t *testing.T) { } status, err := d.Heater() - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, status) // heater disabled @@ -165,7 +165,7 @@ func TestSHT3xHeater(t *testing.T) { } status, err = d.Heater() - assert.Nil(t, err) + assert.NoError(t, err) assert.False(t, status) // heater crc failed @@ -199,11 +199,11 @@ func TestSHT3xSetAccuracy(t *testing.T) { assert.Equal(t, byte(SHT3xAccuracyHigh), d.Accuracy()) err := d.SetAccuracy(SHT3xAccuracyMedium) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, byte(SHT3xAccuracyMedium), d.Accuracy()) err = d.SetAccuracy(SHT3xAccuracyLow) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, byte(SHT3xAccuracyLow), d.Accuracy()) err = d.SetAccuracy(0xff) @@ -219,6 +219,6 @@ func TestSHT3xSerialNumber(t *testing.T) { sn, err := d.SerialNumber() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uint32(0x2000beef), sn) } diff --git a/drivers/i2c/ssd1306_driver_test.go b/drivers/i2c/ssd1306_driver_test.go index 53cce321e..c5869bff8 100644 --- a/drivers/i2c/ssd1306_driver_test.go +++ b/drivers/i2c/ssd1306_driver_test.go @@ -47,7 +47,7 @@ func TestSSD1306StartDefault(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestSSD1306Start128x32(t *testing.T) { @@ -58,7 +58,7 @@ func TestSSD1306Start128x32(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestSSD1306Start96x16(t *testing.T) { @@ -69,7 +69,7 @@ func TestSSD1306Start96x16(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestSSD1306StartExternalVCC(t *testing.T) { @@ -80,7 +80,7 @@ func TestSSD1306StartExternalVCC(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestSSD1306StartSizeError(t *testing.T) { @@ -96,7 +96,7 @@ func TestSSD1306StartSizeError(t *testing.T) { func TestSSD1306Halt(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) - assert.Nil(t, s.Halt()) + assert.NoError(t, s.Halt()) } func TestSSD1306Options(t *testing.T) { @@ -109,7 +109,7 @@ func TestSSD1306Options(t *testing.T) { func TestSSD1306Display(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(96, 16, false) _ = s.Start() - assert.Nil(t, s.Display()) + assert.NoError(t, s.Display()) } func TestSSD1306ShowImage(t *testing.T) { @@ -119,7 +119,7 @@ func TestSSD1306ShowImage(t *testing.T) { assert.ErrorContains(t, s.ShowImage(img), "image must match display width and height: 128x64") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) - assert.Nil(t, s.ShowImage(img)) + assert.NoError(t, s.ShowImage(img)) } func TestSSD1306Command(t *testing.T) { @@ -135,7 +135,7 @@ func TestSSD1306Command(t *testing.T) { return 0, nil } err := s.command(0xFF) - assert.Nil(t, err) + assert.NoError(t, err) } func TestSSD1306Commands(t *testing.T) { @@ -151,7 +151,7 @@ func TestSSD1306Commands(t *testing.T) { return 0, nil } err := s.commands([]byte{0x00, 0xFF}) - assert.Nil(t, err) + assert.NoError(t, err) } func TestSSD1306On(t *testing.T) { @@ -167,7 +167,7 @@ func TestSSD1306On(t *testing.T) { return 0, nil } err := s.On() - assert.Nil(t, err) + assert.NoError(t, err) } func TestSSD1306Off(t *testing.T) { @@ -183,7 +183,7 @@ func TestSSD1306Off(t *testing.T) { return 0, nil } err := s.Off() - assert.Nil(t, err) + assert.NoError(t, err) } func TestSSD1306Reset(t *testing.T) { @@ -200,7 +200,7 @@ func TestSSD1306Reset(t *testing.T) { return 0, nil } err := s.Reset() - assert.Nil(t, err) + assert.NoError(t, err) } // COMMANDS diff --git a/drivers/i2c/th02_driver_test.go b/drivers/i2c/th02_driver_test.go index 44501e82e..26e9b3ce5 100644 --- a/drivers/i2c/th02_driver_test.go +++ b/drivers/i2c/th02_driver_test.go @@ -102,7 +102,7 @@ func TestTH02FastMode(t *testing.T) { // act got, err := d.FastMode() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(0x03), a.written[0]) assert.Equal(t, tc.want, got) @@ -130,7 +130,7 @@ func TestTH02SetHeater(t *testing.T) { // act err := d.SetHeater(tc.heater) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.heater, d.heating) assert.Equal(t, 2, len(a.written)) assert.Equal(t, uint8(0x03), a.written[0]) @@ -162,7 +162,7 @@ func TestTH02Heater(t *testing.T) { // act got, err := d.Heater() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(0x03), a.written[0]) assert.Equal(t, tc.want, got) @@ -186,7 +186,7 @@ func TestTH02SerialNumber(t *testing.T) { // act sn, err := d.SerialNumber() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.written)) assert.Equal(t, uint8(0x11), a.written[0]) assert.Equal(t, want, sn) @@ -297,7 +297,7 @@ func TestTH02Sample(t *testing.T) { // act temp, rh, err := d.Sample() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, tc.wantRH, rh) assert.Equal(t, tc.wantT, temp) }) diff --git a/drivers/i2c/tsl2561_driver_test.go b/drivers/i2c/tsl2561_driver_test.go index bd6342e6d..3609721a0 100644 --- a/drivers/i2c/tsl2561_driver_test.go +++ b/drivers/i2c/tsl2561_driver_test.go @@ -60,7 +60,7 @@ func TestTSL2561DriverStart(t *testing.T) { d := NewTSL2561Driver(a) a.i2cReadImpl = testIDReader - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestTSL2561DriverStartNotFound(t *testing.T) { @@ -77,7 +77,7 @@ func TestTSL2561DriverStartNotFound(t *testing.T) { func TestTSL2561DriverHalt(t *testing.T) { d, _ := initTestTSL2561Driver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestTSL2561DriverRead16(t *testing.T) { @@ -93,7 +93,7 @@ func TestTSL2561DriverRead16(t *testing.T) { return buf.Len(), nil } val, err := d.connection.ReadWordData(1) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uint16(0xAEEA), val) } @@ -180,7 +180,7 @@ func TestTSL2561DriverGetLuminocity(t *testing.T) { return buf.Len(), nil } bb, ir, err := d.GetLuminocity() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uint16(12365), bb) assert.Equal(t, uint16(12365), ir) assert.Equal(t, uint32(72), d.CalculateLux(bb, ir)) @@ -202,7 +202,7 @@ func TestTSL2561DriverGetLuminocityAutoGain(t *testing.T) { _ = d.Start() bb, ir, err := d.GetLuminocity() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uint16(12365), bb) assert.Equal(t, uint16(12365), ir) assert.Equal(t, uint32(72), d.CalculateLux(bb, ir)) diff --git a/drivers/i2c/wiichuck_driver_test.go b/drivers/i2c/wiichuck_driver_test.go index 161dcd9d9..94858de3b 100644 --- a/drivers/i2c/wiichuck_driver_test.go +++ b/drivers/i2c/wiichuck_driver_test.go @@ -44,7 +44,7 @@ func TestWiichuckDriverStart(t *testing.T) { d.interval = 1 * time.Millisecond sem := make(chan bool) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) go func() { for { @@ -67,7 +67,7 @@ func TestWiichuckDriverStart(t *testing.T) { func TestWiichuckDriverHalt(t *testing.T) { d := initTestWiichuckDriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestWiichuckDriverCanParse(t *testing.T) { diff --git a/drivers/i2c/yl40_driver_test.go b/drivers/i2c/yl40_driver_test.go index a3e604403..33678172b 100644 --- a/drivers/i2c/yl40_driver_test.go +++ b/drivers/i2c/yl40_driver_test.go @@ -107,12 +107,12 @@ func TestYL40DriverReadBrightness(t *testing.T) { got, err := yl.ReadBrightness() got2, err2 := yl.Brightness() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(adaptor.written)) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, 2, numCallsRead) assert.Equal(t, want, got) - assert.Nil(t, err2) + assert.NoError(t, err2) assert.Equal(t, want, got2) } @@ -143,12 +143,12 @@ func TestYL40DriverReadTemperature(t *testing.T) { got, err := yl.ReadTemperature() got2, err2 := yl.Temperature() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(adaptor.written)) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, 2, numCallsRead) assert.Equal(t, want, got) - assert.Nil(t, err2) + assert.NoError(t, err2) assert.Equal(t, want, got2) } @@ -178,12 +178,12 @@ func TestYL40DriverReadAIN2(t *testing.T) { got, err := yl.ReadAIN2() got2, err2 := yl.AIN2() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(adaptor.written)) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, 2, numCallsRead) assert.Equal(t, want, got) - assert.Nil(t, err2) + assert.NoError(t, err2) assert.Equal(t, want, got2) } @@ -213,12 +213,12 @@ func TestYL40DriverReadPotentiometer(t *testing.T) { got, err := yl.ReadPotentiometer() got2, err2 := yl.Potentiometer() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(adaptor.written)) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, 2, numCallsRead) assert.Equal(t, want, got) - assert.Nil(t, err2) + assert.NoError(t, err2) assert.Equal(t, want, got2) } @@ -238,7 +238,7 @@ func TestYL40DriverAnalogWrite(t *testing.T) { // act err := pcf.Write(write) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(adaptor.written)) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, want, adaptor.written[1]) @@ -246,12 +246,12 @@ func TestYL40DriverAnalogWrite(t *testing.T) { func TestYL40DriverStart(t *testing.T) { yl := NewYL40Driver(newI2cTestAdaptor()) - assert.Nil(t, yl.Start()) + assert.NoError(t, yl.Start()) } func TestYL40DriverHalt(t *testing.T) { yl := NewYL40Driver(newI2cTestAdaptor()) - assert.Nil(t, yl.Halt()) + assert.NoError(t, yl.Halt()) } func fEqual(want interface{}, got interface{}) bool { diff --git a/drivers/spi/apa102_test.go b/drivers/spi/apa102_test.go index d1f010071..a0a562eba 100644 --- a/drivers/spi/apa102_test.go +++ b/drivers/spi/apa102_test.go @@ -40,5 +40,5 @@ func TestDriverLEDs(t *testing.T) { d.SetRGBA(2, color.RGBA{255, 255, 255, 15}) d.SetRGBA(3, color.RGBA{255, 255, 255, 15}) - assert.Nil(t, d.Draw()) + assert.NoError(t, d.Draw()) } diff --git a/drivers/spi/mfrc522_driver_test.go b/drivers/spi/mfrc522_driver_test.go index cae3160b5..f8acb88aa 100644 --- a/drivers/spi/mfrc522_driver_test.go +++ b/drivers/spi/mfrc522_driver_test.go @@ -39,6 +39,6 @@ func TestMFRC522WriteByteData(t *testing.T) { // act err := d.connection.WriteByteData(0x00, 0x00) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, []byte{0x00, 0x00}, a.spi.Written()) } diff --git a/drivers/spi/spi_connection_test.go b/drivers/spi/spi_connection_test.go index 1db431293..9291a6892 100644 --- a/drivers/spi/spi_connection_test.go +++ b/drivers/spi/spi_connection_test.go @@ -38,7 +38,7 @@ func TestReadCommandData(t *testing.T) { got := []byte{0x01, 0x02} err := c.ReadCommandData(command, got) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, command, sysdev.Written()) assert.Equal(t, want, got) } @@ -54,7 +54,7 @@ func TestReadByteData(t *testing.T) { // act got, err := c.ReadByteData(reg) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, []byte{reg, 0x00}, sysdev.Written()) // for read register we need n+1 bytes assert.Equal(t, want, got) } @@ -71,7 +71,7 @@ func TestReadBlockData(t *testing.T) { got := make([]byte, 4) err := c.ReadBlockData(reg, got) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, []byte{reg, 0x00, 0x00, 0x00, 0x00}, sysdev.Written()) // for read registers we need n+1 bytes assert.Equal(t, want, got) } @@ -83,7 +83,7 @@ func TestWriteByte(t *testing.T) { // act err := c.WriteByte(want) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, []byte{want}, sysdev.Written()) } @@ -97,7 +97,7 @@ func TestWriteByteData(t *testing.T) { // act err := c.WriteByteData(reg, val) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, []byte{reg, val}, sysdev.Written()) } @@ -109,7 +109,7 @@ func TestWriteBlockData(t *testing.T) { // act err := c.WriteBlockData(reg, data) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, append([]byte{reg}, data...), sysdev.Written()) } @@ -120,6 +120,6 @@ func TestWriteBytes(t *testing.T) { // act err := c.WriteBytes(want) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, want, sysdev.Written()) } diff --git a/drivers/spi/spi_driver_test.go b/drivers/spi/spi_driver_test.go index a91fefcf5..6e4257f60 100644 --- a/drivers/spi/spi_driver_test.go +++ b/drivers/spi/spi_driver_test.go @@ -30,12 +30,12 @@ func TestNewDriver(t *testing.T) { func TestStart(t *testing.T) { d := NewDriver(newSpiTestAdaptor(), "SPI_BASIC") - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestHalt(t *testing.T) { d, _ := initTestDriverWithStubbedAdaptor() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestSetName(t *testing.T) { diff --git a/drivers/spi/ssd1306_driver_test.go b/drivers/spi/ssd1306_driver_test.go index 79f010a59..d896f8957 100644 --- a/drivers/spi/ssd1306_driver_test.go +++ b/drivers/spi/ssd1306_driver_test.go @@ -19,19 +19,19 @@ func initTestSSDDriver() *SSD1306Driver { func TestDriverSSDStart(t *testing.T) { d := initTestSSDDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestDriverSSDHalt(t *testing.T) { d := initTestSSDDriver() _ = d.Start() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestDriverSSDDisplay(t *testing.T) { d := initTestSSDDriver() _ = d.Start() - assert.Nil(t, d.Display()) + assert.NoError(t, d.Display()) } func TestSSD1306DriverShowImage(t *testing.T) { @@ -41,7 +41,7 @@ func TestSSD1306DriverShowImage(t *testing.T) { assert.ErrorContains(t, d.ShowImage(img), "Image must match the display width and height") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) - assert.Nil(t, d.ShowImage(img)) + assert.NoError(t, d.ShowImage(img)) } type gpioTestAdaptor struct { diff --git a/master_test.go b/master_test.go index 939adb569..e722a00e9 100644 --- a/master_test.go +++ b/master_test.go @@ -41,7 +41,7 @@ func TestNullReadWriteCloser(t *testing.T) { assert.Equal(t, 3, i) i, _ = n.Read(make([]byte, 10)) assert.Equal(t, 10, i) - assert.Nil(t, n.Close()) + assert.NoError(t, n.Close()) } func TestMasterRobot(t *testing.T) { @@ -69,8 +69,8 @@ func TestMasterToJSON(t *testing.T) { func TestMasterStart(t *testing.T) { g := initTestMaster() - assert.Nil(t, g.Start()) - assert.Nil(t, g.Stop()) + assert.NoError(t, g.Start()) + assert.NoError(t, g.Stop()) assert.False(t, g.Running()) } @@ -82,7 +82,7 @@ func TestMasterStartAutoRun(t *testing.T) { assert.True(t, g.Running()) // stop it - assert.Nil(t, g.Stop()) + assert.NoError(t, g.Stop()) assert.False(t, g.Running()) } @@ -99,7 +99,7 @@ func TestMasterStartDriverErrors(t *testing.T) { want = multierror.Append(want, e) assert.Equal(t, want, g.Start()) - assert.Nil(t, g.Stop()) + assert.NoError(t, g.Stop()) testDriverStart = func() (err error) { return } } @@ -138,7 +138,7 @@ func TestMasterStartRobotAdaptorErrors(t *testing.T) { } assert.Equal(t, want, g.Start()) - assert.Nil(t, g.Stop()) + assert.NoError(t, g.Stop()) testAdaptorConnect = func() (err error) { return } } diff --git a/platforms/adaptors/digitalpinsadaptor_test.go b/platforms/adaptors/digitalpinsadaptor_test.go index 01b911c18..aa61e9454 100644 --- a/platforms/adaptors/digitalpinsadaptor_test.go +++ b/platforms/adaptors/digitalpinsadaptor_test.go @@ -66,7 +66,7 @@ func TestDigitalPinsConnect(t *testing.T) { assert.ErrorContains(t, err, "not connected for pin 7") err = a.Connect() - assert.Nil(t, err) + assert.NoError(t, err) assert.NotEqual(t, (map[string]gobot.DigitalPinner)(nil), a.pins) assert.Equal(t, 0, len(a.pins)) } @@ -83,21 +83,21 @@ func TestDigitalPinsFinalize(t *testing.T) { fs := sys.UseMockFilesystem(mockedPaths) a := NewDigitalPinsAdaptor(sys, testDigitalPinTranslator) // assert that finalize before connect is working - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // arrange - assert.Nil(t, a.Connect()) - assert.Nil(t, a.DigitalWrite("3", 1)) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.DigitalWrite("3", 1)) assert.Equal(t, 1, len(a.pins)) // act err := a.Finalize() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, len(a.pins)) // assert that finalize after finalize is working - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // arrange missing sysfs file - assert.Nil(t, a.Connect()) - assert.Nil(t, a.DigitalWrite("3", 2)) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.DigitalWrite("3", 2)) delete(fs.Files, "/sys/class/gpio/unexport") err = a.Finalize() assert.Contains(t, err.Error(), "/sys/class/gpio/unexport: no such file") @@ -112,13 +112,13 @@ func TestDigitalPinsReConnect(t *testing.T) { "/sys/class/gpio/gpio15/value", } a, _ := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) - assert.Nil(t, a.DigitalWrite("4", 1)) + assert.NoError(t, a.DigitalWrite("4", 1)) assert.Equal(t, 1, len(a.pins)) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // act err := a.Connect() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, a.pins) assert.Equal(t, 0, len(a.pins)) } @@ -133,10 +133,10 @@ func TestDigitalIO(t *testing.T) { a, _ := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) err := a.DigitalWrite("14", 1) - assert.Nil(t, err) + assert.NoError(t, err) i, err := a.DigitalRead("14") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, i) } @@ -153,7 +153,7 @@ func TestDigitalRead(t *testing.T) { // assert read correct value without error i, err := a.DigitalRead("13") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, i) // assert error bubbling for read errors @@ -193,8 +193,8 @@ func TestDigitalReadWithGpiosActiveLow(t *testing.T) { got1, err1 := a.DigitalRead("14") // for a new pin got2, err2 := a.DigitalRead("15") // for an existing pin (calls ApplyOptions()) // assert - assert.Nil(t, err1) - assert.Nil(t, err2) + assert.NoError(t, err1) + assert.NoError(t, err2) assert.Equal(t, 1, got1) // there is no mechanism to negate mocked values assert.Equal(t, 0, got2) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio25/active_low"].Contents) @@ -216,7 +216,7 @@ func TestDigitalWrite(t *testing.T) { WithGpiosOpenDrain("7")(a) WithGpioEventOnFallingEdge("7", gpioEventHandler)(a) err := a.DigitalWrite("7", 1) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio18/value"].Contents) // assert second write to same pin without error and just ignore unsupported options @@ -225,7 +225,7 @@ func TestDigitalWrite(t *testing.T) { WithGpioDebounce("7", 2*time.Second)(a) WithGpioEventOnRisingEdge("7", gpioEventHandler)(a) err = a.DigitalWrite("7", 1) - assert.Nil(t, err) + assert.NoError(t, err) // assert error on bad id assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "not a valid pin") @@ -251,7 +251,7 @@ func TestDigitalWriteWithGpiosActiveLow(t *testing.T) { // act err := a.DigitalWrite("8", 2) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "2", fs.Files["/sys/class/gpio/gpio19/value"].Contents) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio19/active_low"].Contents) } diff --git a/platforms/adaptors/i2cbusadaptor_test.go b/platforms/adaptors/i2cbusadaptor_test.go index 05042fd3d..f514bdccb 100644 --- a/platforms/adaptors/i2cbusadaptor_test.go +++ b/platforms/adaptors/i2cbusadaptor_test.go @@ -36,18 +36,18 @@ func TestI2cWorkflow(t *testing.T) { assert.Equal(t, 0, len(a.buses)) con, err := a.GetI2cConnection(0xff, 1) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.buses)) _, err = con.Write([]byte{0x00, 0x01}) - assert.Nil(t, err) + assert.NoError(t, err) data := []byte{42, 42} _, err = con.Read(data) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, []byte{0x00, 0x01}, data) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) assert.Equal(t, 0, len(a.buses)) } @@ -56,7 +56,7 @@ func TestI2cGetI2cConnection(t *testing.T) { a, _ := initTestI2cAdaptorWithMockedFilesystem([]string{i2cBus1}) // assert working connection c1, e1 := a.GetI2cConnection(0xff, 1) - assert.Nil(t, e1) + assert.NoError(t, e1) assert.NotNil(t, c1) assert.Equal(t, 1, len(a.buses)) // assert invalid bus gets error @@ -65,7 +65,7 @@ func TestI2cGetI2cConnection(t *testing.T) { assert.Nil(t, c2) assert.Equal(t, 1, len(a.buses)) // assert unconnected gets error - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) c3, e3 := a.GetI2cConnection(0x01, 99) assert.ErrorContains(t, e3, "not connected") assert.Nil(t, c3) @@ -76,18 +76,18 @@ func TestI2cFinalize(t *testing.T) { // arrange a, fs := initTestI2cAdaptorWithMockedFilesystem([]string{i2cBus1}) // assert that finalize before connect is working - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // arrange - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) _, _ = a.GetI2cConnection(0xaf, 1) assert.Equal(t, 1, len(a.buses)) // assert that Finalize after GetI2cConnection is working and clean up - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) assert.Equal(t, 0, len(a.buses)) // assert that finalize after finalize is working - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // assert that close error is recognized - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, _ := a.GetI2cConnection(0xbf, 1) assert.Equal(t, 1, len(a.buses)) _, _ = con.Write([]byte{0xbf}) @@ -99,9 +99,9 @@ func TestI2cFinalize(t *testing.T) { func TestI2cReConnect(t *testing.T) { // arrange a, _ := initTestI2cAdaptorWithMockedFilesystem([]string{i2cBus1}) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // act - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) // assert assert.NotNil(t, a.buses) assert.Equal(t, 0, len(a.buses)) diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index c78223d66..15ff4bc23 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -120,7 +120,7 @@ func TestPWMPinsConnect(t *testing.T) { assert.ErrorContains(t, err, "not connected") err = a.Connect() - assert.Nil(t, err) + assert.NoError(t, err) assert.NotEqual(t, (map[string]gobot.PWMPinner)(nil), a.pins) assert.Equal(t, 0, len(a.pins)) } @@ -133,27 +133,27 @@ func TestPWMPinsFinalize(t *testing.T) { fs.Files[pwmPeriodPath].Contents = "0" fs.Files[pwmDutyCyclePath].Contents = "0" // assert that finalize before connect is working - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // arrange - assert.Nil(t, a.Connect()) - assert.Nil(t, a.PwmWrite("33", 1)) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.PwmWrite("33", 1)) assert.Equal(t, 1, len(a.pins)) // act err := a.Finalize() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, len(a.pins)) // assert that finalize after finalize is working - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // arrange missing sysfs file - assert.Nil(t, a.Connect()) - assert.Nil(t, a.PwmWrite("33", 2)) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.PwmWrite("33", 2)) delete(fs.Files, pwmUnexportPath) err = a.Finalize() assert.Contains(t, err.Error(), pwmUnexportPath+": no such file") // arrange write error - assert.Nil(t, a.Connect()) - assert.Nil(t, a.PwmWrite("33", 2)) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.PwmWrite("33", 2)) fs.WithWriteError = true err = a.Finalize() assert.Contains(t, err.Error(), "write error") @@ -162,13 +162,13 @@ func TestPWMPinsFinalize(t *testing.T) { func TestPWMPinsReConnect(t *testing.T) { // arrange a, _ := initTestPWMPinsAdaptorWithMockedFilesystem(pwmMockPaths) - assert.Nil(t, a.PwmWrite("33", 1)) + assert.NoError(t, a.PwmWrite("33", 1)) assert.Equal(t, 1, len(a.pins)) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // act err := a.Connect() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, a.pins) assert.Equal(t, 0, len(a.pins)) } @@ -177,7 +177,7 @@ func TestPwmWrite(t *testing.T) { a, fs := initTestPWMPinsAdaptorWithMockedFilesystem(pwmMockPaths) err := a.PwmWrite("33", 100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) @@ -207,10 +207,10 @@ func TestServoWrite(t *testing.T) { assert.Equal(t, fmt.Sprintf("%d", a.periodDefault), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) - assert.Nil(t, err) + assert.NoError(t, err) err = a.ServoWrite("33", 180) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("notexist", 42) @@ -233,7 +233,7 @@ func TestSetPeriod(t *testing.T) { // act err := a.SetPeriod("33", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) @@ -242,7 +242,7 @@ func TestSetPeriod(t *testing.T) { // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("33", 127) // 127 is a little bit smaller than 50% of period - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 1270000), fs.Files[pwmDutyCyclePath].Contents) newPeriod = newPeriod / 10 @@ -250,7 +250,7 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("33", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 127000), fs.Files[pwmDutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value @@ -260,7 +260,7 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("33", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 2540000), fs.Files[pwmDutyCyclePath].Contents) // act @@ -346,7 +346,7 @@ func Test_PWMPin(t *testing.T) { got, err := a.PWMPin(tc.pin) // assert if tc.wantErr == "" { - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, got) } else { if !strings.Contains(err.Error(), tc.wantErr) { diff --git a/platforms/adaptors/spibusadaptor_test.go b/platforms/adaptors/spibusadaptor_test.go index 80864de86..1b0f0d7d2 100644 --- a/platforms/adaptors/spibusadaptor_test.go +++ b/platforms/adaptors/spibusadaptor_test.go @@ -57,17 +57,17 @@ func TestGetSpiConnection(t *testing.T) { // act con1, err1 := a.GetSpiConnection(busNum, chipNum, mode, bits, maxSpeed) // assert - assert.Nil(t, err1) + assert.NoError(t, err1) assert.NotNil(t, con1) assert.Equal(t, 1, len(a.connections)) // assert cached connection con1a, err2 := a.GetSpiConnection(busNum, chipNum, mode, bits, maxSpeed) - assert.Nil(t, err2) + assert.NoError(t, err2) assert.Equal(t, con1, con1a) assert.Equal(t, 1, len(a.connections)) // assert second connection con2, err3 := a.GetSpiConnection(busNum, chipNum+1, mode, bits, maxSpeed) - assert.Nil(t, err3) + assert.NoError(t, err3) assert.NotNil(t, con2) assert.NotEqual(t, con1, con2) assert.Equal(t, 2, len(a.connections)) @@ -86,12 +86,12 @@ func TestSpiFinalize(t *testing.T) { // arrange a, _ := initTestSpiBusAdaptorWithMockedSpi() _, e := a.GetSpiConnection(spiTestAllowedBus, 2, 3, 4, 5) - assert.Nil(t, e) + assert.NoError(t, e) assert.Equal(t, 1, len(a.connections)) // act err := a.Finalize() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, len(a.connections)) } @@ -99,7 +99,7 @@ func TestSpiFinalizeWithError(t *testing.T) { // arrange a, spi := initTestSpiBusAdaptorWithMockedSpi() _, e := a.GetSpiConnection(spiTestAllowedBus, 2, 3, 4, 5) - assert.Nil(t, e) + assert.NoError(t, e) spi.SetCloseError(true) // act err := a.Finalize() @@ -110,9 +110,9 @@ func TestSpiFinalizeWithError(t *testing.T) { func TestSpiReConnect(t *testing.T) { // arrange a, _ := initTestSpiBusAdaptorWithMockedSpi() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // act - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) // assert assert.NotNil(t, a.connections) assert.Equal(t, 0, len(a.connections)) diff --git a/platforms/audio/audio_adaptor_test.go b/platforms/audio/audio_adaptor_test.go index 4e20511af..823cce510 100644 --- a/platforms/audio/audio_adaptor_test.go +++ b/platforms/audio/audio_adaptor_test.go @@ -16,8 +16,8 @@ var _ gobot.Adaptor = (*Adaptor)(nil) func TestAudioAdaptor(t *testing.T) { a := NewAdaptor() - assert.Nil(t, a.Connect()) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.Finalize()) } func TestAudioAdaptorName(t *testing.T) { diff --git a/platforms/audio/audio_driver_test.go b/platforms/audio/audio_driver_test.go index 89ef710f1..cf5de2195 100644 --- a/platforms/audio/audio_driver_test.go +++ b/platforms/audio/audio_driver_test.go @@ -20,9 +20,9 @@ func TestAudioDriver(t *testing.T) { assert.NotNil(t, d.Connection()) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestAudioDriverName(t *testing.T) { diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index b615c68dc..c7bf5a487 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -83,7 +83,7 @@ func TestPWM(t *testing.T) { fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents, ) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestAnalog(t *testing.T) { @@ -96,7 +96,7 @@ func TestAnalog(t *testing.T) { fs.Files["/sys/bus/iio/devices/iio:device0/in_voltage1_raw"].Contents = "567\n" i, err := a.AnalogRead("P9_40") assert.Equal(t, 567, i) - assert.Nil(t, err) + assert.NoError(t, err) _, err = a.AnalogRead("P9_99") assert.ErrorContains(t, err, "Not a valid analog pin") @@ -106,7 +106,7 @@ func TestAnalog(t *testing.T) { assert.ErrorContains(t, err, "read error") fs.WithReadError = false - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestDigitalIO(t *testing.T) { @@ -151,9 +151,9 @@ func TestDigitalIO(t *testing.T) { fs.Files["/sys/class/gpio/gpio66/value"].Contents = "1" i, err := a.DigitalRead("P8_07") assert.Equal(t, 1, i) - assert.Nil(t, err) + assert.NoError(t, err) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestName(t *testing.T) { @@ -202,7 +202,7 @@ func TestDigitalPinFinalizeFileError(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) err := a.DigitalWrite("P9_12", 1) - assert.Nil(t, err) + assert.NoError(t, err) err = a.Finalize() assert.Contains(t, err.Error(), "/sys/class/gpio/unexport: no such file") @@ -233,11 +233,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-2"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 2) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/ble/battery_driver_test.go b/platforms/ble/battery_driver_test.go index 4aac0c3b4..8280d8a1c 100644 --- a/platforms/ble/battery_driver_test.go +++ b/platforms/ble/battery_driver_test.go @@ -24,8 +24,8 @@ func TestBatteryDriver(t *testing.T) { func TestBatteryDriverStartAndHalt(t *testing.T) { d := initTestBatteryDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestBatteryDriverRead(t *testing.T) { diff --git a/platforms/ble/device_information_driver_test.go b/platforms/ble/device_information_driver_test.go index 79cc202f4..1a8234c51 100644 --- a/platforms/ble/device_information_driver_test.go +++ b/platforms/ble/device_information_driver_test.go @@ -24,8 +24,8 @@ func TestDeviceInformationDriver(t *testing.T) { func TestDeviceInformationDriverStartAndHalt(t *testing.T) { d := initTestDeviceInformationDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestDeviceInformationDriverGetModelNumber(t *testing.T) { diff --git a/platforms/ble/generic_access_driver_test.go b/platforms/ble/generic_access_driver_test.go index 47142136d..8c5c90120 100644 --- a/platforms/ble/generic_access_driver_test.go +++ b/platforms/ble/generic_access_driver_test.go @@ -24,8 +24,8 @@ func TestGenericAccessDriver(t *testing.T) { func TestGenericAccessDriverStartAndHalt(t *testing.T) { d := initTestGenericAccessDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestGenericAccessDriverGetDeviceName(t *testing.T) { diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index b090a8920..b5710e218 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -71,8 +71,8 @@ func TestNewProAdaptor(t *testing.T) { func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() - assert.Nil(t, a.Connect()) - assert.Nil(t, a.DigitalWrite("CSID7", 1)) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.DigitalWrite("CSID7", 1)) fs.WithWriteError = true @@ -85,8 +85,8 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" - assert.Nil(t, a.Connect()) - assert.Nil(t, a.PwmWrite("PWM0", 100)) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.PwmWrite("PWM0", 100)) fs.WithWriteError = true @@ -106,7 +106,7 @@ func TestDigitalIO(t *testing.T) { assert.Equal(t, 1, i) assert.ErrorContains(t, a.DigitalWrite("XIO-P10", 1), "'XIO-P10' is not a valid id for a digital pin") - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestProDigitalIO(t *testing.T) { @@ -121,7 +121,7 @@ func TestProDigitalIO(t *testing.T) { assert.Equal(t, 1, i) assert.ErrorContains(t, a.DigitalWrite("XIO-P0", 1), "'XIO-P0' is not a valid id for a digital pin") - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestPWM(t *testing.T) { @@ -132,7 +132,7 @@ func TestPWM(t *testing.T) { _ = a.Connect() err := a.PwmWrite("PWM0", 100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "0", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents) @@ -141,18 +141,18 @@ func TestPWM(t *testing.T) { assert.Equal(t, "normal", fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents) err = a.ServoWrite("PWM0", 0) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) err = a.ServoWrite("PWM0", 180) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "2000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestI2cDefaultBus(t *testing.T) { @@ -165,11 +165,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-2"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 2) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/dexter/gopigo3/driver_test.go b/platforms/dexter/gopigo3/driver_test.go index c133742d4..ceb6982a8 100644 --- a/platforms/dexter/gopigo3/driver_test.go +++ b/platforms/dexter/gopigo3/driver_test.go @@ -22,12 +22,12 @@ func initTestDriver() *Driver { func TestDriverStart(t *testing.T) { d := initTestDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestDriverHalt(t *testing.T) { d := initTestDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestDriverManufacturerName(t *testing.T) { diff --git a/platforms/digispark/digispark_adaptor_test.go b/platforms/digispark/digispark_adaptor_test.go index de9ccf6b5..59c6105a1 100644 --- a/platforms/digispark/digispark_adaptor_test.go +++ b/platforms/digispark/digispark_adaptor_test.go @@ -92,18 +92,18 @@ func TestDigisparkAdaptorName(t *testing.T) { func TestDigisparkAdaptorConnect(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) } func TestDigisparkAdaptorFinalize(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestDigisparkAdaptorDigitalWrite(t *testing.T) { a := initTestAdaptor() err := a.DigitalWrite("0", uint8(1)) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uint8(0), a.littleWire.(*mock).pin) assert.Equal(t, uint8(1), a.littleWire.(*mock).state) @@ -118,7 +118,7 @@ func TestDigisparkAdaptorDigitalWrite(t *testing.T) { func TestDigisparkAdaptorServoWrite(t *testing.T) { a := initTestAdaptor() err := a.ServoWrite("2", uint8(80)) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uint8(80), a.littleWire.(*mock).locationA) assert.Equal(t, uint8(80), a.littleWire.(*mock).locationB) @@ -131,7 +131,7 @@ func TestDigisparkAdaptorServoWrite(t *testing.T) { func TestDigisparkAdaptorPwmWrite(t *testing.T) { a := initTestAdaptor() err := a.PwmWrite("1", uint8(100)) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uint8(100), a.littleWire.(*mock).pwmChannelA) assert.Equal(t, uint8(100), a.littleWire.(*mock).pwmChannelB) diff --git a/platforms/digispark/digispark_i2c_test.go b/platforms/digispark/digispark_i2c_test.go index 549d70547..5019cc160 100644 --- a/platforms/digispark/digispark_i2c_test.go +++ b/platforms/digispark/digispark_i2c_test.go @@ -45,7 +45,7 @@ func TestDigisparkAdaptorI2cGetI2cConnection(t *testing.T) { c, err = a.GetI2cConnection(availableI2cAddress, a.DefaultI2cBus()) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, c) } @@ -87,7 +87,7 @@ func TestDigisparkAdaptorI2cWrite(t *testing.T) { count, err := c.Write(data) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -107,7 +107,7 @@ func TestDigisparkAdaptorI2cWriteByte(t *testing.T) { err := c.WriteByte(data) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -127,7 +127,7 @@ func TestDigisparkAdaptorI2cWriteByteData(t *testing.T) { err := c.WriteByteData(reg, data) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -147,7 +147,7 @@ func TestDigisparkAdaptorI2cWriteWordData(t *testing.T) { err := c.WriteWordData(reg, data) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -167,7 +167,7 @@ func TestDigisparkAdaptorI2cWriteBlockData(t *testing.T) { err := c.WriteBlockData(reg, data) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -188,7 +188,7 @@ func TestDigisparkAdaptorI2cRead(t *testing.T) { // assert assert.Equal(t, dataLen, count) - assert.Nil(t, err) + assert.NoError(t, err) assert.False(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -206,7 +206,7 @@ func TestDigisparkAdaptorI2cReadByte(t *testing.T) { data, err := c.ReadByte() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.False(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -225,7 +225,7 @@ func TestDigisparkAdaptorI2cReadByteData(t *testing.T) { data, err := c.ReadByteData(reg) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -247,7 +247,7 @@ func TestDigisparkAdaptorI2cReadWordData(t *testing.T) { data, err := c.ReadWordData(reg) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -269,7 +269,7 @@ func TestDigisparkAdaptorI2cReadBlockData(t *testing.T) { err := c.ReadBlockData(reg, data) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -288,7 +288,7 @@ func TestDigisparkAdaptorI2cUpdateDelay(t *testing.T) { err := c.(*digisparkI2cConnection).UpdateDelay(uint(100)) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uint(100), a.littleWire.(*i2cMock).duration) } diff --git a/platforms/dragonboard/dragonboard_adaptor_test.go b/platforms/dragonboard/dragonboard_adaptor_test.go index bde2e27ec..b0b9c6e2f 100644 --- a/platforms/dragonboard/dragonboard_adaptor_test.go +++ b/platforms/dragonboard/dragonboard_adaptor_test.go @@ -55,7 +55,7 @@ func TestDigitalIO(t *testing.T) { assert.Equal(t, 1, i) assert.ErrorContains(t, a.DigitalWrite("GPIO_M", 1), "'GPIO_M' is not a valid id for a digital pin") - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestFinalizeErrorAfterGPIO(t *testing.T) { @@ -70,8 +70,8 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { } fs := a.sys.UseMockFilesystem(mockPaths) - assert.Nil(t, a.Connect()) - assert.Nil(t, a.DigitalWrite("GPIO_B", 1)) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.DigitalWrite("GPIO_B", 1)) fs.WithWriteError = true @@ -89,11 +89,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/firmata/client/client_test.go b/platforms/firmata/client/client_test.go index 5d979fead..ca559ad37 100644 --- a/platforms/firmata/client/client_test.go +++ b/platforms/firmata/client/client_test.go @@ -120,17 +120,17 @@ func TestPins(t *testing.T) { func TestProtocolVersionQuery(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.Nil(t, b.ProtocolVersionQuery()) + assert.NoError(t, b.ProtocolVersionQuery()) } func TestFirmwareQuery(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.Nil(t, b.FirmwareQuery()) + assert.NoError(t, b.FirmwareQuery()) } func TestPinStateQuery(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.Nil(t, b.PinStateQuery(1)) + assert.NoError(t, b.PinStateQuery(1)) } func TestProcessProtocolVersion(t *testing.T) { @@ -232,23 +232,23 @@ func TestProcessDigitalRead4(t *testing.T) { func TestDigitalWrite(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name(), testDataCapabilitiesResponse) - assert.Nil(t, b.DigitalWrite(13, 0)) + assert.NoError(t, b.DigitalWrite(13, 0)) } func TestSetPinMode(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name(), testDataCapabilitiesResponse) - assert.Nil(t, b.SetPinMode(13, Output)) + assert.NoError(t, b.SetPinMode(13, Output)) } func TestAnalogWrite(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name(), testDataCapabilitiesResponse) - assert.Nil(t, b.AnalogWrite(0, 128)) + assert.NoError(t, b.AnalogWrite(0, 128)) } func TestReportAnalog(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.Nil(t, b.ReportAnalog(0, 1)) - assert.Nil(t, b.ReportAnalog(0, 0)) + assert.NoError(t, b.ReportAnalog(0, 1)) + assert.NoError(t, b.ReportAnalog(0, 0)) } func TestProcessPinState13(t *testing.T) { @@ -272,22 +272,22 @@ func TestProcessPinState13(t *testing.T) { func TestI2cConfig(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.Nil(t, b.I2cConfig(100)) + assert.NoError(t, b.I2cConfig(100)) } func TestI2cWrite(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.Nil(t, b.I2cWrite(0x00, []byte{0x01, 0x02})) + assert.NoError(t, b.I2cWrite(0x00, []byte{0x01, 0x02})) } func TestI2cRead(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.Nil(t, b.I2cRead(0x00, 10)) + assert.NoError(t, b.I2cRead(0x00, 10)) } func TestWriteSysex(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.Nil(t, b.WriteSysex([]byte{0x01, 0x02})) + assert.NoError(t, b.WriteSysex([]byte{0x01, 0x02})) } func TestProcessI2cReply(t *testing.T) { @@ -373,9 +373,9 @@ func TestConnect(t *testing.T) { rwc.addTestReadData(testDataProtocolResponse) }) - assert.Nil(t, b.Connect(rwc)) + assert.NoError(t, b.Connect(rwc)) time.Sleep(150 * time.Millisecond) - assert.Nil(t, b.Disconnect()) + assert.NoError(t, b.Disconnect()) } func TestServoConfig(t *testing.T) { diff --git a/platforms/firmata/firmata_adaptor_test.go b/platforms/firmata/firmata_adaptor_test.go index fbfd956d1..3e29c6bb8 100644 --- a/platforms/firmata/firmata_adaptor_test.go +++ b/platforms/firmata/firmata_adaptor_test.go @@ -111,7 +111,7 @@ func TestNewAdaptor(t *testing.T) { func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) a = initTestAdaptor() a.Board.(*mockFirmataBoard).disconnectError = errors.New("close error") @@ -125,7 +125,7 @@ func TestAdaptorConnect(t *testing.T) { a := NewAdaptor("/dev/null") a.PortOpener = openSP a.Board = newMockFirmataBoard() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a = NewAdaptor("/dev/null") a.Board = newMockFirmataBoard() @@ -136,16 +136,16 @@ func TestAdaptorConnect(t *testing.T) { a = NewAdaptor(&readWriteCloser{}) a.Board = newMockFirmataBoard() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a = NewAdaptor("/dev/null") a.Board = nil - assert.Nil(t, a.Disconnect()) + assert.NoError(t, a.Disconnect()) } func TestAdaptorServoWrite(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.ServoWrite("1", 50)) + assert.NoError(t, a.ServoWrite("1", 50)) } func TestAdaptorServoWriteBadPin(t *testing.T) { @@ -155,7 +155,7 @@ func TestAdaptorServoWriteBadPin(t *testing.T) { func TestAdaptorPwmWrite(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.PwmWrite("1", 50)) + assert.NoError(t, a.PwmWrite("1", 50)) } func TestAdaptorPwmWriteBadPin(t *testing.T) { @@ -165,7 +165,7 @@ func TestAdaptorPwmWriteBadPin(t *testing.T) { func TestAdaptorDigitalWrite(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.DigitalWrite("1", 1)) + assert.NoError(t, a.DigitalWrite("1", 1)) } func TestAdaptorDigitalWriteBadPin(t *testing.T) { @@ -176,11 +176,11 @@ func TestAdaptorDigitalWriteBadPin(t *testing.T) { func TestAdaptorDigitalRead(t *testing.T) { a := initTestAdaptor() val, err := a.DigitalRead("1") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, val) val, err = a.DigitalRead("0") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, val) } @@ -194,10 +194,10 @@ func TestAdaptorAnalogRead(t *testing.T) { a := initTestAdaptor() val, err := a.AnalogRead("1") assert.Equal(t, 133, val) - assert.Nil(t, err) + assert.NoError(t, err) val, err = a.AnalogRead("0") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, val) } @@ -210,7 +210,7 @@ func TestAdaptorAnalogReadBadPin(t *testing.T) { func TestServoConfig(t *testing.T) { a := initTestAdaptor() err := a.ServoConfig("9", 0, 0) - assert.Nil(t, err) + assert.NoError(t, err) // test atoi error err = a.ServoConfig("a", 0, 0) diff --git a/platforms/firmata/firmata_i2c_test.go b/platforms/firmata/firmata_i2c_test.go index e9d467b23..eb8ec2e00 100644 --- a/platforms/firmata/firmata_i2c_test.go +++ b/platforms/firmata/firmata_i2c_test.go @@ -72,7 +72,7 @@ func initTestTestAdaptorWithI2cConnection() (i2c.Connection, *i2cMockFirmataBoar func TestClose(t *testing.T) { i2c, _ := initTestTestAdaptorWithI2cConnection() - assert.Nil(t, i2c.Close()) + assert.NoError(t, i2c.Close()) } func TestRead(t *testing.T) { @@ -82,7 +82,7 @@ func TestRead(t *testing.T) { buf := []byte{0} // act countRead, err := con.Read(buf) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, countRead) assert.Equal(t, 1, brd.numBytesToRead) assert.Equal(t, brd.i2cDataForRead, buf) @@ -96,7 +96,7 @@ func TestReadByte(t *testing.T) { // act val, err := con.ReadByte() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, brd.numBytesToRead) assert.Equal(t, brd.i2cDataForRead[0], val) assert.Equal(t, 0, len(brd.i2cWritten)) @@ -110,7 +110,7 @@ func TestReadByteData(t *testing.T) { // act val, err := con.ReadByteData(reg) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, brd.numBytesToRead) assert.Equal(t, brd.i2cDataForRead[0], val) assert.Equal(t, 1, len(brd.i2cWritten)) @@ -127,7 +127,7 @@ func TestReadWordData(t *testing.T) { // act val, err := con.ReadWordData(reg) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, brd.numBytesToRead) assert.Equal(t, uint16(lsb)|uint16(msb)<<8, val) assert.Equal(t, 1, len(brd.i2cWritten)) @@ -143,7 +143,7 @@ func TestReadBlockData(t *testing.T) { // act err := con.ReadBlockData(reg, buf) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 5, brd.numBytesToRead) assert.Equal(t, brd.i2cDataForRead, buf) assert.Equal(t, 1, len(brd.i2cWritten)) @@ -158,7 +158,7 @@ func TestWrite(t *testing.T) { // act written, err := con.Write(want) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, wantLen, written) assert.Equal(t, want, brd.i2cWritten) } @@ -171,7 +171,7 @@ func TestWrite20bytes(t *testing.T) { // act written, err := con.Write(want) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, wantLen, written) assert.Equal(t, want, brd.i2cWritten) } @@ -183,7 +183,7 @@ func TestWriteByte(t *testing.T) { // act err := con.WriteByte(want) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(brd.i2cWritten)) assert.Equal(t, want, brd.i2cWritten[0]) } @@ -196,7 +196,7 @@ func TestWriteByteData(t *testing.T) { // act err := con.WriteByteData(reg, val) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(brd.i2cWritten)) assert.Equal(t, reg, brd.i2cWritten[0]) assert.Equal(t, val, brd.i2cWritten[1]) @@ -210,7 +210,7 @@ func TestWriteWordData(t *testing.T) { // act err := con.WriteWordData(reg, val) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 3, len(brd.i2cWritten)) assert.Equal(t, reg, brd.i2cWritten[0]) assert.Equal(t, uint8(val&0x00FF), brd.i2cWritten[1]) @@ -229,7 +229,7 @@ func TestWriteBlockData(t *testing.T) { // act err := con.WriteBlockData(reg, val) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 33, len(brd.i2cWritten)) assert.Equal(t, reg, brd.i2cWritten[0]) assert.Equal(t, val[0:32], brd.i2cWritten[1:]) diff --git a/platforms/intel-iot/curie/imu_driver_test.go b/platforms/intel-iot/curie/imu_driver_test.go index f1e455921..4e9a21ccd 100644 --- a/platforms/intel-iot/curie/imu_driver_test.go +++ b/platforms/intel-iot/curie/imu_driver_test.go @@ -91,12 +91,12 @@ func initTestIMUDriver() *IMUDriver { func TestIMUDriverStart(t *testing.T) { d := initTestIMUDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestIMUDriverHalt(t *testing.T) { d := initTestIMUDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestIMUDriverDefaultName(t *testing.T) { @@ -118,7 +118,7 @@ func TestIMUDriverConnection(t *testing.T) { func TestIMUDriverReadAccelerometer(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.Nil(t, d.ReadAccelerometer()) + assert.NoError(t, d.ReadAccelerometer()) } func TestIMUDriverReadAccelerometerData(t *testing.T) { @@ -126,14 +126,14 @@ func TestIMUDriverReadAccelerometerData(t *testing.T) { assert.ErrorContains(t, err, "Invalid data") result, err := parseAccelerometerData([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, &AccelerometerData{X: 1920, Y: 1920, Z: 1920}, result) } func TestIMUDriverReadGyroscope(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.Nil(t, d.ReadGyroscope()) + assert.NoError(t, d.ReadGyroscope()) } func TestIMUDriverReadGyroscopeData(t *testing.T) { @@ -141,14 +141,14 @@ func TestIMUDriverReadGyroscopeData(t *testing.T) { assert.ErrorContains(t, err, "Invalid data") result, err := parseGyroscopeData([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, &GyroscopeData{X: 1920, Y: 1920, Z: 1920}, result) } func TestIMUDriverReadTemperature(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.Nil(t, d.ReadTemperature()) + assert.NoError(t, d.ReadTemperature()) } func TestIMUDriverReadTemperatureData(t *testing.T) { @@ -156,14 +156,14 @@ func TestIMUDriverReadTemperatureData(t *testing.T) { assert.ErrorContains(t, err, "Invalid data") result, err := parseTemperatureData([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7}) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, float32(31.546875), result) } func TestIMUDriverEnableShockDetection(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.Nil(t, d.EnableShockDetection(true)) + assert.NoError(t, d.EnableShockDetection(true)) } func TestIMUDriverShockDetectData(t *testing.T) { @@ -171,14 +171,14 @@ func TestIMUDriverShockDetectData(t *testing.T) { assert.ErrorContains(t, err, "Invalid data") result, err := parseShockData([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7}) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, &ShockData{Axis: 0, Direction: 2}, result) } func TestIMUDriverEnableStepCounter(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.Nil(t, d.EnableStepCounter(true)) + assert.NoError(t, d.EnableStepCounter(true)) } func TestIMUDriverStepCountData(t *testing.T) { @@ -186,14 +186,14 @@ func TestIMUDriverStepCountData(t *testing.T) { assert.ErrorContains(t, err, "Invalid data") result, err := parseStepData([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7}) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, int16(256), result) } func TestIMUDriverEnableTapDetection(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.Nil(t, d.EnableTapDetection(true)) + assert.NoError(t, d.EnableTapDetection(true)) } func TestIMUDriverTapDetectData(t *testing.T) { @@ -201,14 +201,14 @@ func TestIMUDriverTapDetectData(t *testing.T) { assert.ErrorContains(t, err, "Invalid data") result, err := parseTapData([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7}) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, &TapData{Axis: 0, Direction: 2}, result) } func TestIMUDriverEnableReadMotion(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.Nil(t, d.ReadMotion()) + assert.NoError(t, d.ReadMotion()) } func TestIMUDriverReadMotionData(t *testing.T) { @@ -216,7 +216,7 @@ func TestIMUDriverReadMotionData(t *testing.T) { assert.ErrorContains(t, err, "Invalid data") result, err := parseMotionData([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, &MotionData{AX: 1920, AY: 1920, AZ: 1920, GX: 1920, GY: 1920, GZ: 1920}, result) } @@ -224,11 +224,11 @@ func TestIMUDriverHandleEvents(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) - assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) - assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7})) - assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7})) - assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7})) - assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7})) - assert.Nil(t, d.handleEvent([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7})) + assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7})) + assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7})) + assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7})) + assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) } diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index cd85a3c3b..e4e998b79 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -235,7 +235,7 @@ func TestConnect(t *testing.T) { assert.Equal(t, 6, a.DefaultI2cBus()) assert.Equal(t, "arduino", a.board) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) } func TestArduinoSetupFail263(t *testing.T) { @@ -272,7 +272,7 @@ func TestArduinoSetupFail131(t *testing.T) { func TestArduinoI2CSetupFailTristate(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.Nil(t, a.arduinoSetup()) + assert.NoError(t, a.arduinoSetup()) fs.WithWriteError = true err := a.arduinoI2CSetup() @@ -282,7 +282,7 @@ func TestArduinoI2CSetupFailTristate(t *testing.T) { func TestArduinoI2CSetupFail14(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.Nil(t, a.arduinoSetup()) + assert.NoError(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/gpio14/direction") err := a.arduinoI2CSetup() @@ -292,7 +292,7 @@ func TestArduinoI2CSetupFail14(t *testing.T) { func TestArduinoI2CSetupUnexportFail(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.Nil(t, a.arduinoSetup()) + assert.NoError(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/unexport") err := a.arduinoI2CSetup() @@ -302,7 +302,7 @@ func TestArduinoI2CSetupUnexportFail(t *testing.T) { func TestArduinoI2CSetupFail236(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.Nil(t, a.arduinoSetup()) + assert.NoError(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/gpio236/direction") err := a.arduinoI2CSetup() @@ -312,7 +312,7 @@ func TestArduinoI2CSetupFail236(t *testing.T) { func TestArduinoI2CSetupFail28(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.Nil(t, a.arduinoSetup()) + assert.NoError(t, a.arduinoSetup()) delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux") err := a.arduinoI2CSetup() @@ -338,7 +338,7 @@ func TestConnectArduinoWriteError(t *testing.T) { func TestConnectSparkfun(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem("sparkfun") - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) assert.Equal(t, 1, a.DefaultI2cBus()) assert.Equal(t, "sparkfun", a.board) } @@ -346,7 +346,7 @@ func TestConnectSparkfun(t *testing.T) { func TestConnectMiniboard(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem("miniboard") - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) assert.Equal(t, 1, a.DefaultI2cBus()) assert.Equal(t, "miniboard", a.board) } @@ -365,10 +365,10 @@ func TestFinalize(t *testing.T) { _ = a.PwmWrite("5", 100) _, _ = a.GetI2cConnection(0xff, 6) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // assert that finalize after finalize is working - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // assert that re-connect is working _ = a.Connect() @@ -400,7 +400,7 @@ func TestDigitalIO(t *testing.T) { _ = a.DigitalWrite("2", 0) i, err := a.DigitalRead("2") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, i) } @@ -468,7 +468,7 @@ func TestPwm(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") err := a.PwmWrite("5", 100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "1960", fs.Files["/sys/class/pwm/pwmchip0/pwm1/duty_cycle"].Contents) err = a.PwmWrite("7", 100) @@ -480,7 +480,7 @@ func TestPwmExportError(t *testing.T) { fs := a.sys.UseMockFilesystem(pwmMockPathsMux13Arduino) delete(fs.Files, "/sys/class/pwm/pwmchip0/export") err := a.Connect() - assert.Nil(t, err) + assert.NoError(t, err) err = a.PwmWrite("5", 100) assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/export: no such file") @@ -541,17 +541,17 @@ func TestI2cWorkflow(t *testing.T) { a.sys.UseMockSyscall() con, err := a.GetI2cConnection(0xff, 6) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0x00, 0x01}) - assert.Nil(t, err) + assert.NoError(t, err) data := []byte{42, 42} _, err = con.Read(data) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, []byte{0x00, 0x01}, data) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -559,11 +559,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem(pwmMockPathsMux13ArduinoI2c) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 6) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0x0A}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/intel-iot/joule/joule_adaptor_test.go b/platforms/intel-iot/joule/joule_adaptor_test.go index edd88ac9e..178825733 100644 --- a/platforms/intel-iot/joule/joule_adaptor_test.go +++ b/platforms/intel-iot/joule/joule_adaptor_test.go @@ -111,13 +111,13 @@ func TestFinalize(t *testing.T) { _ = a.DigitalWrite("J12_1", 1) _ = a.PwmWrite("J12_26", 100) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // assert finalize after finalize is working - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // assert re-connect is working - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) } func TestDigitalIO(t *testing.T) { @@ -129,7 +129,7 @@ func TestDigitalIO(t *testing.T) { _ = a.DigitalWrite("J12_1", 0) i, err := a.DigitalRead("J12_1") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, i) _, err = a.DigitalRead("P9_99") @@ -140,7 +140,7 @@ func TestPwm(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() err := a.PwmWrite("J12_26", 100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "3921568", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) err = a.PwmWrite("4", 100) @@ -176,11 +176,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-2"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 2) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/jetson/jetson_adaptor_test.go b/platforms/jetson/jetson_adaptor_test.go index cb4cdba2c..a3ccec3f9 100644 --- a/platforms/jetson/jetson_adaptor_test.go +++ b/platforms/jetson/jetson_adaptor_test.go @@ -59,7 +59,7 @@ func TestFinalize(t *testing.T) { _ = a.DigitalWrite("3", 1) _, _ = a.GetI2cConnection(0xff, 0) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestPWMPinsConnect(t *testing.T) { @@ -70,7 +70,7 @@ func TestPWMPinsConnect(t *testing.T) { assert.ErrorContains(t, err, "not connected") err = a.Connect() - assert.Nil(t, err) + assert.NoError(t, err) assert.NotEqual(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) assert.Equal(t, 0, len(a.pwmPins)) } @@ -86,13 +86,13 @@ func TestPWMPinsReConnect(t *testing.T) { } a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) assert.Equal(t, 0, len(a.pwmPins)) - assert.Nil(t, a.PwmWrite("33", 1)) + assert.NoError(t, a.PwmWrite("33", 1)) assert.Equal(t, 1, len(a.pwmPins)) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // act err := a.Connect() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, len(a.pwmPins)) } @@ -108,17 +108,17 @@ func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) err := a.DigitalWrite("7", 1) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio216/value"].Contents) err = a.DigitalWrite("13", 1) - assert.Nil(t, err) + assert.NoError(t, err) i, err := a.DigitalRead("13") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, i) assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid id for a digital pin") - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestDigitalPinConcurrency(t *testing.T) { @@ -163,11 +163,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/jetson/pwm_pin_test.go b/platforms/jetson/pwm_pin_test.go index 3fd971f5b..5bddaa8db 100644 --- a/platforms/jetson/pwm_pin_test.go +++ b/platforms/jetson/pwm_pin_test.go @@ -37,15 +37,15 @@ func TestPwmPin(t *testing.T) { require.Equal(t, "", fs.Files[periodPath].Contents) require.Equal(t, "", fs.Files[dutyCyclePath].Contents) - assert.Nil(t, pin.Export()) + assert.NoError(t, pin.Export()) assert.Equal(t, "3", fs.Files[exportPath].Contents) - assert.Nil(t, pin.SetEnabled(true)) + assert.NoError(t, pin.SetEnabled(true)) assert.Equal(t, "1", fs.Files[enablePath].Contents) val, _ := pin.Polarity() assert.True(t, val) - assert.Nil(t, pin.SetPolarity(false)) + assert.NoError(t, pin.SetPolarity(false)) val, _ = pin.Polarity() assert.True(t, val) @@ -54,7 +54,7 @@ func TestPwmPin(t *testing.T) { assert.ErrorContains(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") assert.Equal(t, "", fs.Files[dutyCyclePath].Contents) - assert.Nil(t, pin.SetPeriod(20000000)) + assert.NoError(t, pin.SetPeriod(20000000)) // TODO: see PR #990 assert.Equal(t, "20000000", fs.Files[periodPath].Contents) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) @@ -64,7 +64,7 @@ func TestPwmPin(t *testing.T) { dc, _ := pin.DutyCycle() assert.Equal(t, uint32(0), dc) - assert.Nil(t, pin.SetDutyCycle(10000)) + assert.NoError(t, pin.SetDutyCycle(10000)) assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) @@ -74,6 +74,6 @@ func TestPwmPin(t *testing.T) { assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) assert.Equal(t, uint32(10000), dc) - assert.Nil(t, pin.Unexport()) + assert.NoError(t, pin.Unexport()) assert.Equal(t, "3", fs.Files[unexportPath].Contents) } diff --git a/platforms/joystick/joystick_adaptor_test.go b/platforms/joystick/joystick_adaptor_test.go index 3a96a2031..98ef288fd 100644 --- a/platforms/joystick/joystick_adaptor_test.go +++ b/platforms/joystick/joystick_adaptor_test.go @@ -29,7 +29,7 @@ func TestJoystickAdaptorName(t *testing.T) { func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a = NewAdaptor("6") err := a.Connect() @@ -39,5 +39,5 @@ func TestAdaptorConnect(t *testing.T) { func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() _ = a.Connect() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index 0c581d4de..61ce25f7d 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -36,7 +36,7 @@ func TestJoystickDriverName(t *testing.T) { func TestDriverStart(t *testing.T) { d, _ := initTestDriver("./configs/dualshock3.json") d.interval = 1 * time.Millisecond - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) time.Sleep(2 * time.Millisecond) } @@ -45,7 +45,7 @@ func TestDriverHalt(t *testing.T) { go func() { <-d.halt }() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestDriverHandleEventDS3(t *testing.T) { diff --git a/platforms/keyboard/keyboard_driver_test.go b/platforms/keyboard/keyboard_driver_test.go index 75327c42d..a611c0e51 100644 --- a/platforms/keyboard/keyboard_driver_test.go +++ b/platforms/keyboard/keyboard_driver_test.go @@ -35,10 +35,10 @@ func TestKeyboardDriverName(t *testing.T) { func TestKeyboardDriverStart(t *testing.T) { d := initTestKeyboardDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestKeyboardDriverHalt(t *testing.T) { d := initTestKeyboardDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } diff --git a/platforms/leap/leap_motion_adaptor_test.go b/platforms/leap/leap_motion_adaptor_test.go index a7f8f8a5b..ac0cadddd 100644 --- a/platforms/leap/leap_motion_adaptor_test.go +++ b/platforms/leap/leap_motion_adaptor_test.go @@ -32,7 +32,7 @@ func TestLeapMotionAdaptorName(t *testing.T) { func TestLeapMotionAdaptorConnect(t *testing.T) { a := initTestLeapMotionAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") @@ -42,5 +42,5 @@ func TestLeapMotionAdaptorConnect(t *testing.T) { func TestLeapMotionAdaptorFinalize(t *testing.T) { a := initTestLeapMotionAdaptor() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } diff --git a/platforms/leap/leap_motion_driver_test.go b/platforms/leap/leap_motion_driver_test.go index 34490e40c..2da70f8fa 100644 --- a/platforms/leap/leap_motion_driver_test.go +++ b/platforms/leap/leap_motion_driver_test.go @@ -69,7 +69,7 @@ func TestLeapMotionDriverName(t *testing.T) { func TestLeapMotionDriverStart(t *testing.T) { d, _ := initTestLeapMotionDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) d2, rwc := initTestLeapMotionDriver() e := errors.New("write error") @@ -79,7 +79,7 @@ func TestLeapMotionDriverStart(t *testing.T) { func TestLeapMotionDriverHalt(t *testing.T) { d, _ := initTestLeapMotionDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestLeapMotionDriverParser(t *testing.T) { diff --git a/platforms/mavlink/mavlink_adaptor_test.go b/platforms/mavlink/mavlink_adaptor_test.go index 6a921515c..194bc54ee 100644 --- a/platforms/mavlink/mavlink_adaptor_test.go +++ b/platforms/mavlink/mavlink_adaptor_test.go @@ -66,7 +66,7 @@ func TestMavlinkAdaptorName(t *testing.T) { func TestMavlinkAdaptorConnect(t *testing.T) { a := initTestMavlinkAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } assert.ErrorContains(t, a.Connect(), "connect error") @@ -74,7 +74,7 @@ func TestMavlinkAdaptorConnect(t *testing.T) { func TestMavlinkAdaptorFinalize(t *testing.T) { a := initTestMavlinkAdaptor() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) testAdaptorClose = func() error { return errors.New("close error") diff --git a/platforms/mavlink/mavlink_driver_test.go b/platforms/mavlink/mavlink_driver_test.go index fd7e628c3..5c6846f82 100644 --- a/platforms/mavlink/mavlink_driver_test.go +++ b/platforms/mavlink/mavlink_driver_test.go @@ -59,11 +59,11 @@ func TestMavlinkDriverStart(t *testing.T) { err <- data.(error) }) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) select { case p := <-packet: - assert.Nil(t, d.SendPacket(p)) + assert.NoError(t, d.SendPacket(p)) case <-time.After(100 * time.Millisecond): t.Errorf("packet was not emitted") @@ -82,5 +82,5 @@ func TestMavlinkDriverStart(t *testing.T) { func TestMavlinkDriverHalt(t *testing.T) { d := initTestMavlinkDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } diff --git a/platforms/mavlink/mavlink_udp_adaptor_test.go b/platforms/mavlink/mavlink_udp_adaptor_test.go index 1dffd7cd6..8705a3f6d 100644 --- a/platforms/mavlink/mavlink_udp_adaptor_test.go +++ b/platforms/mavlink/mavlink_udp_adaptor_test.go @@ -65,8 +65,8 @@ func TestMavlinkUDPAdaptorName(t *testing.T) { func TestMavlinkUDPAdaptorConnectAndFinalize(t *testing.T) { a := initTestMavlinkUDPAdaptor() - assert.Nil(t, a.Connect()) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Connect()) + assert.NoError(t, a.Finalize()) } func TestMavlinkUDPAdaptorWrite(t *testing.T) { @@ -82,7 +82,7 @@ func TestMavlinkUDPAdaptorWrite(t *testing.T) { i, err := a.Write([]byte{0x01, 0x02, 0x03}) assert.Equal(t, 3, i) - assert.Nil(t, err) + assert.NoError(t, err) } func TestMavlinkReadMAVLinkReadDefaultPacket(t *testing.T) { diff --git a/platforms/microbit/accelerometer_driver_test.go b/platforms/microbit/accelerometer_driver_test.go index 538cff44c..2ff9fbd94 100644 --- a/platforms/microbit/accelerometer_driver_test.go +++ b/platforms/microbit/accelerometer_driver_test.go @@ -25,8 +25,8 @@ func TestAccelerometerDriver(t *testing.T) { func TestAccelerometerDriverStartAndHalt(t *testing.T) { d := initTestAccelerometerDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestAccelerometerDriverReadData(t *testing.T) { diff --git a/platforms/microbit/button_driver_test.go b/platforms/microbit/button_driver_test.go index adde9c703..6cc965f03 100644 --- a/platforms/microbit/button_driver_test.go +++ b/platforms/microbit/button_driver_test.go @@ -25,8 +25,8 @@ func TestButtonDriver(t *testing.T) { func TestButtonDriverStartAndHalt(t *testing.T) { d := initTestButtonDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestButtonDriverReadData(t *testing.T) { diff --git a/platforms/microbit/io_pin_driver_test.go b/platforms/microbit/io_pin_driver_test.go index 582d3452b..11bf2e57d 100644 --- a/platforms/microbit/io_pin_driver_test.go +++ b/platforms/microbit/io_pin_driver_test.go @@ -39,8 +39,8 @@ func TestIOPinDriverStartAndHalt(t *testing.T) { a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { return []byte{0, 1, 1, 0}, nil }) - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestIOPinDriverStartError(t *testing.T) { @@ -82,7 +82,7 @@ func TestIOPinDriverDigitalWrite(t *testing.T) { d := NewIOPinDriver(a) // TODO: a better test - assert.Nil(t, d.DigitalWrite("0", 1)) + assert.NoError(t, d.DigitalWrite("0", 1)) } func TestIOPinDriverDigitalWriteInvalidPin(t *testing.T) { @@ -139,7 +139,7 @@ func TestIOPinDriverDigitalWriteAnalogRead(t *testing.T) { return []byte{0, 0, 1, 128, 2, 1}, nil }) - assert.Nil(t, d.DigitalWrite("1", 0)) + assert.NoError(t, d.DigitalWrite("1", 0)) val, _ := d.AnalogRead("1") assert.Equal(t, 128, val) @@ -155,5 +155,5 @@ func TestIOPinDriverAnalogReadDigitalWrite(t *testing.T) { val, _ := d.AnalogRead("1") assert.Equal(t, 128, val) - assert.Nil(t, d.DigitalWrite("1", 0)) + assert.NoError(t, d.DigitalWrite("1", 0)) } diff --git a/platforms/microbit/led_driver_test.go b/platforms/microbit/led_driver_test.go index fb24f147b..963759fe3 100644 --- a/platforms/microbit/led_driver_test.go +++ b/platforms/microbit/led_driver_test.go @@ -24,32 +24,32 @@ func TestLEDDriver(t *testing.T) { func TestLEDDriverStartAndHalt(t *testing.T) { d := initTestLEDDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestLEDDriverWriteMatrix(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - assert.Nil(t, d.WriteMatrix([]byte{0x01, 0x02})) + assert.NoError(t, d.WriteMatrix([]byte{0x01, 0x02})) } func TestLEDDriverWriteText(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - assert.Nil(t, d.WriteText("Hello")) + assert.NoError(t, d.WriteText("Hello")) } func TestLEDDriverCommands(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - assert.Nil(t, d.Blank()) - assert.Nil(t, d.Solid()) - assert.Nil(t, d.UpRightArrow()) - assert.Nil(t, d.UpLeftArrow()) - assert.Nil(t, d.DownRightArrow()) - assert.Nil(t, d.DownLeftArrow()) - assert.Nil(t, d.Dimond()) - assert.Nil(t, d.Smile()) - assert.Nil(t, d.Wink()) + assert.NoError(t, d.Blank()) + assert.NoError(t, d.Solid()) + assert.NoError(t, d.UpRightArrow()) + assert.NoError(t, d.UpLeftArrow()) + assert.NoError(t, d.DownRightArrow()) + assert.NoError(t, d.DownLeftArrow()) + assert.NoError(t, d.Dimond()) + assert.NoError(t, d.Smile()) + assert.NoError(t, d.Wink()) } diff --git a/platforms/microbit/magnetometer_driver_test.go b/platforms/microbit/magnetometer_driver_test.go index 7a9e0bde9..884c9d8ae 100644 --- a/platforms/microbit/magnetometer_driver_test.go +++ b/platforms/microbit/magnetometer_driver_test.go @@ -25,8 +25,8 @@ func TestMagnetometerDriver(t *testing.T) { func TestMagnetometerDriverStartAndHalt(t *testing.T) { d := initTestMagnetometerDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestMagnetometerDriverReadData(t *testing.T) { diff --git a/platforms/microbit/temperature_driver_test.go b/platforms/microbit/temperature_driver_test.go index 4ab2bb4a1..5bd352799 100644 --- a/platforms/microbit/temperature_driver_test.go +++ b/platforms/microbit/temperature_driver_test.go @@ -25,8 +25,8 @@ func TestTemperatureDriver(t *testing.T) { func TestTemperatureDriverStartAndHalt(t *testing.T) { d := initTestTemperatureDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestTemperatureDriverReadData(t *testing.T) { diff --git a/platforms/mqtt/mqtt_adaptor_test.go b/platforms/mqtt/mqtt_adaptor_test.go index 3da5833c7..77a38b0ee 100644 --- a/platforms/mqtt/mqtt_adaptor_test.go +++ b/platforms/mqtt/mqtt_adaptor_test.go @@ -90,7 +90,7 @@ func TestMqttAdaptorConnectWithAuthError(t *testing.T) { func TestMqttAdaptorFinalize(t *testing.T) { a := initTestMqttAdaptor() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestMqttAdaptorCannotPublishUnlessConnected(t *testing.T) { diff --git a/platforms/mqtt/mqtt_driver_test.go b/platforms/mqtt/mqtt_driver_test.go index 1cbfe29db..bf77fcdfa 100644 --- a/platforms/mqtt/mqtt_driver_test.go +++ b/platforms/mqtt/mqtt_driver_test.go @@ -16,8 +16,8 @@ func TestMqttDriver(t *testing.T) { assert.True(t, strings.HasPrefix(d.Name(), "MQTT")) assert.True(t, strings.HasPrefix(d.Connection().Name(), "MQTT")) - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestMqttDriverName(t *testing.T) { diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index 9c120b5d7..fe922621d 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -93,7 +93,7 @@ func TestDigitalIO(t *testing.T) { assert.Equal(t, 1, i) assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestInvalidPWMPin(t *testing.T) { @@ -118,7 +118,7 @@ func TestPwmWrite(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("PWM", 100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) @@ -127,15 +127,15 @@ func TestPwmWrite(t *testing.T) { assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.ServoWrite("PWM", 0) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("PWM", 180) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestSetPeriod(t *testing.T) { @@ -147,7 +147,7 @@ func TestSetPeriod(t *testing.T) { // act err := a.SetPeriod("PWM", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) @@ -156,7 +156,7 @@ func TestSetPeriod(t *testing.T) { // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("PWM", 127) // 127 is a little bit smaller than 50% of period - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 1270000), fs.Files[pwmDutyCyclePath].Contents) newPeriod = newPeriod / 10 @@ -164,7 +164,7 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("PWM", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 127000), fs.Files[pwmDutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value @@ -174,14 +174,14 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("PWM", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 2540000), fs.Files[pwmDutyCyclePath].Contents) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - assert.Nil(t, a.DigitalWrite("7", 1)) + assert.NoError(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true @@ -193,7 +193,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) - assert.Nil(t, a.PwmWrite("PWM", 1)) + assert.NoError(t, a.PwmWrite("PWM", 1)) fs.WithWriteError = true @@ -221,11 +221,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewNeoAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/nats/nats_adaptor_test.go b/platforms/nats/nats_adaptor_test.go index e0dbd6bea..feccd0a94 100644 --- a/platforms/nats/nats_adaptor_test.go +++ b/platforms/nats/nats_adaptor_test.go @@ -74,7 +74,7 @@ func TestNatsAdapterSetsRootCAs(t *testing.T) { _ = a.Connect() o := a.client.Opts casPool, err := o.RootCAsCB() - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, casPool) assert.True(t, o.Secure) } @@ -84,7 +84,7 @@ func TestNatsAdapterSetsClientCerts(t *testing.T) { assert.Equal(t, "tls://localhost:4242", a.Host) _ = a.Connect() cert, err := a.client.Opts.TLSCertCB() - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, cert) assert.NotNil(t, cert.Leaf) assert.True(t, a.client.Opts.Secure) @@ -95,7 +95,7 @@ func TestNatsAdapterSetsClientCertsWithUserInfo(t *testing.T) { assert.Equal(t, "tls://localhost:4242", a.Host) _ = a.Connect() cert, err := a.client.Opts.TLSCertCB() - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, cert) assert.NotNil(t, cert.Leaf) assert.True(t, a.client.Opts.Secure) @@ -153,7 +153,7 @@ func TestNatsAdaptorFailedConnect(t *testing.T) { func TestNatsAdaptorFinalize(t *testing.T) { a := NewAdaptor("localhost:9999", 79999) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestNatsAdaptorCannotPublishUnlessConnected(t *testing.T) { diff --git a/platforms/nats/nats_driver_test.go b/platforms/nats/nats_driver_test.go index 7c8a14c61..d9a4a970b 100644 --- a/platforms/nats/nats_driver_test.go +++ b/platforms/nats/nats_driver_test.go @@ -17,8 +17,8 @@ func TestNatsDriver(t *testing.T) { assert.True(t, strings.HasPrefix(d.Connection().Name(), "NATS")) assert.NotNil(t, d.adaptor()) - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestNatsDriverName(t *testing.T) { diff --git a/platforms/neurosky/neurosky_adaptor_test.go b/platforms/neurosky/neurosky_adaptor_test.go index b52bfddaa..68528c391 100644 --- a/platforms/neurosky/neurosky_adaptor_test.go +++ b/platforms/neurosky/neurosky_adaptor_test.go @@ -69,7 +69,7 @@ func TestNeuroskyAdaptorName(t *testing.T) { func TestNeuroskyAdaptorConnect(t *testing.T) { a := initTestNeuroskyAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") @@ -84,7 +84,7 @@ func TestNeuroskyAdaptorFinalize(t *testing.T) { return rwc, nil } _ = a.Connect() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) rwc.CloseError(errors.New("close error")) _ = a.Connect() diff --git a/platforms/neurosky/neurosky_driver_test.go b/platforms/neurosky/neurosky_driver_test.go index d35cd819a..d5d3cfee5 100644 --- a/platforms/neurosky/neurosky_driver_test.go +++ b/platforms/neurosky/neurosky_driver_test.go @@ -52,7 +52,7 @@ func TestNeuroskyDriverStart(t *testing.T) { sem <- true }) - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) time.Sleep(50 * time.Millisecond) rwc.ReadError(e) @@ -69,7 +69,7 @@ func TestNeuroskyDriverStart(t *testing.T) { func TestNeuroskyDriverHalt(t *testing.T) { d := initTestNeuroskyDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestNeuroskyDriverParse(t *testing.T) { diff --git a/platforms/opencv/camera_driver_test.go b/platforms/opencv/camera_driver_test.go index 989c0e95e..973f36cf2 100644 --- a/platforms/opencv/camera_driver_test.go +++ b/platforms/opencv/camera_driver_test.go @@ -36,7 +36,7 @@ func TestCameraDriverName(t *testing.T) { func TestCameraDriverStart(t *testing.T) { sem := make(chan bool) d := initTestCameraDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) d.On(d.Event("frame"), func(data interface{}) { sem <- true }) @@ -47,7 +47,7 @@ func TestCameraDriverStart(t *testing.T) { } d = NewCameraDriver("") - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) d = NewCameraDriver(true) assert.NotNil(t, d.Start()) @@ -55,5 +55,5 @@ func TestCameraDriverStart(t *testing.T) { func TestCameraDriverHalt(t *testing.T) { d := initTestCameraDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } diff --git a/platforms/opencv/window_driver_test.go b/platforms/opencv/window_driver_test.go index 7d5d2acd5..bc652ccb9 100644 --- a/platforms/opencv/window_driver_test.go +++ b/platforms/opencv/window_driver_test.go @@ -33,12 +33,12 @@ func TestWindowDriverName(t *testing.T) { func TestWindowDriverStart(t *testing.T) { d := initTestWindowDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestWindowDriverHalt(t *testing.T) { d := initTestWindowDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestWindowDriverShowImage(t *testing.T) { diff --git a/platforms/parrot/ardrone/ardrone_adaptor_test.go b/platforms/parrot/ardrone/ardrone_adaptor_test.go index bfaf830f1..90bed54ef 100644 --- a/platforms/parrot/ardrone/ardrone_adaptor_test.go +++ b/platforms/parrot/ardrone/ardrone_adaptor_test.go @@ -29,7 +29,7 @@ func TestArdroneAdaptor(t *testing.T) { func TestArdroneAdaptorConnect(t *testing.T) { a := initTestArdroneAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a.connect = func(a *Adaptor) (drone, error) { return nil, errors.New("connection error") @@ -46,5 +46,5 @@ func TestArdroneAdaptorName(t *testing.T) { func TestArdroneAdaptorFinalize(t *testing.T) { a := initTestArdroneAdaptor() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } diff --git a/platforms/parrot/ardrone/ardrone_driver_test.go b/platforms/parrot/ardrone/ardrone_driver_test.go index bec2ff8e2..2d35a189b 100644 --- a/platforms/parrot/ardrone/ardrone_driver_test.go +++ b/platforms/parrot/ardrone/ardrone_driver_test.go @@ -34,12 +34,12 @@ func TestArdroneDriverName(t *testing.T) { func TestArdroneDriverStart(t *testing.T) { d := initTestArdroneDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestArdroneDriverHalt(t *testing.T) { d := initTestArdroneDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestArdroneDriverTakeOff(t *testing.T) { diff --git a/platforms/parrot/bebop/bebop_adaptor_test.go b/platforms/parrot/bebop/bebop_adaptor_test.go index 7d31d9fcf..6c5e0301c 100644 --- a/platforms/parrot/bebop/bebop_adaptor_test.go +++ b/platforms/parrot/bebop/bebop_adaptor_test.go @@ -29,7 +29,7 @@ func TestBebopAdaptorName(t *testing.T) { func TestBebopAdaptorConnect(t *testing.T) { a := initTestBebopAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a.connect = func(a *Adaptor) error { return errors.New("connection error") @@ -40,5 +40,5 @@ func TestBebopAdaptorConnect(t *testing.T) { func TestBebopAdaptorFinalize(t *testing.T) { a := initTestBebopAdaptor() _ = a.Connect() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } diff --git a/platforms/parrot/minidrone/minidrone_driver_test.go b/platforms/parrot/minidrone/minidrone_driver_test.go index 5ab313a45..a197a8947 100644 --- a/platforms/parrot/minidrone/minidrone_driver_test.go +++ b/platforms/parrot/minidrone/minidrone_driver_test.go @@ -24,133 +24,133 @@ func TestMinidroneDriver(t *testing.T) { func TestMinidroneDriverStartAndHalt(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestMinidroneTakeoff(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.TakeOff()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.TakeOff()) } func TestMinidroneEmergency(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Emergency()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Emergency()) } func TestMinidroneTakePicture(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.TakePicture()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.TakePicture()) } func TestMinidroneUp(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Up(25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Up(25)) } func TestMinidroneUpTooFar(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Up(125)) - assert.Nil(t, d.Up(-50)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Up(125)) + assert.NoError(t, d.Up(-50)) } func TestMinidroneDown(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Down(25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Down(25)) } func TestMinidroneForward(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Forward(25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Forward(25)) } func TestMinidroneBackward(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Backward(25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Backward(25)) } func TestMinidroneRight(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Right(25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Right(25)) } func TestMinidroneLeft(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Left(25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Left(25)) } func TestMinidroneClockwise(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Clockwise(25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Clockwise(25)) } func TestMinidroneCounterClockwise(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.CounterClockwise(25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.CounterClockwise(25)) } func TestMinidroneStop(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Stop()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Stop()) } func TestMinidroneStartStopRecording(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.StartRecording()) - assert.Nil(t, d.StopRecording()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.StartRecording()) + assert.NoError(t, d.StopRecording()) } func TestMinidroneHullProtectionOutdoor(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.HullProtection(true)) - assert.Nil(t, d.Outdoor(true)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.HullProtection(true)) + assert.NoError(t, d.Outdoor(true)) } func TestMinidroneHullFlips(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.FrontFlip()) - assert.Nil(t, d.BackFlip()) - assert.Nil(t, d.RightFlip()) - assert.Nil(t, d.LeftFlip()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.FrontFlip()) + assert.NoError(t, d.BackFlip()) + assert.NoError(t, d.RightFlip()) + assert.NoError(t, d.LeftFlip()) } func TestMinidroneLightControl(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.LightControl(0, LightBlinked, 25)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.LightControl(0, LightBlinked, 25)) } func TestMinidroneClawControl(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.ClawControl(0, ClawOpen)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.ClawControl(0, ClawOpen)) } func TestMinidroneGunControl(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.GunControl(0)) + assert.NoError(t, d.Start()) + assert.NoError(t, d.GunControl(0)) } func TestMinidroneProcessFlightData(t *testing.T) { d := initTestMinidroneDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) d.processFlightStatus([]byte{0x00, 0x00, 0x00}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x00}) @@ -166,5 +166,5 @@ func TestMinidroneProcessFlightData(t *testing.T) { d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06}) - assert.Nil(t, d.Stop()) + assert.NoError(t, d.Stop()) } diff --git a/platforms/particle/adaptor_test.go b/platforms/particle/adaptor_test.go index 43e2d6c39..544804e76 100644 --- a/platforms/particle/adaptor_test.go +++ b/platforms/particle/adaptor_test.go @@ -88,13 +88,13 @@ func TestNewAdaptor(t *testing.T) { func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) } func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() _ = a.Connect() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestAdaptorAnalogRead(t *testing.T) { @@ -403,5 +403,5 @@ func TestAdaptorEventStream(t *testing.T) { } _, err = a.EventStream("devices", "") - assert.Nil(t, err) + assert.NoError(t, err) } diff --git a/platforms/pebble/pebble_adaptor_test.go b/platforms/pebble/pebble_adaptor_test.go index 23e2488a5..b7b4577ac 100644 --- a/platforms/pebble/pebble_adaptor_test.go +++ b/platforms/pebble/pebble_adaptor_test.go @@ -20,10 +20,10 @@ func TestAdaptor(t *testing.T) { func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) } func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } diff --git a/platforms/pebble/pebble_driver_test.go b/platforms/pebble/pebble_driver_test.go index 997afe9b6..b68f3f3f8 100644 --- a/platforms/pebble/pebble_driver_test.go +++ b/platforms/pebble/pebble_driver_test.go @@ -16,12 +16,12 @@ func initTestDriver() *Driver { func TestDriverStart(t *testing.T) { d := initTestDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestDriverHalt(t *testing.T) { d := initTestDriver() - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestDriver(t *testing.T) { diff --git a/platforms/raspi/pwm_pin_test.go b/platforms/raspi/pwm_pin_test.go index 06e842cd4..ea3cc6f82 100644 --- a/platforms/raspi/pwm_pin_test.go +++ b/platforms/raspi/pwm_pin_test.go @@ -17,13 +17,13 @@ func TestPwmPin(t *testing.T) { pin := NewPWMPin(a, path, "1") - assert.Nil(t, pin.Export()) - assert.Nil(t, pin.SetEnabled(true)) + assert.NoError(t, pin.Export()) + assert.NoError(t, pin.SetEnabled(true)) val, _ := pin.Polarity() assert.True(t, val) - assert.Nil(t, pin.SetPolarity(false)) + assert.NoError(t, pin.SetPolarity(false)) val, _ = pin.Polarity() assert.True(t, val) @@ -32,7 +32,7 @@ func TestPwmPin(t *testing.T) { assert.ErrorContains(t, err, "Raspi PWM pin period not set") assert.ErrorContains(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") - assert.Nil(t, pin.SetPeriod(20000000)) + assert.NoError(t, pin.SetPeriod(20000000)) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) assert.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") @@ -40,7 +40,7 @@ func TestPwmPin(t *testing.T) { dc, _ := pin.DutyCycle() assert.Equal(t, uint32(0), dc) - assert.Nil(t, pin.SetDutyCycle(10000)) + assert.NoError(t, pin.SetDutyCycle(10000)) dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) @@ -49,5 +49,5 @@ func TestPwmPin(t *testing.T) { dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) - assert.Nil(t, pin.Unexport()) + assert.NoError(t, pin.Unexport()) } diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index cba65d377..402916421 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -103,7 +103,7 @@ func TestFinalize(t *testing.T) { _ = a.PwmWrite("7", 255) _, _ = a.GetI2cConnection(0xff, 0) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestDigitalPWM(t *testing.T) { @@ -111,17 +111,17 @@ func TestDigitalPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockedPaths) a.PiBlasterPeriod = 20000000 - assert.Nil(t, a.PwmWrite("7", 4)) + assert.NoError(t, a.PwmWrite("7", 4)) pin, _ := a.PWMPin("7") period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) - assert.Nil(t, a.PwmWrite("7", 255)) + assert.NoError(t, a.PwmWrite("7", 255)) assert.Equal(t, "4=1", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - assert.Nil(t, a.ServoWrite("11", 90)) + assert.NoError(t, a.ServoWrite("11", 90)) assert.Equal(t, "17=0.5", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) @@ -132,7 +132,7 @@ func TestDigitalPWM(t *testing.T) { period, _ = pin.Period() assert.Equal(t, uint32(20000000), period) - assert.Nil(t, pin.SetDutyCycle(1.5*1000*1000)) + assert.NoError(t, pin.SetDutyCycle(1.5*1000*1000)) assert.Equal(t, "18=0.075", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) } @@ -149,19 +149,19 @@ func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockedPaths) err := a.DigitalWrite("7", 1) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio4/value"].Contents) a.revision = "2" err = a.DigitalWrite("13", 1) - assert.Nil(t, err) + assert.NoError(t, err) i, err := a.DigitalRead("13") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, i) assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "Not a valid pin") - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestDigitalPinConcurrency(t *testing.T) { @@ -197,18 +197,18 @@ func TestPWMPin(t *testing.T) { a.revision = "3" firstSysPin, err := a.PWMPin("35") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.pwmPins)) secondSysPin, err := a.PWMPin("35") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.pwmPins)) assert.Equal(t, secondSysPin, firstSysPin) otherSysPin, err := a.PWMPin("36") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(a.pwmPins)) assert.NotEqual(t, otherSysPin, firstSysPin) } @@ -222,17 +222,17 @@ func TestPWMPinsReConnect(t *testing.T) { } _, err := a.PWMPin("35") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 1, len(a.pwmPins)) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) // act err = a.Connect() // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 0, len(a.pwmPins)) _, _ = a.PWMPin("35") _, err = a.PWMPin("36") - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, 2, len(a.pwmPins)) } @@ -262,11 +262,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/sphero/bb8/bb8_driver_test.go b/platforms/sphero/bb8/bb8_driver_test.go index e5ed22afa..d937730f7 100644 --- a/platforms/sphero/bb8/bb8_driver_test.go +++ b/platforms/sphero/bb8/bb8_driver_test.go @@ -24,6 +24,6 @@ func TestBB8Driver(t *testing.T) { func TestBB8DriverStartAndHalt(t *testing.T) { d := initTestBB8Driver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } diff --git a/platforms/sphero/ollie/ollie_driver_test.go b/platforms/sphero/ollie/ollie_driver_test.go index 4eecfee7a..3116d5849 100644 --- a/platforms/sphero/ollie/ollie_driver_test.go +++ b/platforms/sphero/ollie/ollie_driver_test.go @@ -26,8 +26,8 @@ func TestOllieDriver(t *testing.T) { func TestOllieDriverStartAndHalt(t *testing.T) { d := initTestOllieDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } func TestLocatorData(t *testing.T) { diff --git a/platforms/sphero/sphero_adaptor_test.go b/platforms/sphero/sphero_adaptor_test.go index e51aa2775..1ca2a7205 100644 --- a/platforms/sphero/sphero_adaptor_test.go +++ b/platforms/sphero/sphero_adaptor_test.go @@ -82,7 +82,7 @@ func TestSpheroAdaptorReconnect(t *testing.T) { func TestSpheroAdaptorFinalize(t *testing.T) { a, rwc := initTestSpheroAdaptor() _ = a.Connect() - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) rwc.testAdaptorClose = func() error { return errors.New("close error") @@ -94,7 +94,7 @@ func TestSpheroAdaptorFinalize(t *testing.T) { func TestSpheroAdaptorConnect(t *testing.T) { a, _ := initTestSpheroAdaptor() - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) a.connect = func(string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") diff --git a/platforms/sphero/sphero_driver_test.go b/platforms/sphero/sphero_driver_test.go index a3d5df1ca..879455c62 100644 --- a/platforms/sphero/sphero_driver_test.go +++ b/platforms/sphero/sphero_driver_test.go @@ -84,13 +84,13 @@ func TestSpheroDriver(t *testing.T) { func TestSpheroDriverStart(t *testing.T) { d := initTestSpheroDriver() - assert.Nil(t, d.Start()) + assert.NoError(t, d.Start()) } func TestSpheroDriverHalt(t *testing.T) { d := initTestSpheroDriver() d.adaptor().connected = true - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Halt()) } func TestSpheroDriverSetDataStreaming(t *testing.T) { diff --git a/platforms/sphero/sprkplus/sprkplus_driver_test.go b/platforms/sphero/sprkplus/sprkplus_driver_test.go index 0c28c86ea..80097850f 100644 --- a/platforms/sphero/sprkplus/sprkplus_driver_test.go +++ b/platforms/sphero/sprkplus/sprkplus_driver_test.go @@ -24,6 +24,6 @@ func TestSPRKPlusDriver(t *testing.T) { func TestSPRKPlusDriverStartAndHalt(t *testing.T) { d := initTestSPRKPlusDriver() - assert.Nil(t, d.Start()) - assert.Nil(t, d.Halt()) + assert.NoError(t, d.Start()) + assert.NoError(t, d.Halt()) } diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 4e3abed6b..14a9dae1c 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -93,7 +93,7 @@ func TestDigitalIO(t *testing.T) { assert.Equal(t, 1, i) assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestInvalidPWMPin(t *testing.T) { @@ -118,7 +118,7 @@ func TestPwmWrite(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("33", 100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) @@ -127,15 +127,15 @@ func TestPwmWrite(t *testing.T) { assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.ServoWrite("33", 0) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("33", 180) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestSetPeriod(t *testing.T) { @@ -147,7 +147,7 @@ func TestSetPeriod(t *testing.T) { // act err := a.SetPeriod("33", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) @@ -156,7 +156,7 @@ func TestSetPeriod(t *testing.T) { // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("33", 127) // 127 is a little bit smaller than 50% of period - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 1270000), fs.Files[pwmDutyCyclePath].Contents) newPeriod = newPeriod / 10 @@ -164,7 +164,7 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("33", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 127000), fs.Files[pwmDutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value @@ -174,14 +174,14 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("33", newPeriod) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, fmt.Sprintf("%d", 2540000), fs.Files[pwmDutyCyclePath].Contents) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - assert.Nil(t, a.DigitalWrite("7", 1)) + assert.NoError(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true @@ -193,7 +193,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) - assert.Nil(t, a.PwmWrite("33", 1)) + assert.NoError(t, a.PwmWrite("33", 1)) fs.WithWriteError = true @@ -221,11 +221,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-4"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 4) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index 88ace4597..859a324a5 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -78,7 +78,7 @@ func TestDigitalIO(t *testing.T) { ) assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestPWM(t *testing.T) { @@ -87,7 +87,7 @@ func TestPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" err := a.PwmWrite("32", 100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "0", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents) @@ -96,24 +96,24 @@ func TestPWM(t *testing.T) { assert.Equal(t, "normal", fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents) err = a.ServoWrite("32", 0) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) err = a.ServoWrite("32", 180) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "2000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) - assert.Nil(t, a.Finalize()) + assert.NoError(t, a.Finalize()) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - assert.Nil(t, a.DigitalWrite("7", 1)) + assert.NoError(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true @@ -126,7 +126,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" - assert.Nil(t, a.PwmWrite("32", 1)) + assert.NoError(t, a.PwmWrite("32", 1)) fs.WithWriteError = true @@ -184,11 +184,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-5"}) - assert.Nil(t, a.Connect()) + assert.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 5) - assert.Nil(t, err) + assert.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.Nil(t, err) + assert.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/robot_test.go b/robot_test.go index 5f7e69ced..dcf9df1cf 100644 --- a/robot_test.go +++ b/robot_test.go @@ -39,8 +39,8 @@ func TestRobotDevicesToJSON(t *testing.T) { func TestRobotStart(t *testing.T) { r := newTestRobot("Robot99") - assert.Nil(t, r.Start()) - assert.Nil(t, r.Stop()) + assert.NoError(t, r.Start()) + assert.NoError(t, r.Stop()) assert.False(t, r.Running()) } @@ -55,13 +55,13 @@ func TestRobotStartAutoRun(t *testing.T) { ) go func() { - assert.Nil(t, r.Start()) + assert.NoError(t, r.Start()) }() time.Sleep(10 * time.Millisecond) assert.True(t, r.Running()) // stop it - assert.Nil(t, r.Stop()) + assert.NoError(t, r.Stop()) assert.False(t, r.Running()) } diff --git a/system/digitalpin_gpiod_test.go b/system/digitalpin_gpiod_test.go index 04f8bdd61..6d591777c 100644 --- a/system/digitalpin_gpiod_test.go +++ b/system/digitalpin_gpiod_test.go @@ -259,7 +259,7 @@ func TestWrite(t *testing.T) { assert.Contains(t, err.Error(), want) } } else { - assert.Nil(t, err) + assert.NoError(t, err) } assert.Equal(t, tc.want, lm.lastVal) }) @@ -294,7 +294,7 @@ func TestRead(t *testing.T) { assert.Contains(t, err.Error(), want) } } else { - assert.Nil(t, err) + assert.NoError(t, err) } assert.Equal(t, got, tc.simVal) }) diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index 1c16c518b..1e031d8df 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -36,20 +36,20 @@ func TestDigitalPin(t *testing.T) { assert.Nil(t, pin.valFile) err := pin.Unexport() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "10", fs.Files["/sys/class/gpio/unexport"].Contents) err = pin.Export() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "10", fs.Files["/sys/class/gpio/export"].Contents) assert.NotNil(t, pin.valFile) err = pin.Write(1) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio10/value"].Contents) err = pin.ApplyOptions(WithPinDirectionInput()) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "in", fs.Files["/sys/class/gpio/gpio10/direction"].Contents) data, _ := pin.Read() @@ -68,7 +68,7 @@ func TestDigitalPin(t *testing.T) { } err = pin.Unexport() - assert.Nil(t, err) + assert.NoError(t, err) writeFile = func(File, []byte) (int, error) { return 0, &os.PathError{Err: errors.New("write error")} @@ -87,7 +87,7 @@ func TestDigitalPin(t *testing.T) { return 0, nil } err = pin.Export() - assert.Nil(t, err) + assert.NoError(t, err) // assert write error on export writeFile = func(File, []byte) (int, error) { diff --git a/system/fs_mock_test.go b/system/fs_mock_test.go index 35762890a..17296912d 100644 --- a/system/fs_mock_test.go +++ b/system/fs_mock_test.go @@ -14,10 +14,10 @@ func TestMockFilesystemOpen(t *testing.T) { assert.False(t, f1.Opened) f2, err := fs.openFile("foo", 0, 0o666) assert.Equal(t, f2, f1) - assert.Nil(t, err) + assert.NoError(t, err) err = f2.Sync() - assert.Nil(t, err) + assert.NoError(t, err) _, err = fs.openFile("bar", 0, 0o666) assert.ErrorContains(t, err, " : bar: no such file") @@ -31,11 +31,11 @@ func TestMockFilesystemStat(t *testing.T) { fs := newMockFilesystem([]string{"foo", "bar/baz"}) fileStat, err := fs.stat("foo") - assert.Nil(t, err) + assert.NoError(t, err) assert.False(t, fileStat.IsDir()) dirStat, err := fs.stat("bar") - assert.Nil(t, err) + assert.NoError(t, err) assert.True(t, dirStat.IsDir()) _, err = fs.stat("plonk") @@ -61,7 +61,7 @@ func TestMockFilesystemFind(t *testing.T) { // act dirs, err := fs.find(tt.baseDir, tt.pattern) // assert - assert.Nil(t, err) + assert.NoError(t, err) sort.Strings(dirs) assert.Equal(t, tt.want, dirs) }) @@ -73,7 +73,7 @@ func TestMockFilesystemWrite(t *testing.T) { f1 := fs.Files["bar"] f2, err := fs.openFile("bar", 0, 0o666) - assert.Nil(t, err) + assert.NoError(t, err) // Never been read or written. assert.True(t, f1.Seq <= 0) @@ -89,7 +89,7 @@ func TestMockFilesystemRead(t *testing.T) { f1.Contents = "Yip" f2, err := fs.openFile("bar", 0, 0o666) - assert.Nil(t, err) + assert.NoError(t, err) // Never been read or written. assert.True(t, f1.Seq <= 0) diff --git a/system/fs_test.go b/system/fs_test.go index b4e3a3152..ae7d79113 100644 --- a/system/fs_test.go +++ b/system/fs_test.go @@ -10,13 +10,13 @@ import ( func TestFilesystemOpen(t *testing.T) { fs := &nativeFilesystem{} file, err := fs.openFile(os.DevNull, os.O_RDONLY, 0o666) - assert.Nil(t, err) + assert.NoError(t, err) var _ File = file } func TestFilesystemStat(t *testing.T) { fs := &nativeFilesystem{} fileInfo, err := fs.stat(os.DevNull) - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, fileInfo) } diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index 4993a628c..061bf395f 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -83,7 +83,7 @@ func TestNewI2cDevice(t *testing.T) { assert.Equal(t, (*i2cDevice)(nil), d) } else { var _ gobot.I2cSystemDevicer = d - assert.Nil(t, err) + assert.NoError(t, err) } }) } @@ -93,7 +93,7 @@ func TestClose(t *testing.T) { // arrange d, _ := initTestI2cDeviceWithMockedSys() // act & assert - assert.Nil(t, d.Close()) + assert.NoError(t, d.Close()) } func TestWriteRead(t *testing.T) { @@ -105,8 +105,8 @@ func TestWriteRead(t *testing.T) { wn, werr := d.Write(1, wbuf) rn, rerr := d.Read(1, rbuf) // assert - assert.Nil(t, werr) - assert.Nil(t, rerr) + assert.NoError(t, werr) + assert.NoError(t, rerr) assert.Equal(t, len(wbuf), wn) assert.Equal(t, len(wbuf), rn) // will read only the written values assert.Equal(t, rbuf[:len(wbuf)], wbuf) @@ -144,7 +144,7 @@ func TestReadByte(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) @@ -191,7 +191,7 @@ func TestReadByteData(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) @@ -241,7 +241,7 @@ func TestReadWordData(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) @@ -299,7 +299,7 @@ func TestReadBlockData(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, msc.dataSlice, buf) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) @@ -343,7 +343,7 @@ func TestWriteByte(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) @@ -388,7 +388,7 @@ func TestWriteByteData(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) @@ -437,7 +437,7 @@ func TestWriteWordData(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) @@ -494,7 +494,7 @@ func TestWriteBlockData(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) assert.Equal(t, uint8(len(data)+1), msc.sliceSize) // including size element @@ -523,7 +523,7 @@ func Test_setAddress(t *testing.T) { // act err := d.setAddress(0xff) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, uintptr(0xff), msc.devAddress) } @@ -567,7 +567,7 @@ func Test_queryFunctionality(t *testing.T) { if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, err) + assert.NoError(t, err) } if tc.wantFile { assert.NotNil(t, d.file) diff --git a/system/pwmpin_sysfs_test.go b/system/pwmpin_sysfs_test.go index d5c9509fb..63f458935 100644 --- a/system/pwmpin_sysfs_test.go +++ b/system/pwmpin_sysfs_test.go @@ -35,25 +35,25 @@ func TestPwmPin(t *testing.T) { assert.Equal(t, "10", pin.pin) err := pin.Unexport() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "10", fs.Files["/sys/class/pwm/pwmchip0/unexport"].Contents) err = pin.Export() - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "10", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) - assert.Nil(t, pin.SetPolarity(false)) + assert.NoError(t, pin.SetPolarity(false)) assert.Equal(t, inverted, fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].Contents) pol, _ := pin.Polarity() assert.False(t, pol) - assert.Nil(t, pin.SetPolarity(true)) + assert.NoError(t, pin.SetPolarity(true)) assert.Equal(t, normal, fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].Contents) pol, _ = pin.Polarity() assert.True(t, pol) assert.NotEqual(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents) err = pin.SetEnabled(true) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents) err = pin.SetPolarity(true) assert.ErrorContains(t, err, "Cannot set PWM polarity when enabled") @@ -61,13 +61,13 @@ func TestPwmPin(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm10/period"].Contents = "6" data, _ := pin.Period() assert.Equal(t, uint32(6), data) - assert.Nil(t, pin.SetPeriod(100000)) + assert.NoError(t, pin.SetPeriod(100000)) data, _ = pin.Period() assert.Equal(t, uint32(100000), data) assert.NotEqual(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].Contents) err = pin.SetDutyCycle(100) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, "100", fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].Contents) data, _ = pin.DutyCycle() assert.Equal(t, uint32(100), data) @@ -88,7 +88,7 @@ func TestPwmPinAlreadyExported(t *testing.T) { } // no error indicates that the pin was already exported - assert.Nil(t, pin.Export()) + assert.NoError(t, pin.Export()) } func TestPwmPinExportError(t *testing.T) { diff --git a/system/system_test.go b/system/system_test.go index 2e4e26363..83f1c46df 100644 --- a/system/system_test.go +++ b/system/system_test.go @@ -34,7 +34,7 @@ func TestNewAccesser_NewSpiDevice(t *testing.T) { // act con, err := a.NewSpiDevice(busNum, chipNum, mode, bits, maxSpeed) // assert - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, con) assert.Equal(t, busNum, spi.busNum) assert.Equal(t, chipNum, spi.chipNum) From 1f09353831aea935627fd51e8feccc90430dff60 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Thu, 26 Oct 2023 20:41:41 +0200 Subject: [PATCH 14/57] system(gpio): add edge polling function (#1015) --- adaptor.go | 8 +- system/GPIO.md | 22 ++ system/digitalpin_config.go | 37 ++- system/digitalpin_config_test.go | 33 +++ system/digitalpin_gpiod.go | 15 +- system/digitalpin_gpiod_test.go | 8 +- system/digitalpin_poll.go | 81 +++++++ system/digitalpin_poll_test.go | 175 ++++++++++++++ system/digitalpin_sysfs.go | 65 ++++-- system/digitalpin_sysfs_test.go | 376 +++++++++++++++++++++++++++---- 10 files changed, 737 insertions(+), 83 deletions(-) create mode 100644 system/digitalpin_poll.go create mode 100644 system/digitalpin_poll_test.go diff --git a/adaptor.go b/adaptor.go index 596332642..81c6919a4 100644 --- a/adaptor.go +++ b/adaptor.go @@ -21,12 +21,18 @@ type DigitalPinOptioner interface { SetDrive(drive int) (changed bool) // SetDebounce initializes the input pin with the given debounce period. SetDebounce(period time.Duration) (changed bool) - // SetEventHandlerForEdge initializes the input pin for edge detection and to call the event handler on specified edge. + // SetEventHandlerForEdge initializes the input pin for edge detection to call the event handler on specified edge. // lineOffset is within the GPIO chip (needs to transformed to the pin id), timestamp is the detection time, // detectedEdge contains the direction of the pin changes, seqno is the sequence number for this event in the sequence // of events for all the lines in this line request, lseqno is the same but for this line SetEventHandlerForEdge(handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, lseqno uint32), edge int) (changed bool) + // SetPollForEdgeDetection use a discrete input polling method to detect edges. A poll interval of zero or smaller + // will deactivate this function. Please note: Using this feature is CPU consuming and less accurate than using cdev + // event handler (gpiod implementation) and should be done only if the former is not implemented or not working for + // the adaptor. E.g. sysfs driver in gobot has not implemented edge detection yet. The function is only useful + // together with SetEventHandlerForEdge() and its corresponding With*() functions. + SetPollForEdgeDetection(pollInterval time.Duration, pollQuitChan chan struct{}) (changed bool) } // DigitalPinOptionApplier is the interface to apply options to change pin behavior immediately diff --git a/system/GPIO.md b/system/GPIO.md index ee9586c0c..e2a4fae1c 100644 --- a/system/GPIO.md +++ b/system/GPIO.md @@ -142,6 +142,28 @@ Connect the input header pin26 to +3.3V with an resistor (e.g. 1kOhm). 1 ``` +### Test edge detection behavior of gpio251 (sysfs Tinkerboard) + +investigate status: + +```sh +# cat /sys/class/gpio/gpio251/edge +none +``` + +The file exists only if the pin can be configured as an interrupt generating input pin. To activate edge detection, +"rising", "falling", or "both" needs to be set. + +```sh +# cat /sys/class/gpio/gpio251/value +1 +``` + +If edge detection is activated, a poll will return only when the interrupt was triggered. The new value is written to +the beginning of the file. + +> Not tested yet, not supported by gobot yet. + ### Test output behavior of gpio251 (sysfs Tinkerboard) Connect the output header pin26 to +3.3V with an resistor (e.g. 1kOhm leads to ~0.3mA, 300Ohm leads to ~10mA). diff --git a/system/digitalpin_config.go b/system/digitalpin_config.go index 26d8bafaf..76e880283 100644 --- a/system/digitalpin_config.go +++ b/system/digitalpin_config.go @@ -53,6 +53,8 @@ type digitalPinConfig struct { debouncePeriod time.Duration edge int edgeEventHandler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, lseqno uint32) + pollInterval time.Duration + pollQuitChan chan struct{} } func newDigitalPinConfig(label string, options ...func(gobot.DigitalPinOptioner) bool) *digitalPinConfig { @@ -140,6 +142,16 @@ func WithPinEventOnBothEdges(handler func(lineOffset int, timestamp time.Duratio } } +// WithPinPollForEdgeDetection initializes a discrete input pin polling function to use for edge detection. +func WithPinPollForEdgeDetection( + pollInterval time.Duration, + pollQuitChan chan struct{}, +) func(gobot.DigitalPinOptioner) bool { + return func(d gobot.DigitalPinOptioner) bool { + return d.SetPollForEdgeDetection(pollInterval, pollQuitChan) + } +} + // SetLabel sets the label to use for next reconfigure. The function is intended to use by WithPinLabel(). func (d *digitalPinConfig) SetLabel(label string) bool { if d.label == label { @@ -211,9 +223,12 @@ func (d *digitalPinConfig) SetDebounce(period time.Duration) bool { return true } -// SetEventHandlerForEdge sets the input pin to edge detection and to call the event handler on specified edge. The +// SetEventHandlerForEdge sets the input pin to edge detection to call the event handler on specified edge. The // function is intended to use by WithPinEventOnFallingEdge(), WithPinEventOnRisingEdge() and WithPinEventOnBothEdges(). -func (d *digitalPinConfig) SetEventHandlerForEdge(handler func(int, time.Duration, string, uint32, uint32), edge int) bool { +func (d *digitalPinConfig) SetEventHandlerForEdge( + handler func(int, time.Duration, string, uint32, uint32), + edge int, +) bool { if d.edge == edge { return false } @@ -221,3 +236,21 @@ func (d *digitalPinConfig) SetEventHandlerForEdge(handler func(int, time.Duratio d.edgeEventHandler = handler return true } + +// SetPollForEdgeDetection use a discrete input polling method to detect edges. A poll interval of zero or smaller +// will deactivate this function. Please note: Using this feature is CPU consuming and less accurate than using cdev +// event handler (gpiod implementation) and should be done only if the former is not implemented or not working for +// the adaptor. E.g. sysfs driver in gobot has not implemented edge detection yet. The function is only useful +// together with SetEventHandlerForEdge() and its corresponding With*() functions. +// The function is intended to use by WithPinPollForEdgeDetection(). +func (d *digitalPinConfig) SetPollForEdgeDetection( + pollInterval time.Duration, + pollQuitChan chan struct{}, +) (changed bool) { + if d.pollInterval == pollInterval { + return false + } + d.pollInterval = pollInterval + d.pollQuitChan = pollQuitChan + return true +} diff --git a/system/digitalpin_config_test.go b/system/digitalpin_config_test.go index be73c5190..c14d6fb5b 100644 --- a/system/digitalpin_config_test.go +++ b/system/digitalpin_config_test.go @@ -413,3 +413,36 @@ func TestWithPinEventOnBothEdges(t *testing.T) { }) } } + +func TestWithPinPollForEdgeDetection(t *testing.T) { + const ( + oldVal = time.Duration(1) + newVal = time.Duration(3) + ) + tests := map[string]struct { + oldPollInterval time.Duration + want bool + wantVal time.Duration + }{ + "no_change": { + oldPollInterval: newVal, + }, + "change": { + oldPollInterval: oldVal, + want: true, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + dpc := &digitalPinConfig{pollInterval: tc.oldPollInterval} + stopChan := make(chan struct{}) + defer close(stopChan) + // act + got := WithPinPollForEdgeDetection(newVal, stopChan)(dpc) + // assert + assert.Equal(t, tc.want, got) + assert.Equal(t, newVal, dpc.pollInterval) + }) + } +} diff --git a/system/digitalpin_gpiod.go b/system/digitalpin_gpiod.go index df913cad1..c161dc00f 100644 --- a/system/digitalpin_gpiod.go +++ b/system/digitalpin_gpiod.go @@ -215,7 +215,8 @@ func digitalPinGpiodReconfigureLine(d *digitalPinGpiod, forceInput bool) error { opts = append(opts, gpiod.WithDebounce(d.debouncePeriod)) } // edge detection - if d.edgeEventHandler != nil { + if d.edgeEventHandler != nil && d.pollInterval <= 0 { + // use edge detection provided by gpiod wrappedHandler := digitalPinGpiodGetWrappedEventHandler(d.edgeEventHandler) switch d.edge { case digitalPinEventOnFallingEdge: @@ -277,10 +278,20 @@ func digitalPinGpiodReconfigureLine(d *digitalPinGpiod, forceInput bool) error { } d.line = gpiodLine + // start discrete polling function and wait for first read is done + if (d.direction == IN || forceInput) && d.pollInterval > 0 { + if err := startEdgePolling(d.label, d.Read, d.pollInterval, d.edge, d.edgeEventHandler, + d.pollQuitChan); err != nil { + return err + } + } + return nil } -func digitalPinGpiodGetWrappedEventHandler(handler func(int, time.Duration, string, uint32, uint32)) func(gpiod.LineEvent) { +func digitalPinGpiodGetWrappedEventHandler( + handler func(int, time.Duration, string, uint32, uint32), +) func(gpiod.LineEvent) { return func(evt gpiod.LineEvent) { detectedEdge := "none" switch evt.Type { diff --git a/system/digitalpin_gpiod_test.go b/system/digitalpin_gpiod_test.go index 6d591777c..30d7ba823 100644 --- a/system/digitalpin_gpiod_test.go +++ b/system/digitalpin_gpiod_test.go @@ -114,7 +114,7 @@ func TestApplyOptions(t *testing.T) { } } -func TestExport(t *testing.T) { +func TestExportGpiod(t *testing.T) { tests := map[string]struct { simErr error wantReconfigured int @@ -155,7 +155,7 @@ func TestExport(t *testing.T) { } } -func TestUnexport(t *testing.T) { +func TestUnexportGpiod(t *testing.T) { tests := map[string]struct { simNoLine bool simReconfErr error @@ -217,7 +217,7 @@ func TestUnexport(t *testing.T) { } } -func TestWrite(t *testing.T) { +func TestWriteGpiod(t *testing.T) { tests := map[string]struct { val int simErr error @@ -266,7 +266,7 @@ func TestWrite(t *testing.T) { } } -func TestRead(t *testing.T) { +func TestReadGpiod(t *testing.T) { tests := map[string]struct { simVal int simErr error diff --git a/system/digitalpin_poll.go b/system/digitalpin_poll.go new file mode 100644 index 000000000..6526acfee --- /dev/null +++ b/system/digitalpin_poll.go @@ -0,0 +1,81 @@ +package system + +import ( + "fmt" + "sync" + "time" +) + +func startEdgePolling( + pinLabel string, + pinReadFunc func() (int, error), + pollInterval time.Duration, + wantedEdge int, + eventHandler func(offset int, t time.Duration, et string, sn uint32, lsn uint32), + quitChan chan struct{}, +) error { + if eventHandler == nil { + return fmt.Errorf("an event handler is mandatory for edge polling") + } + if quitChan == nil { + return fmt.Errorf("the quit channel is mandatory for edge polling") + } + + const allEdges = "all" + + triggerEventOn := "none" + switch wantedEdge { + case digitalPinEventOnFallingEdge: + triggerEventOn = DigitalPinEventFallingEdge + case digitalPinEventOnRisingEdge: + triggerEventOn = DigitalPinEventRisingEdge + case digitalPinEventOnBothEdges: + triggerEventOn = allEdges + default: + return fmt.Errorf("unsupported edge type %d for edge polling", wantedEdge) + } + + wg := sync.WaitGroup{} + wg.Add(1) + + go func() { + var oldState int + var readStart time.Time + var firstLoopDone bool + for { + select { + case <-quitChan: + return + default: + // note: pure reading takes between 30us and 1ms on rasperry Pi1, typically 50us, with sysfs also 500us + // can happen, so we use the time stamp before start of reading to reduce random duration offset + readStart = time.Now() + readValue, err := pinReadFunc() + if err != nil { + fmt.Printf("edge polling error occurred while reading the pin %s: %v", pinLabel, err) + readValue = oldState // keep the value + } + if readValue != oldState { + detectedEdge := DigitalPinEventRisingEdge + if readValue < oldState { + detectedEdge = DigitalPinEventFallingEdge + } + if firstLoopDone && (triggerEventOn == allEdges || triggerEventOn == detectedEdge) { + eventHandler(0, time.Duration(readStart.UnixNano()), detectedEdge, 0, 0) + } + oldState = readValue + } + // the real poll interval is increased by the reading time, see also note above + // negative or zero duration causes no sleep + time.Sleep(pollInterval - time.Since(readStart)) + if !firstLoopDone { + wg.Done() + firstLoopDone = true + } + } + } + }() + + wg.Wait() + return nil +} diff --git a/system/digitalpin_poll_test.go b/system/digitalpin_poll_test.go new file mode 100644 index 000000000..c9a9fd3d1 --- /dev/null +++ b/system/digitalpin_poll_test.go @@ -0,0 +1,175 @@ +package system + +import ( + "fmt" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func Test_startEdgePolling(t *testing.T) { + type readValue struct { + value int + err string + } + tests := map[string]struct { + eventOnEdge int + simulateReadValues []readValue + simulateNoEventHandler bool + simulateNoQuitChan bool + wantEdgeTypes []string + wantErr string + }{ + "edge_falling": { + eventOnEdge: digitalPinEventOnFallingEdge, + simulateReadValues: []readValue{ + {value: 1}, + {value: 0}, + {value: 1}, + {value: 0}, + {value: 0}, + }, + wantEdgeTypes: []string{DigitalPinEventFallingEdge, DigitalPinEventFallingEdge}, + }, + "no_edge_falling": { + eventOnEdge: digitalPinEventOnFallingEdge, + simulateReadValues: []readValue{ + {value: 0}, + {value: 1}, + {value: 1}, + }, + wantEdgeTypes: nil, + }, + "edge_rising": { + eventOnEdge: digitalPinEventOnRisingEdge, + simulateReadValues: []readValue{ + {value: 0}, + {value: 1}, + {value: 0}, + {value: 1}, + {value: 1}, + }, + wantEdgeTypes: []string{DigitalPinEventRisingEdge, DigitalPinEventRisingEdge}, + }, + "no_edge_rising": { + eventOnEdge: digitalPinEventOnRisingEdge, + simulateReadValues: []readValue{ + {value: 1}, + {value: 0}, + {value: 0}, + }, + wantEdgeTypes: nil, + }, + "edge_both": { + eventOnEdge: digitalPinEventOnBothEdges, + simulateReadValues: []readValue{ + {value: 0}, + {value: 1}, + {value: 0}, + {value: 1}, + {value: 1}, + }, + wantEdgeTypes: []string{DigitalPinEventRisingEdge, DigitalPinEventFallingEdge, DigitalPinEventRisingEdge}, + }, + "no_edges_low": { + eventOnEdge: digitalPinEventOnBothEdges, + simulateReadValues: []readValue{ + {value: 0}, + {value: 0}, + {value: 0}, + }, + wantEdgeTypes: nil, + }, + "no_edges_high": { + eventOnEdge: digitalPinEventOnBothEdges, + simulateReadValues: []readValue{ + {value: 1}, + {value: 1}, + {value: 1}, + }, + wantEdgeTypes: nil, + }, + "read_error_keep_state": { + eventOnEdge: digitalPinEventOnBothEdges, + simulateReadValues: []readValue{ + {value: 0}, + {value: 1, err: "read error suppress rising and falling edge"}, + {value: 0}, + {value: 1}, + {value: 1}, + }, + wantEdgeTypes: []string{DigitalPinEventRisingEdge}, + }, + "error_no_eventhandler": { + simulateNoEventHandler: true, + wantErr: "event handler is mandatory", + }, + "error_no_quitchannel": { + simulateNoQuitChan: true, + wantErr: "quit channel is mandatory", + }, + "error_unsupported_edgetype_none": { + eventOnEdge: digitalPinEventNone, + wantErr: "unsupported edge type 0", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + pinLabel := "test_pin" + pollInterval := time.Microsecond // zero is possible, just to show usage + // arrange event handler + var edgeTypes []string + var eventHandler func(int, time.Duration, string, uint32, uint32) + if !tc.simulateNoEventHandler { + eventHandler = func(offset int, t time.Duration, et string, sn uint32, lsn uint32) { + edgeTypes = append(edgeTypes, et) + } + } + // arrange quit channel + var quitChan chan struct{} + if !tc.simulateNoQuitChan { + quitChan = make(chan struct{}) + } + defer func() { + if quitChan != nil { + close(quitChan) + } + }() + // arrange reads + numCallsRead := 0 + wg := sync.WaitGroup{} + if tc.simulateReadValues != nil { + wg.Add(1) + } + readFunc := func() (int, error) { + numCallsRead++ + readVal := tc.simulateReadValues[numCallsRead-1] + var err error + if readVal.err != "" { + err = fmt.Errorf(readVal.err) + } + if numCallsRead >= len(tc.simulateReadValues) { + close(quitChan) // ensure no further read call + quitChan = nil // lets skip defer routine + wg.Done() // release assertions + } + + return readVal.value, err + } + // act + err := startEdgePolling(pinLabel, readFunc, pollInterval, tc.eventOnEdge, eventHandler, quitChan) + wg.Wait() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, len(tc.simulateReadValues), numCallsRead) + assert.Equal(t, tc.wantEdgeTypes, edgeTypes) + }) + } +} diff --git a/system/digitalpin_sysfs.go b/system/digitalpin_sysfs.go index f29a4157e..7829befe4 100644 --- a/system/digitalpin_sysfs.go +++ b/system/digitalpin_sysfs.go @@ -47,7 +47,7 @@ func newDigitalPinSysfs(fs filesystem, pin string, options ...func(gobot.Digital func (d *digitalPinSysfs) ApplyOptions(options ...func(gobot.DigitalPinOptioner) bool) error { anyChange := false for _, option := range options { - anyChange = anyChange || option(d) + anyChange = option(d) || anyChange } if anyChange { return d.reconfigure() @@ -87,7 +87,7 @@ func (d *digitalPinSysfs) Unexport() error { d.activeLowFile = nil } - _, err = writeFile(unexport, []byte(d.pin)) + err = writeFile(unexport, []byte(d.pin)) if err != nil { // If EINVAL then the pin is reserved in the system and can't be unexported e, ok := err.(*os.PathError) @@ -101,7 +101,7 @@ func (d *digitalPinSysfs) Unexport() error { // Write writes the given value to the character device func (d *digitalPinSysfs) Write(b int) error { - _, err := writeFile(d.valFile, []byte(strconv.Itoa(b))) + err := writeFile(d.valFile, []byte(strconv.Itoa(b))) return err } @@ -121,7 +121,7 @@ func (d *digitalPinSysfs) reconfigure() error { } defer exportFile.Close() - _, err = writeFile(exportFile, []byte(d.pin)) + err = writeFile(exportFile, []byte(d.pin)) if err != nil { // If EBUSY then the pin has already been exported e, ok := err.(*os.PathError) @@ -142,7 +142,7 @@ func (d *digitalPinSysfs) reconfigure() error { break } if attempt > 10 { - return err + break } time.Sleep(10 * time.Millisecond) } @@ -164,45 +164,59 @@ func (d *digitalPinSysfs) reconfigure() error { if d.activeLow { d.activeLowFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/active_low", gpioPath, d.label), os.O_RDWR, 0o644) if err == nil { - _, err = writeFile(d.activeLowFile, []byte("1")) + err = writeFile(d.activeLowFile, []byte("1")) } } } - // configure bias (unsupported) + // configure bias (inputs and outputs, unsupported) if err == nil { if d.bias != digitalPinBiasDefault && systemSysfsDebug { log.Printf("bias options (%d) are not supported by sysfs, please use hardware resistors instead\n", d.bias) } } - // configure drive (unsupported) - if d.drive != digitalPinDrivePushPull && systemSysfsDebug { - log.Printf("drive options (%d) are not supported by sysfs\n", d.drive) - } + // configure debounce period (inputs only), edge detection (inputs only) and drive (outputs only) + if d.direction == IN { + // configure debounce (unsupported) + if d.debouncePeriod != 0 && systemSysfsDebug { + log.Printf("debounce period option (%d) is not supported by sysfs\n", d.debouncePeriod) + } - // configure debounce (unsupported) - if d.debouncePeriod != 0 && systemSysfsDebug { - log.Printf("debounce period option (%d) is not supported by sysfs\n", d.debouncePeriod) - } + // configure edge detection + if err == nil { + if d.edge != 0 && d.pollInterval <= 0 { + err = fmt.Errorf("edge detect option (%d) is not implemented for sysfs without discrete polling", d.edge) + } + } - // configure edge detection (not implemented) - if d.edge != 0 && systemSysfsDebug { - log.Printf("edge detect option (%d) is not implemented for sysfs\n", d.edge) + // start discrete polling function and wait for first read is done + if err == nil { + if d.pollInterval > 0 { + err = startEdgePolling(d.label, d.Read, d.pollInterval, d.edge, d.edgeEventHandler, d.pollQuitChan) + } + } + } else { + // configure drive (unsupported) + if d.drive != digitalPinDrivePushPull && systemSysfsDebug { + log.Printf("drive options (%d) are not supported by sysfs\n", d.drive) + } } if err != nil { - return d.Unexport() + if e := d.Unexport(); e != nil { + err = fmt.Errorf("unexport error '%v' after '%v'", e, err) + } } return err } func (d *digitalPinSysfs) writeDirectionWithInitialOutput() error { - if _, err := writeFile(d.dirFile, []byte(d.direction)); err != nil || d.direction == IN { + if err := writeFile(d.dirFile, []byte(d.direction)); err != nil || d.direction == IN { return err } - _, err := writeFile(d.valFile, []byte(strconv.Itoa(d.outInitialState))) + err := writeFile(d.valFile, []byte(strconv.Itoa(d.outInitialState))) return err } @@ -210,9 +224,9 @@ func (d *digitalPinSysfs) writeDirectionWithInitialOutput() error { // https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt // https://www.kernel.org/doc/Documentation/gpio/sysfs.txt -var writeFile = func(f File, data []byte) (i int, err error) { +var writeFile = func(f File, data []byte) error { if f == nil { - return 0, errNotExported + return errNotExported } // sysfs docs say: @@ -221,8 +235,9 @@ var writeFile = func(f File, data []byte) (i int, err error) { // > entire buffer back. // however, this seems outdated/inaccurate (docs are from back in the Kernel BitKeeper days). - i, err = f.Write(data) - return i, err + // Write() returns already a non-nil error when n != len(b). + _, err := f.Write(data) + return err } var readFile = func(f File) ([]byte, error) { diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index 1e031d8df..04b025ecd 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -4,8 +4,10 @@ import ( "errors" "os" "testing" + "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -16,20 +18,333 @@ var ( _ gobot.DigitalPinOptionApplier = (*digitalPinSysfs)(nil) ) -func initTestDigitalPinSysFsWithMockedFilesystem(mockPaths []string) (*digitalPinSysfs, *MockFilesystem) { +func initTestDigitalPinSysfsWithMockedFilesystem(mockPaths []string) (*digitalPinSysfs, *MockFilesystem) { fs := newMockFilesystem(mockPaths) pin := newDigitalPinSysfs(fs, "10") return pin, fs } -func TestDigitalPin(t *testing.T) { +func Test_newDigitalPinSysfs(t *testing.T) { + // arrange + m := &MockFilesystem{} + const pinID = "1" + // act + pin := newDigitalPinSysfs(m, pinID, WithPinOpenDrain()) + // assert + assert.Equal(t, pinID, pin.pin) + assert.Equal(t, m, pin.fs) + assert.Equal(t, "gpio"+pinID, pin.label) + assert.Equal(t, "in", pin.direction) + assert.Equal(t, 1, pin.drive) +} + +func TestApplyOptionsSysfs(t *testing.T) { + tests := map[string]struct { + changed []bool + simErr bool + wantExport string + wantErr string + }{ + "both_changed": { + changed: []bool{true, true}, + wantExport: "10", + }, + "first_changed": { + changed: []bool{true, false}, + wantExport: "10", + }, + "second_changed": { + changed: []bool{false, true}, + wantExport: "10", + }, + "none_changed": { + changed: []bool{false, false}, + wantExport: "", + }, + "error_on_change": { + changed: []bool{false, true}, + simErr: true, + wantExport: "10", + wantErr: "gpio10/direction: no such file", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + mockPaths := []string{ + "/sys/class/gpio/export", + "/sys/class/gpio/gpio10/value", + } + if !tc.simErr { + mockPaths = append(mockPaths, "/sys/class/gpio/gpio10/direction") + } + pin, fs := initTestDigitalPinSysfsWithMockedFilesystem(mockPaths) + + optionFunction1 := func(gobot.DigitalPinOptioner) bool { + pin.digitalPinConfig.direction = OUT + return tc.changed[0] + } + optionFunction2 := func(gobot.DigitalPinOptioner) bool { + pin.digitalPinConfig.drive = 15 + return tc.changed[1] + } + // act + err := pin.ApplyOptions(optionFunction1, optionFunction2) + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, OUT, pin.digitalPinConfig.direction) + assert.Equal(t, 15, pin.digitalPinConfig.drive) + // marker for call of reconfigure, correct reconfigure is tested independently + assert.Equal(t, tc.wantExport, fs.Files["/sys/class/gpio/export"].Contents) + }) + } +} + +func TestDirectionBehaviorSysfs(t *testing.T) { + // arrange + pin := newDigitalPinSysfs(nil, "1") + require.Equal(t, "in", pin.direction) + pin.direction = "test" + // act && assert + assert.Equal(t, "test", pin.DirectionBehavior()) +} + +func TestDigitalPinExportSysfs(t *testing.T) { + // this tests mainly the function reconfigure() + const ( + exportPath = "/sys/class/gpio/export" + dirPath = "/sys/class/gpio/gpio10/direction" + valuePath = "/sys/class/gpio/gpio10/value" + inversePath = "/sys/class/gpio/gpio10/active_low" + unexportPath = "/sys/class/gpio/unexport" + ) + allMockPaths := []string{exportPath, dirPath, valuePath, inversePath, unexportPath} + tests := map[string]struct { + mockPaths []string + changeDirection string + changeOutInitialState int + changeActiveLow bool + changeBias int + changeDrive int + changeDebouncePeriod time.Duration + changeEdge int + changePollInterval time.Duration + simEbusyOnWrite int + wantWrites int + wantExport string + wantUnexport string + wantDirection string + wantValue string + wantInverse string + wantErr string + }{ + "ok_without_option": { + mockPaths: allMockPaths, + wantWrites: 2, + wantExport: "10", + wantDirection: "in", + }, + "ok_input_bias_dropped": { + mockPaths: allMockPaths, + changeBias: 3, + wantWrites: 2, + wantExport: "10", + wantDirection: "in", + }, + "ok_input_drive_dropped": { + mockPaths: allMockPaths, + changeDrive: 2, + wantWrites: 2, + wantExport: "10", + wantDirection: "in", + }, + "ok_input_debounce_dropped": { + mockPaths: allMockPaths, + changeDebouncePeriod: 2 * time.Second, + wantWrites: 2, + wantExport: "10", + wantDirection: "in", + }, + "ok_input_inverse": { + mockPaths: allMockPaths, + changeActiveLow: true, + wantWrites: 3, + wantExport: "10", + wantDirection: "in", + wantInverse: "1", + }, + "ok_output": { + mockPaths: allMockPaths, + changeDirection: "out", + changeOutInitialState: 4, + wantWrites: 3, + wantExport: "10", + wantDirection: "out", + wantValue: "4", + }, + "ok_output_bias_dropped": { + mockPaths: allMockPaths, + changeDirection: "out", + changeBias: 3, + wantWrites: 3, + wantExport: "10", + wantDirection: "out", + wantValue: "0", + }, + "ok_output_drive_dropped": { + mockPaths: allMockPaths, + changeDirection: "out", + changeDrive: 2, + wantWrites: 3, + wantExport: "10", + wantDirection: "out", + wantValue: "0", + }, + "ok_output_debounce_dropped": { + mockPaths: allMockPaths, + changeDirection: "out", + changeDebouncePeriod: 2 * time.Second, + wantWrites: 3, + wantExport: "10", + wantDirection: "out", + wantValue: "0", + }, + "ok_output_inverse": { + mockPaths: allMockPaths, + changeDirection: "out", + changeActiveLow: true, + wantWrites: 4, + wantExport: "10", + wantDirection: "out", + wantInverse: "1", + wantValue: "0", + }, + "ok_already_exported": { + mockPaths: allMockPaths, + wantWrites: 2, + wantExport: "10", + wantDirection: "in", + simEbusyOnWrite: 1, // just means "already exported" + }, + "error_no_eventhandler_for_polling": { // this only tests the call of function, all other is tested separately + mockPaths: allMockPaths, + changePollInterval: 3 * time.Second, + wantWrites: 3, + wantUnexport: "10", + wantDirection: "in", + wantErr: "event handler is mandatory", + }, + "error_no_export_file": { + mockPaths: []string{unexportPath}, + wantErr: "/export: no such file", + }, + "error_no_direction_file": { + mockPaths: []string{exportPath, unexportPath}, + wantWrites: 2, + wantUnexport: "10", + wantErr: "gpio10/direction: no such file", + }, + "error_write_direction_file": { + mockPaths: allMockPaths, + wantWrites: 3, + wantUnexport: "10", + simEbusyOnWrite: 2, + wantErr: "device or resource busy", + }, + "error_no_value_file": { + mockPaths: []string{exportPath, dirPath, unexportPath}, + wantWrites: 2, + wantUnexport: "10", + wantErr: "gpio10/value: no such file", + }, + "error_no_inverse_file": { + mockPaths: []string{exportPath, dirPath, valuePath, unexportPath}, + changeActiveLow: true, + wantWrites: 3, + wantUnexport: "10", + wantErr: "gpio10/active_low: no such file", + }, + "error_input_edge_without_poll": { + mockPaths: allMockPaths, + changeEdge: 2, + wantWrites: 3, + wantUnexport: "10", + wantErr: "not implemented for sysfs without discrete polling", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + fs := newMockFilesystem(tc.mockPaths) + pin := newDigitalPinSysfs(fs, "10") + if tc.changeDirection != "" { + pin.direction = tc.changeDirection + } + if tc.changeOutInitialState != 0 { + pin.outInitialState = tc.changeOutInitialState + } + if tc.changeActiveLow { + pin.activeLow = tc.changeActiveLow + } + if tc.changeBias != 0 { + pin.bias = tc.changeBias + } + if tc.changeDrive != 0 { + pin.drive = tc.changeDrive + } + if tc.changeDebouncePeriod != 0 { + pin.debouncePeriod = tc.changeDebouncePeriod + } + if tc.changeEdge != 0 { + pin.edge = tc.changeEdge + } + if tc.changePollInterval != 0 { + pin.pollInterval = tc.changePollInterval + } + // arrange write function + oldWriteFunc := writeFile + numCallsWrite := 0 + writeFile = func(f File, data []byte) error { + numCallsWrite++ + require.NoError(t, oldWriteFunc(f, data)) + if numCallsWrite == tc.simEbusyOnWrite { + return &os.PathError{Err: Syscall_EBUSY} + } + return nil + } + defer func() { writeFile = oldWriteFunc }() + // act + err := pin.Export() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + assert.NotNil(t, pin.valFile) + assert.NotNil(t, pin.dirFile) + assert.Equal(t, tc.wantDirection, fs.Files[dirPath].Contents) + assert.Equal(t, tc.wantExport, fs.Files[exportPath].Contents) + assert.Equal(t, tc.wantValue, fs.Files[valuePath].Contents) + assert.Equal(t, tc.wantInverse, fs.Files[inversePath].Contents) + } + assert.Equal(t, tc.wantUnexport, fs.Files[unexportPath].Contents) + assert.Equal(t, tc.wantWrites, numCallsWrite) + }) + } +} + +func TestDigitalPinSysfs(t *testing.T) { mockPaths := []string{ "/sys/class/gpio/export", "/sys/class/gpio/unexport", "/sys/class/gpio/gpio10/value", "/sys/class/gpio/gpio10/direction", } - pin, fs := initTestDigitalPinSysFsWithMockedFilesystem(mockPaths) + pin, fs := initTestDigitalPinSysfsWithMockedFilesystem(mockPaths) assert.Equal(t, "10", pin.pin) assert.Equal(t, "gpio10", pin.label) @@ -39,10 +354,7 @@ func TestDigitalPin(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "10", fs.Files["/sys/class/gpio/unexport"].Contents) - err = pin.Export() - assert.NoError(t, err) - assert.Equal(t, "10", fs.Files["/sys/class/gpio/export"].Contents) - assert.NotNil(t, pin.valFile) + require.NoError(t, pin.Export()) err = pin.Write(1) assert.NoError(t, err) @@ -63,63 +375,29 @@ func TestDigitalPin(t *testing.T) { assert.ErrorContains(t, err, "pin has not been exported") assert.Equal(t, 0, data) - writeFile = func(File, []byte) (int, error) { - return 0, &os.PathError{Err: Syscall_EINVAL} + writeFile = func(File, []byte) error { + return &os.PathError{Err: Syscall_EINVAL} } err = pin.Unexport() assert.NoError(t, err) - writeFile = func(File, []byte) (int, error) { - return 0, &os.PathError{Err: errors.New("write error")} + writeFile = func(File, []byte) error { + return &os.PathError{Err: errors.New("write error")} } err = pin.Unexport() assert.ErrorContains(t, err.(*os.PathError).Err, "write error") - - // assert a busy error is dropped (just means "already exported") - cnt := 0 - writeFile = func(File, []byte) (int, error) { - cnt++ - if cnt == 1 { - return 0, &os.PathError{Err: Syscall_EBUSY} - } - return 0, nil - } - err = pin.Export() - assert.NoError(t, err) - - // assert write error on export - writeFile = func(File, []byte) (int, error) { - return 0, &os.PathError{Err: errors.New("write error")} - } - err = pin.Export() - assert.ErrorContains(t, err.(*os.PathError).Err, "write error") -} - -func TestDigitalPinExportError(t *testing.T) { - mockPaths := []string{ - "/sys/class/gpio/export", - "/sys/class/gpio/gpio11/direction", - } - pin, _ := initTestDigitalPinSysFsWithMockedFilesystem(mockPaths) - - writeFile = func(File, []byte) (int, error) { - return 0, &os.PathError{Err: Syscall_EBUSY} - } - - err := pin.Export() - assert.ErrorContains(t, err, " : /sys/class/gpio/gpio10/direction: no such file") } -func TestDigitalPinUnexportError(t *testing.T) { +func TestDigitalPinUnexportErrorSysfs(t *testing.T) { mockPaths := []string{ "/sys/class/gpio/unexport", } - pin, _ := initTestDigitalPinSysFsWithMockedFilesystem(mockPaths) + pin, _ := initTestDigitalPinSysfsWithMockedFilesystem(mockPaths) - writeFile = func(File, []byte) (int, error) { - return 0, &os.PathError{Err: Syscall_EBUSY} + writeFile = func(File, []byte) error { + return &os.PathError{Err: Syscall_EBUSY} } err := pin.Unexport() From f7f482010b25f00afd7a76b2428afd7944bb349a Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Fri, 27 Oct 2023 20:46:45 +0200 Subject: [PATCH 15/57] tests(gpio,aio): cleanup helper_test (#1018) --- drivers/aio/analog_sensor_driver_test.go | 25 +++-- drivers/aio/grove_drivers_test.go | 7 +- .../grove_temperature_sensor_driver_test.go | 8 +- drivers/aio/helpers_test.go | 51 ++++----- drivers/aio/temperature_sensor_driver_test.go | 16 +-- drivers/gpio/button_driver_test.go | 24 ++-- drivers/gpio/buzzer_driver_test.go | 12 +- drivers/gpio/direct_pin_driver_test.go | 8 +- drivers/gpio/grove_drivers_test.go | 4 +- drivers/gpio/hd44780_driver_test.go | 4 +- drivers/gpio/helpers_test.go | 104 ++++++------------ drivers/gpio/led_driver_test.go | 10 +- drivers/gpio/makey_button_driver_test.go | 16 +-- drivers/gpio/pir_motion_driver_test.go | 12 +- drivers/gpio/relay_driver_test.go | 20 ++-- drivers/gpio/rgb_led_driver_test.go | 10 +- drivers/gpio/servo_driver_test.go | 2 +- drivers/spi/ssd1306_driver_test.go | 30 ++--- 18 files changed, 162 insertions(+), 201 deletions(-) diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index 0ed0ddc85..3b60eb209 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -27,10 +27,11 @@ func TestAnalogSensorDriver(t *testing.T) { assert.Equal(t, "42", d.Pin()) assert.Equal(t, 30*time.Second, d.interval) - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = 100 return - }) + } + ret := d.Command("ReadRaw")(nil).(map[string]interface{}) assert.Equal(t, 100, ret["val"].(int)) assert.Nil(t, ret["err"]) @@ -42,10 +43,10 @@ func TestAnalogSensorDriver(t *testing.T) { // refresh value on read a = newAioTestAdaptor() d = NewAnalogSensorDriver(a, "3") - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = 150 return - }) + } assert.Equal(t, 0.0, d.Value()) val, err := d.Read() assert.NoError(t, err) @@ -78,9 +79,9 @@ func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange d.SetScaler(AnalogSensorLinearScaler(0, 255, tt.toMin, tt.toMax)) - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { return tt.input, nil - }) + } // act got, err := d.Read() // assert @@ -108,10 +109,10 @@ func TestAnalogSensorDriverStart(t *testing.T) { }) // send data - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = 100 return - }) + } assert.NoError(t, d.Start()) @@ -128,10 +129,10 @@ func TestAnalogSensorDriverStart(t *testing.T) { }) // send error - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { err = errors.New("read error") return - }) + } select { case <-sem: @@ -148,10 +149,10 @@ func TestAnalogSensorDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = 200 return - }) + } d.halt <- true diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go index 13b1d1bde..e9ea6d408 100644 --- a/drivers/aio/grove_drivers_test.go +++ b/drivers/aio/grove_drivers_test.go @@ -51,10 +51,10 @@ func TestAnalogDriverHalt(t *testing.T) { for _, driver := range drivers { var callCount int32 - testAdaptor.TestAdaptorAnalogRead(func() (int, error) { + testAdaptor.analogReadFunc = func() (int, error) { atomic.AddInt32(&callCount, 1) return 42, nil - }) + } // Start the driver and allow for multiple digital reads _ = driver.Start() @@ -84,11 +84,10 @@ func TestDriverPublishesError(t *testing.T) { for _, driver := range drivers { sem := make(chan struct{}, 1) // send error - returnErr := func() (val int, err error) { + testAdaptor.analogReadFunc = func() (val int, err error) { err = errors.New("read error") return } - testAdaptor.TestAdaptorAnalogRead(returnErr) assert.NoError(t, driver.Start()) diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index 7d13996e3..602ad26c9 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -40,10 +40,10 @@ func TestGroveTemperatureSensorDriverScaling(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { // arrange - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = tt.input return - }) + } // act got, err := d.Read() // assert @@ -58,10 +58,10 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { a := newAioTestAdaptor() d := NewGroveTemperatureSensorDriver(a, "1") - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = 585 return - }) + } _ = d.Once(d.Event(Value), func(data interface{}) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true diff --git a/drivers/aio/helpers_test.go b/drivers/aio/helpers_test.go index 70df8edba..38ab5c2db 100644 --- a/drivers/aio/helpers_test.go +++ b/drivers/aio/helpers_test.go @@ -3,37 +3,42 @@ package aio import "sync" type aioTestAdaptor struct { - name string - port string - mtx sync.Mutex - testAdaptorAnalogRead func() (val int, err error) - testAdaptorAnalogWrite func(val int) (err error) - written []int + name string + port string + mtx sync.Mutex + analogReadFunc func() (val int, err error) + analogWriteFunc func(val int) (err error) + written []int } -func (t *aioTestAdaptor) TestAdaptorAnalogRead(f func() (val int, err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testAdaptorAnalogRead = f -} +func newAioTestAdaptor() *aioTestAdaptor { + t := aioTestAdaptor{ + name: "aio_test_adaptor", + port: "/dev/null", + analogReadFunc: func() (val int, err error) { + return 99, nil + }, + analogWriteFunc: func(val int) (err error) { + return nil + }, + } -func (t *aioTestAdaptor) TestAdaptorAnalogWrite(f func(val int) (err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testAdaptorAnalogWrite = f + return &t } +// AnalogRead capabilities (interface AnalogReader) func (t *aioTestAdaptor) AnalogRead(pin string) (val int, err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorAnalogRead() + return t.analogReadFunc() } +// AnalogWrite capabilities (interface AnalogWriter) func (t *aioTestAdaptor) AnalogWrite(pin string, val int) (err error) { t.mtx.Lock() defer t.mtx.Unlock() t.written = append(t.written, val) - return t.testAdaptorAnalogWrite(val) + return t.analogWriteFunc(val) } func (t *aioTestAdaptor) Connect() (err error) { return } @@ -41,15 +46,3 @@ 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", - testAdaptorAnalogRead: func() (val int, err error) { - return 99, nil - }, - testAdaptorAnalogWrite: func(val int) (err error) { - return nil - }, - } -} diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index eaf5e9027..7519ec46d 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -41,10 +41,10 @@ func TestTemperatureSensorDriverNtcScaling(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { // arrange - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = tt.input return - }) + } // act got, err := d.Read() // assert @@ -76,10 +76,10 @@ func TestTemperatureSensorDriverLinearScaling(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { // arrange - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = tt.input return - }) + } // act got, err := d.Read() // assert @@ -96,10 +96,10 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.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 - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { val = 585 return - }) + } _ = d.Once(d.Event(Value), func(data interface{}) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true @@ -121,10 +121,10 @@ func TestTempSensorPublishesError(t *testing.T) { d := NewTemperatureSensorDriver(a, "1") // send error - a.TestAdaptorAnalogRead(func() (val int, err error) { + a.analogReadFunc = func() (val int, err error) { err = errors.New("read error") return - }) + } assert.NoError(t, d.Start()) diff --git a/drivers/gpio/button_driver_test.go b/drivers/gpio/button_driver_test.go index 03d07e105..7455418cd 100644 --- a/drivers/gpio/button_driver_test.go +++ b/drivers/gpio/button_driver_test.go @@ -44,10 +44,10 @@ func TestButtonDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 1 return - }) + } assert.NoError(t, d.Start()) @@ -62,10 +62,10 @@ func TestButtonDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 0 return - }) + } select { case <-sem: @@ -77,10 +77,10 @@ func TestButtonDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { err = errors.New("digital read error") return - }) + } select { case <-sem: @@ -94,10 +94,10 @@ func TestButtonDriverStart(t *testing.T) { d.halt <- true - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 1 return - }) + } select { case <-sem: @@ -117,10 +117,10 @@ func TestButtonDriverDefaultState(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 0 return - }) + } assert.NoError(t, d.Start()) @@ -135,10 +135,10 @@ func TestButtonDriverDefaultState(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 1 return - }) + } select { case <-sem: diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index 8fcd5ddff..b845813aa 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -53,9 +53,9 @@ func TestBuzzerDriverTone(t *testing.T) { func TestBuzzerDriverOnError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) - a.TestAdaptorDigitalWrite(func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") - }) + } assert.ErrorContains(t, d.On(), "write error") } @@ -63,9 +63,9 @@ func TestBuzzerDriverOnError(t *testing.T) { func TestBuzzerDriverOffError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) - a.TestAdaptorDigitalWrite(func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") - }) + } assert.ErrorContains(t, d.Off(), "write error") } @@ -73,9 +73,9 @@ func TestBuzzerDriverOffError(t *testing.T) { func TestBuzzerDriverToneError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) - a.TestAdaptorDigitalWrite(func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") - }) + } assert.ErrorContains(t, d.Tone(100, 0.01), "write error") } diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index 59e78a414..7996eee28 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -13,17 +13,17 @@ var _ gobot.Driver = (*DirectPinDriver)(nil) func initTestDirectPinDriver() *DirectPinDriver { a := newGpioTestAdaptor() - a.testAdaptorDigitalRead = func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 1 return } - a.testAdaptorDigitalWrite = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") } - a.testAdaptorPwmWrite = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) (err error) { return errors.New("write error") } - a.testAdaptorServoWrite = func(string, byte) (err error) { + a.servoWriteFunc = func(string, byte) (err error) { return errors.New("write error") } return NewDirectPinDriver(a, "1") diff --git a/drivers/gpio/grove_drivers_test.go b/drivers/gpio/grove_drivers_test.go index 19ee99eb4..d580fc51f 100644 --- a/drivers/gpio/grove_drivers_test.go +++ b/drivers/gpio/grove_drivers_test.go @@ -53,7 +53,7 @@ func TestDigitalDriverHalt(t *testing.T) { for _, driver := range drivers { var callCount int32 - testAdaptor.testAdaptorDigitalRead = func(string) (int, error) { + testAdaptor.digitalReadFunc = func(string) (int, error) { atomic.AddInt32(&callCount, 1) return 42, nil } @@ -89,7 +89,7 @@ func TestDriverPublishesError(t *testing.T) { err = errors.New("read error") return } - testAdaptor.testAdaptorDigitalRead = returnErr + testAdaptor.digitalReadFunc = returnErr assert.NoError(t, driver.Start()) diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index 6bc2b1592..81985d98f 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -126,14 +126,14 @@ func TestHD44780DriverWriteError(t *testing.T) { var a *gpioTestAdaptor d, a = initTestHD44780Driver4BitModeWithStubbedAdaptor() - a.testAdaptorDigitalWrite = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") } _ = d.Start() assert.ErrorContains(t, d.Write("hello gobot"), "write error") d, a = initTestHD44780Driver8BitModeWithStubbedAdaptor() - a.testAdaptorDigitalWrite = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") } _ = d.Start() diff --git a/drivers/gpio/helpers_test.go b/drivers/gpio/helpers_test.go index b7031cab8..8b29a3811 100644 --- a/drivers/gpio/helpers_test.go +++ b/drivers/gpio/helpers_test.go @@ -10,98 +10,66 @@ func (t *gpioTestBareAdaptor) Name() string { return "" } func (t *gpioTestBareAdaptor) SetName(n string) {} type gpioTestAdaptor struct { - name string - port string - mtx sync.Mutex - testAdaptorDigitalWrite func(pin string, val byte) (err error) - testAdaptorServoWrite func(pin string, val byte) (err error) - testAdaptorPwmWrite func(pin string, val byte) (err error) - testAdaptorAnalogRead func(ping string) (val int, err error) - testAdaptorDigitalRead func(ping string) (val int, err error) + name string + port string + mtx sync.Mutex + digitalReadFunc func(ping string) (val int, err error) + digitalWriteFunc func(pin string, val byte) (err error) + pwmWriteFunc func(pin string, val byte) (err error) + servoWriteFunc func(pin string, val byte) (err error) } -func (t *gpioTestAdaptor) TestAdaptorDigitalWrite(f func(pin string, val byte) (err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testAdaptorDigitalWrite = f -} - -func (t *gpioTestAdaptor) TestAdaptorServoWrite(f func(pin string, val byte) (err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testAdaptorServoWrite = f -} - -func (t *gpioTestAdaptor) TestAdaptorPwmWrite(f func(pin string, val byte) (err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testAdaptorPwmWrite = f -} +func newGpioTestAdaptor() *gpioTestAdaptor { + t := gpioTestAdaptor{ + name: "gpio_test_adaptor", + port: "/dev/null", + digitalWriteFunc: func(pin string, val byte) (err error) { + return nil + }, + servoWriteFunc: func(pin string, val byte) (err error) { + return nil + }, + pwmWriteFunc: func(pin string, val byte) (err error) { + return nil + }, + digitalReadFunc: func(pin string) (val int, err error) { + return 1, nil + }, + } -func (t *gpioTestAdaptor) TestAdaptorAnalogRead(f func(pin string) (val int, err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testAdaptorAnalogRead = f + return &t } -func (t *gpioTestAdaptor) TestAdaptorDigitalRead(f func(pin string) (val int, err error)) { +// DigitalRead capabilities (interface DigitalReader) +func (t *gpioTestAdaptor) DigitalRead(pin string) (val int, err error) { t.mtx.Lock() defer t.mtx.Unlock() - t.testAdaptorDigitalRead = f + return t.digitalReadFunc(pin) } -func (t *gpioTestAdaptor) ServoWrite(pin string, val byte) (err error) { +// DigitalWrite capabilities (interface DigitalWriter) +func (t *gpioTestAdaptor) DigitalWrite(pin string, val byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorServoWrite(pin, val) + return t.digitalWriteFunc(pin, val) } +// PwmWrite capabilities (interface PwmWriter) func (t *gpioTestAdaptor) PwmWrite(pin string, val byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorPwmWrite(pin, val) + return t.pwmWriteFunc(pin, val) } -func (t *gpioTestAdaptor) AnalogRead(pin string) (val int, err error) { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testAdaptorAnalogRead(pin) -} - -func (t *gpioTestAdaptor) DigitalRead(pin string) (val int, err error) { +// ServoWrite capabilities (interface ServoWriter) +func (t *gpioTestAdaptor) ServoWrite(pin string, val byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorDigitalRead(pin) + return t.servoWriteFunc(pin, val) } -func (t *gpioTestAdaptor) DigitalWrite(pin string, val byte) (err error) { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testAdaptorDigitalWrite(pin, val) -} func (t *gpioTestAdaptor) Connect() (err error) { return } func (t *gpioTestAdaptor) Finalize() (err error) { return } func (t *gpioTestAdaptor) Name() string { return t.name } func (t *gpioTestAdaptor) SetName(n string) { t.name = n } func (t *gpioTestAdaptor) Port() string { return t.port } - -func newGpioTestAdaptor() *gpioTestAdaptor { - return &gpioTestAdaptor{ - port: "/dev/null", - testAdaptorDigitalWrite: func(pin string, val byte) (err error) { - return nil - }, - testAdaptorServoWrite: func(pin string, val byte) (err error) { - return nil - }, - testAdaptorPwmWrite: func(pin string, val byte) (err error) { - return nil - }, - testAdaptorAnalogRead: func(pin string) (val int, err error) { - return 99, nil - }, - testAdaptorDigitalRead: func(pin string) (val int, err error) { - return 1, nil - }, - } -} diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index b05a10522..38d40bc76 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -13,10 +13,10 @@ var _ gobot.Driver = (*LedDriver)(nil) func initTestLedDriver() *LedDriver { a := newGpioTestAdaptor() - a.testAdaptorDigitalWrite = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return nil } - a.testAdaptorPwmWrite = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) (err error) { return nil } return NewLedDriver(a, "1") @@ -30,10 +30,10 @@ func TestLedDriver(t *testing.T) { assert.Equal(t, "1", d.Pin()) assert.NotNil(t, d.Connection()) - a.testAdaptorDigitalWrite = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") } - a.testAdaptorPwmWrite = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) (err error) { return errors.New("pwm error") } @@ -72,7 +72,7 @@ func TestLedDriverToggle(t *testing.T) { func TestLedDriverBrightness(t *testing.T) { a := newGpioTestAdaptor() d := NewLedDriver(a, "1") - a.testAdaptorPwmWrite = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) (err error) { err = errors.New("pwm error") return } diff --git a/drivers/gpio/makey_button_driver_test.go b/drivers/gpio/makey_button_driver_test.go index ef3711135..996e6a39a 100644 --- a/drivers/gpio/makey_button_driver_test.go +++ b/drivers/gpio/makey_button_driver_test.go @@ -54,10 +54,10 @@ func TestMakeyButtonDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 0 return - }) + } select { case <-sem: @@ -70,10 +70,10 @@ func TestMakeyButtonDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 1 return - }) + } select { case <-sem: @@ -86,10 +86,10 @@ func TestMakeyButtonDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { err = errors.New("digital read error") return - }) + } select { case <-sem: @@ -102,10 +102,10 @@ func TestMakeyButtonDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 1 return - }) + } d.halt <- true diff --git a/drivers/gpio/pir_motion_driver_test.go b/drivers/gpio/pir_motion_driver_test.go index 9d83d70fd..79ab0d710 100644 --- a/drivers/gpio/pir_motion_driver_test.go +++ b/drivers/gpio/pir_motion_driver_test.go @@ -46,10 +46,10 @@ func TestPIRMotionDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 1 return - }) + } select { case <-sem: @@ -62,10 +62,10 @@ func TestPIRMotionDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { val = 0 return - }) + } select { case <-sem: @@ -77,10 +77,10 @@ func TestPIRMotionDriverStart(t *testing.T) { sem <- true }) - a.TestAdaptorDigitalRead(func(string) (val int, err error) { + a.digitalReadFunc = func(string) (val int, err error) { err = errors.New("digital read error") return - }) + } select { case <-sem: diff --git a/drivers/gpio/relay_driver_test.go b/drivers/gpio/relay_driver_test.go index 3abae423f..340965d72 100644 --- a/drivers/gpio/relay_driver_test.go +++ b/drivers/gpio/relay_driver_test.go @@ -15,10 +15,10 @@ func (l *RelayDriver) High() bool { return l.high } func initTestRelayDriver() (*RelayDriver, *gpioTestAdaptor) { a := newGpioTestAdaptor() - a.testAdaptorDigitalWrite = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return nil } - a.testAdaptorPwmWrite = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) (err error) { return nil } return NewRelayDriver(a, "1"), a @@ -49,10 +49,10 @@ func TestRelayDriverHalt(t *testing.T) { func TestRelayDriverToggle(t *testing.T) { d, a := initTestRelayDriver() var lastVal byte - a.TestAdaptorDigitalWrite(func(pin string, val byte) error { + a.digitalWriteFunc = func(pin string, val byte) error { lastVal = val return nil - }) + } _ = d.Off() assert.False(t, d.State()) @@ -68,10 +68,10 @@ func TestRelayDriverToggle(t *testing.T) { func TestRelayDriverToggleInverted(t *testing.T) { d, a := initTestRelayDriver() var lastVal byte - a.TestAdaptorDigitalWrite(func(pin string, val byte) error { + a.digitalWriteFunc = func(pin string, val byte) error { lastVal = val return nil - }) + } d.Inverted = true _ = d.Off() @@ -88,10 +88,10 @@ func TestRelayDriverToggleInverted(t *testing.T) { func TestRelayDriverCommands(t *testing.T) { d, a := initTestRelayDriver() var lastVal byte - a.TestAdaptorDigitalWrite(func(pin string, val byte) error { + a.digitalWriteFunc = func(pin string, val byte) error { lastVal = val return nil - }) + } assert.Nil(t, d.Command("Off")(nil)) assert.False(t, d.State()) @@ -109,10 +109,10 @@ func TestRelayDriverCommands(t *testing.T) { func TestRelayDriverCommandsInverted(t *testing.T) { d, a := initTestRelayDriver() var lastVal byte - a.TestAdaptorDigitalWrite(func(pin string, val byte) error { + a.digitalWriteFunc = func(pin string, val byte) error { lastVal = val return nil - }) + } d.Inverted = true assert.Nil(t, d.Command("Off")(nil)) diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index e66fa0e7e..818e2490a 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -13,10 +13,10 @@ var _ gobot.Driver = (*RgbLedDriver)(nil) func initTestRgbLedDriver() *RgbLedDriver { a := newGpioTestAdaptor() - a.testAdaptorDigitalWrite = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return nil } - a.testAdaptorPwmWrite = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) (err error) { return nil } return NewRgbLedDriver(a, "1", "2", "3") @@ -34,10 +34,10 @@ func TestRgbLedDriver(t *testing.T) { assert.Equal(t, "3", d.BluePin()) assert.NotNil(t, d.Connection()) - a.testAdaptorDigitalWrite = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") } - a.testAdaptorPwmWrite = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) (err error) { return errors.New("pwm error") } @@ -79,7 +79,7 @@ func TestRgbLedDriverSetLevel(t *testing.T) { assert.NoError(t, d.SetLevel("1", 150)) d = NewRgbLedDriver(a, "1", "2", "3") - a.testAdaptorPwmWrite = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) (err error) { err = errors.New("pwm error") return } diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index a3ac2b2ac..5aad8c953 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -24,7 +24,7 @@ func TestServoDriver(t *testing.T) { assert.Equal(t, "1", d.Pin()) assert.NotNil(t, d.Connection()) - a.testAdaptorServoWrite = func(string, byte) (err error) { + a.servoWriteFunc = func(string, byte) (err error) { return errors.New("pwm error") } diff --git a/drivers/spi/ssd1306_driver_test.go b/drivers/spi/ssd1306_driver_test.go index d896f8957..b3ec7d791 100644 --- a/drivers/spi/ssd1306_driver_test.go +++ b/drivers/spi/ssd1306_driver_test.go @@ -49,41 +49,41 @@ type gpioTestAdaptor struct { port string mtx sync.Mutex Connector - testAdaptorDigitalWrite func() (err error) - testAdaptorServoWrite func() (err error) - testAdaptorPwmWrite func() (err error) - testAdaptorAnalogRead func() (val int, err error) - testAdaptorDigitalRead func() (val int, err error) + digitalWriteFunc func() (err error) + servoWriteFunc func() (err error) + pwmWriteFunc func() (err error) + analogReadFunc func() (val int, err error) + digitalReadFunc func() (val int, err error) } func (t *gpioTestAdaptor) ServoWrite(string, byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorServoWrite() + return t.servoWriteFunc() } func (t *gpioTestAdaptor) PwmWrite(string, byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorPwmWrite() + return t.pwmWriteFunc() } func (t *gpioTestAdaptor) AnalogRead(string) (val int, err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorAnalogRead() + return t.analogReadFunc() } func (t *gpioTestAdaptor) DigitalRead(string) (val int, err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorDigitalRead() + return t.digitalReadFunc() } func (t *gpioTestAdaptor) DigitalWrite(string, byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testAdaptorDigitalWrite() + return t.digitalWriteFunc() } func (t *gpioTestAdaptor) Connect() (err error) { return } func (t *gpioTestAdaptor) Finalize() (err error) { return } @@ -95,19 +95,19 @@ func newGpioTestAdaptor() *gpioTestAdaptor { a := newSpiTestAdaptor() return &gpioTestAdaptor{ port: "/dev/null", - testAdaptorDigitalWrite: func() (err error) { + digitalWriteFunc: func() (err error) { return nil }, - testAdaptorServoWrite: func() (err error) { + servoWriteFunc: func() (err error) { return nil }, - testAdaptorPwmWrite: func() (err error) { + pwmWriteFunc: func() (err error) { return nil }, - testAdaptorAnalogRead: func() (val int, err error) { + analogReadFunc: func() (val int, err error) { return 99, nil }, - testAdaptorDigitalRead: func() (val int, err error) { + digitalReadFunc: func() (val int, err error) { return 1, nil }, Connector: a, From f219a4055db6597c0ebc6b0e2a9ffe394df295fc Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Fri, 27 Oct 2023 21:06:07 +0200 Subject: [PATCH 16/57] gpio(hcsr04): add driver for ultrasonic ranging module (#1012) --- README.md | 5 +- appveyor.yml | 3 +- drivers/gpio/README.md | 7 +- drivers/gpio/{gpio.go => gpio_driver.go} | 62 ++++ drivers/gpio/gpio_driver_test.go | 78 ++++ drivers/gpio/hcsr04_driver.go | 218 +++++++++++ drivers/gpio/hcsr04_driver_test.go | 338 ++++++++++++++++++ drivers/gpio/helpers_test.go | 58 ++- examples/raspi_hcsr04.go | 89 +++++ examples/tinkerboard_hcsr04.go | 93 +++++ platforms/adaptors/digitalpinsadaptor.go | 25 ++ platforms/adaptors/digitalpinsadaptor_test.go | 1 + platforms/firmata/firmata_adaptor.go | 3 + platforms/firmata/firmata_adaptor_test.go | 3 + platforms/firmata/firmata_i2c.go | 3 + platforms/firmata/firmata_i2c_test.go | 3 + platforms/firmata/tcp_firmata_adaptor.go | 3 + platforms/firmata/tcp_firmata_adaptor_test.go | 3 + 18 files changed, 987 insertions(+), 8 deletions(-) rename drivers/gpio/{gpio.go => gpio_driver.go} (62%) create mode 100644 drivers/gpio/gpio_driver_test.go create mode 100644 drivers/gpio/hcsr04_driver.go create mode 100644 drivers/gpio/hcsr04_driver_test.go create mode 100644 examples/raspi_hcsr04.go create mode 100644 examples/tinkerboard_hcsr04.go diff --git a/README.md b/README.md index 560c40eb4..f14c67628 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ Support for many devices that use General Purpose Input/Output (GPIO) have a shared set of drivers provided using the `gobot/drivers/gpio` package: - [GPIO](https://en.wikipedia.org/wiki/General_Purpose_Input/Output) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/gpio) - - AIP1640 LED + - AIP1640 LED Dot Matrix/7 Segment Controller - Button - Buzzer - Direct Pin @@ -281,8 +281,11 @@ a shared set of drivers provided using the `gobot/drivers/gpio` package: - Grove Magnetic Switch - Grove Relay - Grove Touch Sensor + - HC-SR04 Ultrasonic Ranging Module + - HD44780 LCD controller - LED - Makey Button + - MAX7219 LED Dot Matrix - Motor - Proximity Infra Red (PIR) Motion Sensor - Relay diff --git a/appveyor.yml b/appveyor.yml index 1bc2f7642..dd9d21df6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,10 +15,9 @@ before_test: build_script: - go test -v -cpu=2 . - go test -v -cpu=2 ./drivers/aio/... - - go test -v -cpu=2 ./drivers/i2c/... + - go test -v -cpu=2 ./platforms/ble/... - go test -v -cpu=2 ./platforms/dji/... - go test -v -cpu=2 ./platforms/firmata/... - - go test -v -cpu=2 ./platforms/ble/... - go test -v -cpu=2 ./platforms/joystick/... - go test -v -cpu=2 ./platforms/parrot/... - go test -v -cpu=2 ./platforms/sphero/... diff --git a/drivers/gpio/README.md b/drivers/gpio/README.md index e9b2da3aa..fbd8fe192 100644 --- a/drivers/gpio/README.md +++ b/drivers/gpio/README.md @@ -12,17 +12,22 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r Gobot has a extensible system for connecting to hardware devices. The following GPIO devices are currently supported: +- AIP1640 LED Dot Matrix/7 Segment Controller - Button - Buzzer - Direct Pin +- EasyDriver - Grove Button - Grove Buzzer - Grove LED - Grove Magnetic Switch - Grove Relay - Grove Touch Sensor +- HC-SR04 Ultrasonic Ranging Module +- HD44780 LCD controller - LED - Makey Button +- MAX7219 LED Dot Matrix - Motor - Proximity Infra Red (PIR) Motion Sensor - Relay @@ -30,5 +35,3 @@ Gobot has a extensible system for connecting to hardware devices. The following - Servo - Stepper Motor - TM1638 LED Controller - -More drivers are coming soon... diff --git a/drivers/gpio/gpio.go b/drivers/gpio/gpio_driver.go similarity index 62% rename from drivers/gpio/gpio.go rename to drivers/gpio/gpio_driver.go index 624cca19f..bc09ae0a7 100644 --- a/drivers/gpio/gpio.go +++ b/drivers/gpio/gpio_driver.go @@ -2,6 +2,9 @@ package gpio import ( "errors" + "sync" + + "gobot.io/x/gobot/v2" ) var ( @@ -61,3 +64,62 @@ type DigitalWriter interface { type DigitalReader interface { DigitalRead(string) (val int, err error) } + +// Driver implements the interface gobot.Driver. +type Driver struct { + name string + connection gobot.Adaptor + afterStart func() error + beforeHalt func() error + gobot.Commander + mutex *sync.Mutex // mutex often needed to ensure that write-read sequences are not interrupted +} + +// NewDriver creates a new generic and basic gpio gobot driver. +func NewDriver(a gobot.Adaptor, name string) *Driver { + d := &Driver{ + name: gobot.DefaultName(name), + connection: a, + afterStart: func() error { return nil }, + beforeHalt: func() error { return nil }, + Commander: gobot.NewCommander(), + mutex: &sync.Mutex{}, + } + + return d +} + +// Name returns the name of the gpio device. +func (d *Driver) Name() string { + return d.name +} + +// SetName sets the name of the gpio device. +func (d *Driver) SetName(name string) { + d.name = name +} + +// Connection returns the connection of the gpio device. +func (d *Driver) Connection() gobot.Connection { + return d.connection.(gobot.Connection) +} + +// Start initializes the gpio device. +func (d *Driver) Start() error { + d.mutex.Lock() + defer d.mutex.Unlock() + + // currently there is nothing to do here for the driver + + return d.afterStart() +} + +// Halt halts the gpio device. +func (d *Driver) Halt() error { + d.mutex.Lock() + defer d.mutex.Unlock() + + // currently there is nothing to do after halt for the driver + + return d.beforeHalt() +} diff --git a/drivers/gpio/gpio_driver_test.go b/drivers/gpio/gpio_driver_test.go new file mode 100644 index 000000000..30ae59bbc --- /dev/null +++ b/drivers/gpio/gpio_driver_test.go @@ -0,0 +1,78 @@ +package gpio + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" +) + +var _ gobot.Driver = (*Driver)(nil) + +func initTestDriverWithStubbedAdaptor() (*Driver, *gpioTestAdaptor) { + a := newGpioTestAdaptor() + d := NewDriver(a, "GPIO_BASIC") + return d, a +} + +func initTestDriver() *Driver { + d, _ := initTestDriverWithStubbedAdaptor() + return d +} + +func TestNewDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + var di interface{} = NewDriver(a, "GPIO_BASIC") + // assert + d, ok := di.(*Driver) + if !ok { + t.Errorf("NewDriver() should have returned a *Driver") + } + assert.Contains(t, d.name, "GPIO_BASIC") + assert.Equal(t, a, d.connection) + assert.NoError(t, d.afterStart()) + assert.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) +} + +func TestSetName(t *testing.T) { + // arrange + d := initTestDriver() + // act + d.SetName("TESTME") + // assert + assert.Equal(t, "TESTME", d.Name()) +} + +func TestConnection(t *testing.T) { + // arrange + d, a := initTestDriverWithStubbedAdaptor() + // act, assert + assert.Equal(t, a, d.Connection()) +} + +func TestStart(t *testing.T) { + // arrange + d := initTestDriver() + // act, assert + assert.NoError(t, d.Start()) + // arrange after start function + d.afterStart = func() error { return fmt.Errorf("after start error") } + // act, assert + assert.ErrorContains(t, d.Start(), "after start error") +} + +func TestHalt(t *testing.T) { + // arrange + d := initTestDriver() + // act, assert + assert.NoError(t, d.Halt()) + // arrange after start function + d.beforeHalt = func() error { return fmt.Errorf("before halt error") } + // act, assert + assert.ErrorContains(t, d.Halt(), "before halt error") +} diff --git a/drivers/gpio/hcsr04_driver.go b/drivers/gpio/hcsr04_driver.go new file mode 100644 index 000000000..471c055a4 --- /dev/null +++ b/drivers/gpio/hcsr04_driver.go @@ -0,0 +1,218 @@ +package gpio + +import ( + "fmt" + "sync" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/system" +) + +const ( + hcsr04SoundSpeed = 343 // in [m/s] + // the device can measure 2 cm .. 4 m, this means sweep distances between 4 cm and 8 m + // this cause pulse duration between 0.12 ms and 24 ms (at 34.3 cm/ms, ~0.03 ms/cm, ~3 ms/m) + // so we use 60 ms as a limit for timeout and 100 ms for duration between 2 consecutive measurements + hcsr04StartTransmitTimeout time.Duration = 100 * time.Millisecond // unfortunately takes sometimes longer than 60 ms + hcsr04ReceiveTimeout time.Duration = 60 * time.Millisecond + hcsr04EmitTriggerDuration time.Duration = 10 * time.Microsecond // according to specification + hcsr04MonitorUpdate time.Duration = 200 * time.Millisecond + // the resolution of the device is ~3 mm, which relates to 10 us (343 mm/ms = 0.343 mm/us) + // the poll interval increases the reading interval to this value and adds around 3 mm inaccuracy + // it takes only an effect for fast systems, because reading inputs is typically much slower, e.g. 30-50 us on raspi + // so, using the internal edge detection with "cdev" is more precise + hcsr04PollInputIntervall time.Duration = 10 * time.Microsecond +) + +// HCSR04Driver is a driver for ultrasonic range measurement. +type HCSR04Driver struct { + *Driver + triggerPinID string + echoPinID string + useEdgePolling bool // use discrete edge polling instead "cdev" from gpiod + measureMutex *sync.Mutex // to ensure that only one measurement is done at a time + triggerPin gobot.DigitalPinner + echoPin gobot.DigitalPinner + lastMeasureMicroSec int64 // ~120 .. 24000 us + distanceMonitorStopChan chan struct{} + distanceMonitorStopWaitGroup *sync.WaitGroup + delayMicroSecChan chan int64 // channel for event handler return value + pollQuitChan chan struct{} // channel for quit the continuous polling +} + +// NewHCSR04Driver creates a new instance of the driver for HC-SR04 (same as SEN-US01). +// +// Datasheet: https://www.makershop.de/download/HCSR04-datasheet-version-1.pdf +func NewHCSR04Driver(a gobot.Adaptor, triggerPinID string, echoPinID string, useEdgePolling bool) *HCSR04Driver { + h := HCSR04Driver{ + Driver: NewDriver(a, "HCSR04"), + triggerPinID: triggerPinID, + echoPinID: echoPinID, + useEdgePolling: useEdgePolling, + measureMutex: &sync.Mutex{}, + } + + h.afterStart = func() error { + tpin, err := a.(gobot.DigitalPinnerProvider).DigitalPin(triggerPinID) + if err != nil { + return fmt.Errorf("error on get trigger pin: %v", err) + } + if err := tpin.ApplyOptions(system.WithPinDirectionOutput(0)); err != nil { + return fmt.Errorf("error on apply output for trigger pin: %v", err) + } + h.triggerPin = tpin + + // pins are inputs by default + epin, err := a.(gobot.DigitalPinnerProvider).DigitalPin(echoPinID) + if err != nil { + return fmt.Errorf("error on get echo pin: %v", err) + } + + epinOptions := []func(gobot.DigitalPinOptioner) bool{system.WithPinEventOnBothEdges(h.createEventHandler())} + if h.useEdgePolling { + h.pollQuitChan = make(chan struct{}) + epinOptions = append(epinOptions, system.WithPinPollForEdgeDetection(hcsr04PollInputIntervall, h.pollQuitChan)) + } + if err := epin.ApplyOptions(epinOptions...); err != nil { + return fmt.Errorf("error on apply options for echo pin: %v", err) + } + h.echoPin = epin + + h.delayMicroSecChan = make(chan int64) + + return nil + } + + h.beforeHalt = func() error { + if useEdgePolling { + close(h.pollQuitChan) + } + + if err := h.stopDistanceMonitor(); err != nil { + fmt.Printf("no need to stop distance monitoring: %v\n", err) + } + + // note: Unexport() of all pins will be done on adaptor.Finalize() + + close(h.delayMicroSecChan) + + return nil + } + + return &h +} + +// MeasureDistance retrieves the distance in front of sensor in meters and returns the measure. It is not designed +// to work in a fast loop! For this specific usage, use StartDistanceMonitor() associated with Distance() instead. +func (h *HCSR04Driver) MeasureDistance() (float64, error) { + err := h.measureDistance() + if err != nil { + return 0, err + } + return h.Distance(), nil +} + +// Distance returns the last distance measured in meter, it does not trigger a distance measurement +func (h *HCSR04Driver) Distance() float64 { + distMm := h.lastMeasureMicroSec * hcsr04SoundSpeed / 1000 / 2 + return float64(distMm) / 1000.0 +} + +// StartDistanceMonitor starts continuous measurement. The current value can be read by Distance() +func (h *HCSR04Driver) StartDistanceMonitor() error { + // ensure that start and stop can not interfere + h.mutex.Lock() + defer h.mutex.Unlock() + + if h.distanceMonitorStopChan != nil { + return fmt.Errorf("distance monitor already started for '%s'", h.name) + } + + h.distanceMonitorStopChan = make(chan struct{}) + h.distanceMonitorStopWaitGroup = &sync.WaitGroup{} + h.distanceMonitorStopWaitGroup.Add(1) + + go func(name string) { + defer h.distanceMonitorStopWaitGroup.Done() + for { + select { + case <-h.distanceMonitorStopChan: + h.distanceMonitorStopChan = nil + return + default: + if err := h.measureDistance(); err != nil { + fmt.Printf("continuous measure distance skipped for '%s': %v\n", name, err) + } + time.Sleep(hcsr04MonitorUpdate) + } + } + }(h.name) + + return nil +} + +// StopDistanceMonitor stop the monitor process +func (h *HCSR04Driver) StopDistanceMonitor() error { + // ensure that start and stop can not interfere + h.mutex.Lock() + defer h.mutex.Unlock() + + return h.stopDistanceMonitor() +} + +func (h *HCSR04Driver) createEventHandler() func(int, time.Duration, string, uint32, uint32) { + var startTimestamp time.Duration + return func(offset int, t time.Duration, et string, sn uint32, lsn uint32) { + switch et { + case system.DigitalPinEventRisingEdge: + startTimestamp = t + case system.DigitalPinEventFallingEdge: + // unfortunately there is an additional falling edge at each start trigger, so we need to filter this + // we use the start duration value for filtering + if startTimestamp == 0 { + return + } + h.delayMicroSecChan <- (t - startTimestamp).Microseconds() + startTimestamp = 0 + } + } +} + +func (h *HCSR04Driver) stopDistanceMonitor() error { + if h.distanceMonitorStopChan == nil { + return fmt.Errorf("distance monitor is not yet started for '%s'", h.name) + } + + h.distanceMonitorStopChan <- struct{}{} + h.distanceMonitorStopWaitGroup.Wait() + + return nil +} + +func (h *HCSR04Driver) measureDistance() error { + h.measureMutex.Lock() + defer h.measureMutex.Unlock() + + if err := h.emitTrigger(); err != nil { + return err + } + + // stop the loop if the measure is done or the timeout is elapsed + timeout := hcsr04StartTransmitTimeout + hcsr04ReceiveTimeout + select { + case <-time.After(timeout): + return fmt.Errorf("timeout %s reached while waiting for value with echo pin %s", timeout, h.echoPinID) + case h.lastMeasureMicroSec = <-h.delayMicroSecChan: + } + + return nil +} + +func (h *HCSR04Driver) emitTrigger() error { + if err := h.triggerPin.Write(1); err != nil { + return err + } + time.Sleep(hcsr04EmitTriggerDuration) + return h.triggerPin.Write(0) +} diff --git a/drivers/gpio/hcsr04_driver_test.go b/drivers/gpio/hcsr04_driver_test.go new file mode 100644 index 000000000..994600a55 --- /dev/null +++ b/drivers/gpio/hcsr04_driver_test.go @@ -0,0 +1,338 @@ +package gpio + +import ( + "fmt" + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2/system" +) + +func initTestHCSR04DriverWithStubbedAdaptor(triggerPinID string, echoPinID string) (*HCSR04Driver, *digitalPinMock) { + a := newGpioTestAdaptor() + tpin := a.addDigitalPin(triggerPinID) + _ = a.addDigitalPin(echoPinID) + d := NewHCSR04Driver(a, triggerPinID, echoPinID, false) + if err := d.Start(); err != nil { + panic(err) + } + return d, tpin +} + +func TestNewHCSR04Driver(t *testing.T) { + // arrange + const ( + triggerPinID = "3" + echoPinID = "4" + ) + a := newGpioTestAdaptor() + tpin := a.addDigitalPin(triggerPinID) + epin := a.addDigitalPin(echoPinID) + // act + d := NewHCSR04Driver(a, triggerPinID, echoPinID, false) + // assert + assert.IsType(t, &HCSR04Driver{}, d) + assert.NotNil(t, d.Driver) + assert.True(t, strings.HasPrefix(d.name, "HCSR04")) + assert.Equal(t, a, d.connection) + assert.NoError(t, d.afterStart()) + assert.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + assert.Equal(t, triggerPinID, d.triggerPinID) + assert.Equal(t, echoPinID, d.echoPinID) + assert.Equal(t, false, d.useEdgePolling) + assert.Equal(t, tpin, d.triggerPin) + assert.Equal(t, epin, d.echoPin) +} + +func TestHCSR04MeasureDistance(t *testing.T) { + tests := map[string]struct { + measureMicroSec int64 + simulateWriteErr string + wantCallsWrite int + wantVal float64 + wantErr string + }{ + "measure_ok": { + measureMicroSec: 5831, + wantCallsWrite: 2, + wantVal: 1.0, + }, + "error_timeout": { + measureMicroSec: 170000, // > 160 ms + wantCallsWrite: 2, + wantErr: "timeout 160ms reached", + }, + "error_write": { + measureMicroSec: 5831, + simulateWriteErr: "write error", + wantCallsWrite: 1, + wantErr: "write error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, tpin := initTestHCSR04DriverWithStubbedAdaptor("3", "4") + // arrange sensor and event handler simulation + waitForTriggerChan := make(chan struct{}) + loopWg := sync.WaitGroup{} + defer func() { + close(waitForTriggerChan) + loopWg.Wait() + }() + loopWg.Add(1) + go func() { + <-waitForTriggerChan + m := tc.measureMicroSec // to prevent data race together with wait group + loopWg.Done() + time.Sleep(time.Duration(m) * time.Microsecond) + d.delayMicroSecChan <- m + }() + // arrange writes + numCallsWrite := 0 + var oldVal int + tpin.writeFunc = func(val int) error { + numCallsWrite++ + if val == 0 && oldVal == 1 { + // falling edge detected + waitForTriggerChan <- struct{}{} + } + oldVal = val + var err error + if tc.simulateWriteErr != "" { + err = fmt.Errorf(tc.simulateWriteErr) + } + return err + } + // act + got, err := d.MeasureDistance() + // assert + assert.Equal(t, tc.wantCallsWrite, numCallsWrite) + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + require.NoError(t, err) + } + assert.Equal(t, tc.wantVal, got) + }) + } +} + +func TestHCSR04Distance(t *testing.T) { + tests := map[string]struct { + measureMicroSec int64 + simulateWriteErr string + wantVal float64 + wantErr string + }{ + "distance_0mm": { + measureMicroSec: 0, // no validity test yet + wantVal: 0.0, + }, + "distance_2cm": { + measureMicroSec: 117, // 117us ~ 0.12ms => ~2cm + wantVal: 0.02, + }, + "distance_4m": { + measureMicroSec: 23324, // 23324us ~ 24ms => ~4m + wantVal: 4.0, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := HCSR04Driver{lastMeasureMicroSec: tc.measureMicroSec} + // act + got := d.Distance() + // assert + assert.Equal(t, tc.wantVal, got) + }) + } +} + +func TestHCSR04StartDistanceMonitor(t *testing.T) { + tests := map[string]struct { + simulateIsStarted bool + simulateWriteErr bool + wantErr string + }{ + "start_ok": {}, + "start_ok_measure_error": { + simulateWriteErr: true, + }, + "error_already_started": { + simulateIsStarted: true, + wantErr: "already started for 'HCSR04-", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, tpin := initTestHCSR04DriverWithStubbedAdaptor("3", "4") + defer func() { + if d.distanceMonitorStopChan != nil { + close(d.distanceMonitorStopChan) + } + if d.distanceMonitorStopWaitGroup != nil { + d.distanceMonitorStopWaitGroup.Wait() + } + }() + if tc.simulateIsStarted { + d.distanceMonitorStopChan = make(chan struct{}) + } + tpin.writeFunc = func(val int) error { + if tc.simulateWriteErr { + return fmt.Errorf("write error") + } + return nil + } + // act + err := d.StartDistanceMonitor() + time.Sleep(1 * time.Millisecond) // < 160 ms + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + require.NoError(t, err) + assert.NotNil(t, d.distanceMonitorStopChan) + assert.NotNil(t, d.distanceMonitorStopWaitGroup) + } + }) + } +} + +func TestHCSR04StopDistanceMonitor(t *testing.T) { + tests := map[string]struct { + start bool + wantErr string + }{ + "stop_ok": { + start: true, + }, + "error_not_started": { + wantErr: "not yet started for 'HCSR04-", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, _ := initTestHCSR04DriverWithStubbedAdaptor("3", "4") + defer func() { + if d.distanceMonitorStopChan != nil { + close(d.distanceMonitorStopChan) + } + if d.distanceMonitorStopWaitGroup != nil { + d.distanceMonitorStopWaitGroup.Wait() + } + }() + if tc.start { + err := d.StartDistanceMonitor() + require.NoError(t, err) + } + // act + err := d.StopDistanceMonitor() + time.Sleep(1 * time.Millisecond) // < 160 ms + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + require.NoError(t, err) + assert.Nil(t, d.distanceMonitorStopChan) + } + }) + } +} + +func TestHCSR04_createEventHandler(t *testing.T) { + type eventCall struct { + timeStamp time.Duration + eventType string + } + tests := map[string]struct { + calls []eventCall + wants []int64 + }{ + "only_rising": { + calls: []eventCall{ + {timeStamp: 1 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 2 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + }, + }, + "only_falling": { + calls: []eventCall{ + {timeStamp: 2 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + {timeStamp: 3 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + }, + }, + "event_normal": { + calls: []eventCall{ + {timeStamp: 1 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 10 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + }, + wants: []int64{9}, + }, + "event_falling_before": { + calls: []eventCall{ + {timeStamp: 1 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + {timeStamp: 2 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 10 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + }, + wants: []int64{8}, + }, + "event_falling_after": { + calls: []eventCall{ + {timeStamp: 1 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 10 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + {timeStamp: 12 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + }, + wants: []int64{9}, + }, + "event_rising_before": { + calls: []eventCall{ + {timeStamp: 1 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 5 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 10 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + }, + wants: []int64{5}, + }, + "event_rising_after": { + calls: []eventCall{ + {timeStamp: 1 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 10 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + {timeStamp: 12 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + }, + wants: []int64{9}, + }, + "event_multiple": { + calls: []eventCall{ + {timeStamp: 1 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 10 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + {timeStamp: 11 * time.Microsecond, eventType: system.DigitalPinEventRisingEdge}, + {timeStamp: 13 * time.Microsecond, eventType: system.DigitalPinEventFallingEdge}, + }, + wants: []int64{9, 2}, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := HCSR04Driver{delayMicroSecChan: make(chan int64, len(tc.wants))} + // act + eh := d.createEventHandler() + for _, call := range tc.calls { + eh(0, call.timeStamp, call.eventType, 0, 0) + } + // assert + for _, want := range tc.wants { + got := <-d.delayMicroSecChan + assert.Equal(t, want, got) + } + }) + } +} diff --git a/drivers/gpio/helpers_test.go b/drivers/gpio/helpers_test.go index 8b29a3811..41c051159 100644 --- a/drivers/gpio/helpers_test.go +++ b/drivers/gpio/helpers_test.go @@ -1,6 +1,11 @@ package gpio -import "sync" +import ( + "fmt" + "sync" + + "gobot.io/x/gobot/v2" +) type gpioTestBareAdaptor struct{} @@ -9,8 +14,13 @@ func (t *gpioTestBareAdaptor) Finalize() (err error) { return } func (t *gpioTestBareAdaptor) Name() string { return "" } func (t *gpioTestBareAdaptor) SetName(n string) {} +type digitalPinMock struct { + writeFunc func(val int) (err error) +} + type gpioTestAdaptor struct { name string + pinMap map[string]gobot.DigitalPinner port string mtx sync.Mutex digitalReadFunc func(ping string) (val int, err error) @@ -21,8 +31,9 @@ type gpioTestAdaptor struct { func newGpioTestAdaptor() *gpioTestAdaptor { t := gpioTestAdaptor{ - name: "gpio_test_adaptor", - port: "/dev/null", + name: "gpio_test_adaptor", + pinMap: make(map[string]gobot.DigitalPinner), + port: "/dev/null", digitalWriteFunc: func(pin string, val byte) (err error) { return nil }, @@ -73,3 +84,44 @@ func (t *gpioTestAdaptor) Finalize() (err error) { return } func (t *gpioTestAdaptor) Name() string { return t.name } func (t *gpioTestAdaptor) SetName(n string) { t.name = n } func (t *gpioTestAdaptor) Port() string { return t.port } + +// DigitalPin (interface DigitalPinnerProvider) return a pin object +func (t *gpioTestAdaptor) DigitalPin(id string) (gobot.DigitalPinner, error) { + if pin, ok := t.pinMap[id]; ok { + return pin, nil + } + return nil, fmt.Errorf("pin '%s' not found in '%s'", id, t.name) +} + +// ApplyOptions (interface DigitalPinOptionApplier by DigitalPinner) apply all given options to the pin immediately +func (d *digitalPinMock) ApplyOptions(options ...func(gobot.DigitalPinOptioner) bool) error { + return nil +} + +// Export (interface DigitalPinner) exports the pin for use by the adaptor +func (d *digitalPinMock) Export() error { + return nil +} + +// Unexport (interface DigitalPinner) releases the pin from the adaptor, so it is free for the operating system +func (d *digitalPinMock) Unexport() error { + return nil +} + +// Read (interface DigitalPinner) reads the current value of the pin +func (d *digitalPinMock) Read() (n int, err error) { + return 0, err +} + +// Write (interface DigitalPinner) writes to the pin +func (d *digitalPinMock) Write(b int) error { + return d.writeFunc(b) +} + +func (t *gpioTestAdaptor) addDigitalPin(id string) *digitalPinMock { + dpm := &digitalPinMock{ + writeFunc: func(val int) (err error) { return nil }, + } + t.pinMap[id] = dpm + return dpm +} diff --git a/examples/raspi_hcsr04.go b/examples/raspi_hcsr04.go new file mode 100644 index 000000000..83fd3d31e --- /dev/null +++ b/examples/raspi_hcsr04.go @@ -0,0 +1,89 @@ +//go:build example +// +build example + +// +// Do not build by default. + +package main + +import ( + "fmt" + "log" + "os" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/raspi" +) + +func main() { + const ( + triggerOutput = "11" + echoInput = "13" + ) + + // this is mandatory for systems with defunct edge detection, although the "cdev" is used with an newer Kernel + // keep in mind, that this cause more inaccurate measurements + const pollEdgeDetection = true + + a := raspi.NewAdaptor() + hcsr04 := gpio.NewHCSR04Driver(a, triggerOutput, echoInput, pollEdgeDetection) + + work := func() { + if pollEdgeDetection { + fmt.Println("Please note that measurements are CPU consuming and will be more inaccurate with this setting.") + fmt.Println("After startup the system is under load and the measurement is very inaccurate, so wait a bit...") + time.Sleep(2000 * time.Millisecond) + } + + if err := hcsr04.StartDistanceMonitor(); err != nil { + log.Fatal(err) + } + + // first single shot + if v, err := hcsr04.MeasureDistance(); err != nil { + log.Fatal(err) + } else { + fmt.Printf("first single shot done: %5.3f m\n", v) + } + + ticker := gobot.Every(1*time.Second, func() { + fmt.Printf("continuous measurement: %5.3f m\n", hcsr04.Distance()) + }) + + gobot.After(5*time.Second, func() { + if err := hcsr04.StopDistanceMonitor(); err != nil { + log.Fatal(err) + } + ticker.Stop() + }) + + gobot.After(7*time.Second, func() { + // second single shot + if v, err := hcsr04.MeasureDistance(); err != nil { + log.Fatal(err) + } else { + fmt.Printf("second single shot done: %5.3f m\n", v) + } + // cleanup + if err := hcsr04.Halt(); err != nil { + log.Println(err) + } + if err := a.Finalize(); err != nil { + log.Println(err) + } + os.Exit(0) + }) + } + + robot := gobot.NewRobot("distanceBot", + []gobot.Connection{a}, + []gobot.Device{hcsr04}, + work, + ) + + if err := robot.Start(); err != nil { + log.Fatal(err) + } +} diff --git a/examples/tinkerboard_hcsr04.go b/examples/tinkerboard_hcsr04.go new file mode 100644 index 000000000..9c18140be --- /dev/null +++ b/examples/tinkerboard_hcsr04.go @@ -0,0 +1,93 @@ +//go:build example +// +build example + +// +// Do not build by default. + +package main + +import ( + "fmt" + "log" + "os" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/tinkerboard" +) + +// Wiring +// PWR Tinkerboard: 2(+5V), 6, 9, 14, 20 (GND) +// GPIO Tinkerboard: header pin 7 is the trigger output, pin 22 used as echo input +// HC-SR04: the power is wired to +5V and GND of tinkerboard, the same for trigger output and the echo input pin +func main() { + const ( + triggerOutput = "7" + echoInput = "22" + ) + + // this is mandatory for systems with defunct edge detection, although the "cdev" is used with an newer Kernel + // keep in mind, that this cause more inaccurate measurements + const pollEdgeDetection = true + + a := tinkerboard.NewAdaptor() + hcsr04 := gpio.NewHCSR04Driver(a, triggerOutput, echoInput, pollEdgeDetection) + + work := func() { + if pollEdgeDetection { + fmt.Println("Please note that measurements are CPU consuming and will be more inaccurate with this setting.") + fmt.Println("After startup the system is under load and the measurement is very inaccurate, so wait a bit...") + time.Sleep(2000 * time.Millisecond) + } + + if err := hcsr04.StartDistanceMonitor(); err != nil { + log.Fatal(err) + } + + // first single shot + if v, err := hcsr04.MeasureDistance(); err != nil { + log.Fatal(err) + } else { + fmt.Printf("first single shot done: %5.3f m\n", v) + } + + ticker := gobot.Every(1*time.Second, func() { + fmt.Printf("continuous measurement: %5.3f m\n", hcsr04.Distance()) + }) + + gobot.After(5*time.Second, func() { + if err := hcsr04.StopDistanceMonitor(); err != nil { + log.Fatal(err) + } + ticker.Stop() + }) + + gobot.After(7*time.Second, func() { + // second single shot + if v, err := hcsr04.MeasureDistance(); err != nil { + log.Fatal(err) + } else { + fmt.Printf("second single shot done: %5.3f m\n", v) + } + // cleanup + if err := hcsr04.Halt(); err != nil { + log.Println(err) + } + if err := a.Finalize(); err != nil { + log.Println(err) + } + os.Exit(0) + }) + } + + robot := gobot.NewRobot("distanceBot", + []gobot.Connection{a}, + []gobot.Device{hcsr04}, + work, + ) + + if err := robot.Start(); err != nil { + log.Fatal(err) + } +} diff --git a/platforms/adaptors/digitalpinsadaptor.go b/platforms/adaptors/digitalpinsadaptor.go index 5321bb2e5..7ffc9de10 100644 --- a/platforms/adaptors/digitalpinsadaptor.go +++ b/platforms/adaptors/digitalpinsadaptor.go @@ -6,6 +6,7 @@ import ( "time" "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) @@ -31,6 +32,7 @@ type digitalPinsOptioner interface { detectedEdge string, seqno uint32, lseqno uint32)) prepareDigitalPinEventOnBothEdges(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, lseqno uint32)) + prepareDigitalPinPollForEdgeDetection(pin string, pollInterval time.Duration, pollQuitChan chan struct{}) } // DigitalPinsAdaptor is a adaptor for digital pins, normally used for composition in platforms. @@ -196,6 +198,17 @@ func WithGpioEventOnBothEdges(pin string, handler func(lineOffset int, timestamp } } +// WithGpioPollForEdgeDetection prepares the given input pin to use a discrete input pin polling function together with +// edge detection. +func WithGpioPollForEdgeDetection(pin string, pollInterval time.Duration, pollQuitChan chan struct{}) func(Optioner) { + return func(o Optioner) { + a, ok := o.(digitalPinsOptioner) + if ok { + a.prepareDigitalPinPollForEdgeDetection(pin, pollInterval, pollQuitChan) + } + } +} + // Connect prepare new connection to digital pins. func (a *DigitalPinsAdaptor) Connect() error { a.mutex.Lock() @@ -370,6 +383,18 @@ func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnBothEdges(id string, handle a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnBothEdges(handler)) } +func (a *DigitalPinsAdaptor) prepareDigitalPinPollForEdgeDetection( + id string, + pollInterval time.Duration, + pollQuitChan chan struct{}, +) { + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + a.pinOptions[id] = append(a.pinOptions[id], system.WithPinPollForEdgeDetection(pollInterval, pollQuitChan)) +} + func (a *DigitalPinsAdaptor) digitalPin(id string, opts ...func(gobot.DigitalPinOptioner) bool) (gobot.DigitalPinner, error) { if a.pins == nil { return nil, fmt.Errorf("not connected for pin %s", id) diff --git a/platforms/adaptors/digitalpinsadaptor_test.go b/platforms/adaptors/digitalpinsadaptor_test.go index aa61e9454..f25feda58 100644 --- a/platforms/adaptors/digitalpinsadaptor_test.go +++ b/platforms/adaptors/digitalpinsadaptor_test.go @@ -215,6 +215,7 @@ func TestDigitalWrite(t *testing.T) { WithGpiosPullUp("7")(a) WithGpiosOpenDrain("7")(a) WithGpioEventOnFallingEdge("7", gpioEventHandler)(a) + WithGpioPollForEdgeDetection("7", 0, nil)(a) err := a.DigitalWrite("7", 1) assert.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio18/value"].Contents) diff --git a/platforms/firmata/firmata_adaptor.go b/platforms/firmata/firmata_adaptor.go index 5686c2bc2..ddd06751e 100644 --- a/platforms/firmata/firmata_adaptor.go +++ b/platforms/firmata/firmata_adaptor.go @@ -1,3 +1,6 @@ +//go:build !windows +// +build !windows + package firmata import ( diff --git a/platforms/firmata/firmata_adaptor_test.go b/platforms/firmata/firmata_adaptor_test.go index 3e29c6bb8..fa095c193 100644 --- a/platforms/firmata/firmata_adaptor_test.go +++ b/platforms/firmata/firmata_adaptor_test.go @@ -1,3 +1,6 @@ +//go:build !windows +// +build !windows + package firmata import ( diff --git a/platforms/firmata/firmata_i2c.go b/platforms/firmata/firmata_i2c.go index ef7f67d02..4e7759a10 100644 --- a/platforms/firmata/firmata_i2c.go +++ b/platforms/firmata/firmata_i2c.go @@ -1,3 +1,6 @@ +//go:build !windows +// +build !windows + package firmata import ( diff --git a/platforms/firmata/firmata_i2c_test.go b/platforms/firmata/firmata_i2c_test.go index eb8ec2e00..cf9142998 100644 --- a/platforms/firmata/firmata_i2c_test.go +++ b/platforms/firmata/firmata_i2c_test.go @@ -1,3 +1,6 @@ +//go:build !windows +// +build !windows + package firmata import ( diff --git a/platforms/firmata/tcp_firmata_adaptor.go b/platforms/firmata/tcp_firmata_adaptor.go index c389a6943..af34cac96 100644 --- a/platforms/firmata/tcp_firmata_adaptor.go +++ b/platforms/firmata/tcp_firmata_adaptor.go @@ -1,3 +1,6 @@ +//go:build !windows +// +build !windows + package firmata import ( diff --git a/platforms/firmata/tcp_firmata_adaptor_test.go b/platforms/firmata/tcp_firmata_adaptor_test.go index 71829d16b..b63937a21 100644 --- a/platforms/firmata/tcp_firmata_adaptor_test.go +++ b/platforms/firmata/tcp_firmata_adaptor_test.go @@ -1,3 +1,6 @@ +//go:build !windows +// +build !windows + package firmata import ( From 991af9a201312ee25fd30de5007ffdb65fd19204 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sat, 28 Oct 2023 13:57:35 +0200 Subject: [PATCH 17/57] jetson(PWM): fix set period (#1019) --- platforms/jetson/pwm_pin.go | 2 +- platforms/jetson/pwm_pin_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platforms/jetson/pwm_pin.go b/platforms/jetson/pwm_pin.go index 18b432e0c..93a3f57aa 100644 --- a/platforms/jetson/pwm_pin.go +++ b/platforms/jetson/pwm_pin.go @@ -89,7 +89,7 @@ func (p *PWMPin) SetPeriod(period uint32) error { if period < minimumPeriod { return errors.New("Cannot set the period more then minimum") } - if err := p.writeFile(fmt.Sprintf("pwm%s/period", p.fn), fmt.Sprintf("%v", p.period)); err != nil { + if err := p.writeFile(fmt.Sprintf("pwm%s/period", p.fn), fmt.Sprintf("%v", period)); err != nil { return err } p.period = period diff --git a/platforms/jetson/pwm_pin_test.go b/platforms/jetson/pwm_pin_test.go index 5bddaa8db..a61e22753 100644 --- a/platforms/jetson/pwm_pin_test.go +++ b/platforms/jetson/pwm_pin_test.go @@ -55,11 +55,11 @@ func TestPwmPin(t *testing.T) { assert.Equal(t, "", fs.Files[dutyCyclePath].Contents) assert.NoError(t, pin.SetPeriod(20000000)) - // TODO: see PR #990 assert.Equal(t, "20000000", fs.Files[periodPath].Contents) + assert.Equal(t, "20000000", fs.Files[periodPath].Contents) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) assert.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") - // TODO: see PR #990 assert.Equal(t, "20000000", fs.Files[periodPath].Contents) + assert.Equal(t, "20000000", fs.Files[periodPath].Contents) dc, _ := pin.DutyCycle() assert.Equal(t, uint32(0), dc) From 693cbf158d00a9e12b68f6f7f4f708d0c8e1a6e1 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 29 Oct 2023 19:35:26 +0100 Subject: [PATCH 18/57] i2c(PCA9685, adafruit): clean up architecture and fix init (#1021) --- .golangci.yml | 1 - README.md | 5 +- drivers/i2c/README.md | 5 +- drivers/i2c/adafruit2327_driver.go | 45 ++ drivers/i2c/adafruit2327_driver_test.go | 94 +++ drivers/i2c/adafruit2348_driver.go | 334 +++++++++++ drivers/i2c/adafruit2348_driver_test.go | 162 +++++ drivers/i2c/adafruit_driver.go | 567 ------------------ drivers/i2c/adafruit_driver_test.go | 245 -------- drivers/i2c/pca9685_driver.go | 112 ++-- drivers/i2c/pca9685_driver_test.go | 320 ++++++++-- ...t_servo.go => raspi_adafruit2327_servo.go} | 56 +- ...motor.go => raspi_adafruit2348_dcmotor.go} | 52 +- ...epper.go => raspi_adafruit2348_stepper.go} | 44 +- 14 files changed, 1037 insertions(+), 1005 deletions(-) create mode 100644 drivers/i2c/adafruit2327_driver.go create mode 100644 drivers/i2c/adafruit2327_driver_test.go create mode 100644 drivers/i2c/adafruit2348_driver.go create mode 100644 drivers/i2c/adafruit2348_driver_test.go delete mode 100644 drivers/i2c/adafruit_driver.go delete mode 100644 drivers/i2c/adafruit_driver_test.go rename examples/{raspi_adafruit_servo.go => raspi_adafruit2327_servo.go} (90%) rename examples/{raspi_adafruit_dcmotor.go => raspi_adafruit2348_dcmotor.go} (64%) rename examples/{raspi_adafruit_stepper.go => raspi_adafruit2348_stepper.go} (65%) diff --git a/.golangci.yml b/.golangci.yml index 4466f95f4..9b907888c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -88,7 +88,6 @@ linters: - exhaustruct # useful with some exclusions for existing code (e.g. mavlink/common/common.go) - funlen # useful with some tweeks (reduce bugs, simplify code, better understandable code) - gci # useful (improve readability) - - gochecknoinits # useful (reduce bugs, simplify bug catching) - gocognit # useful with some tweeks (better understandable code) - goconst # useful (reduce bugs) - gocritic # useful with some exclusions for existing code (e.g. mavlink/common/common.go) diff --git a/README.md b/README.md index f14c67628..8a1a4310a 100644 --- a/README.md +++ b/README.md @@ -309,8 +309,9 @@ Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of drivers provided using the `gobot/drivers/i2c` package: - [I2C](https://en.wikipedia.org/wiki/I%C2%B2C) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/i2c) - - Adafruit 2x16 RGB-LCD with 5 keys - - Adafruit Motor Hat + - Adafruit 1109 2x16 RGB-LCD with 5 keys + - Adafruit 2327 16-Channel PWM/Servo HAT Hat + - Adafruit 2348 DC and Stepper Motor Hat - ADS1015 Analog to Digital Converter - ADS1115 Analog to Digital Converter - ADXL345 Digital Accelerometer diff --git a/drivers/i2c/README.md b/drivers/i2c/README.md index b17c583a5..ea6e4ba32 100644 --- a/drivers/i2c/README.md +++ b/drivers/i2c/README.md @@ -12,8 +12,9 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r Gobot has a extensible system for connecting to hardware devices. The following i2c devices are currently supported: -- Adafruit 2x16 RGB-LCD with 5 keys -- Adafruit Motor Hat +- Adafruit 1109 2x16 RGB-LCD with 5 keys +- Adafruit 2327 16-Channel PWM/Servo HAT Hat +- Adafruit 2348 DC and Stepper Motor Hat - ADS1015 Analog to Digital Converter - ADS1115 Analog to Digital Converter - ADXL345 Digital Accelerometer diff --git a/drivers/i2c/adafruit2327_driver.go b/drivers/i2c/adafruit2327_driver.go new file mode 100644 index 000000000..c26ff5d87 --- /dev/null +++ b/drivers/i2c/adafruit2327_driver.go @@ -0,0 +1,45 @@ +package i2c + +import ( + "gobot.io/x/gobot/v2" +) + +// Adafruit2327Driver is a driver for Adafruit 16-Channel PWM/Servo HAT & Bonnet - a Raspberry Pi add-on, based on +// PCA9685. This driver just wraps the PCA9685Driver. +// Stacking 62 of them is possible (addresses 0x40..0x7E), for controlling up to 992 servos. +// datasheet: +// https://cdn-learn.adafruit.com/downloads/pdf/adafruit-16-channel-pwm-servo-hat-for-raspberry-pi.pdf +type Adafruit2327Driver struct { + *PCA9685Driver +} + +// NewAdafruit2327Driver initializes a new driver for PWM servos. +// Params: +// +// c Connector - the Adaptor to use with this Driver +// +// Optional params: +// +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver +func NewAdafruit2327Driver(c Connector, options ...func(Config)) *Adafruit2327Driver { + pca := NewPCA9685Driver(c, options...) // the default address of the driver is already 0x40 + pca.SetName(gobot.DefaultName("Adafruit2327ServoHat")) + d := &Adafruit2327Driver{ + PCA9685Driver: pca, + } + + // TODO: add API funcs + return d +} + +// SetServoMotorFreq sets the frequency for the currently addressed PWM Servo HAT. +func (a *Adafruit2327Driver) SetServoMotorFreq(freq float64) error { + return a.SetPWMFreq(float32(freq)) +} + +// SetServoMotorPulse is a convenience function to specify the 'tick' value, +// between 0-4095, when the signal will turn on, and when it will turn off. +func (a *Adafruit2327Driver) SetServoMotorPulse(channel byte, on, off int32) error { + return a.SetPWM(int(channel), uint16(on), uint16(off)) +} diff --git a/drivers/i2c/adafruit2327_driver_test.go b/drivers/i2c/adafruit2327_driver_test.go new file mode 100644 index 000000000..9690be1fa --- /dev/null +++ b/drivers/i2c/adafruit2327_driver_test.go @@ -0,0 +1,94 @@ +package i2c + +import ( + "errors" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" +) + +// this ensures that the implementation implements the gobot.Driver interface +var _ gobot.Driver = (*Adafruit2327Driver)(nil) + +func initTestAdafruit2327WithStubbedAdaptor() (*Adafruit2327Driver, *i2cTestAdaptor) { + a := newI2cTestAdaptor() + d := NewAdafruit2327Driver(a) + if err := d.Start(); err != nil { + panic(err) + } + return d, a +} + +func TestNewAdafruit2327Driver(t *testing.T) { + // arrange & act + d := NewAdafruit2327Driver(newI2cTestAdaptor()) + // assert + assert.IsType(t, &Adafruit2327Driver{}, d) + assert.True(t, strings.HasPrefix(d.Name(), "Adafruit2327ServoHat")) + assert.Equal(t, 0x40, d.defaultAddress) +} + +func TestAdafruit2327Options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithBus() option and + // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". + // arrange & act + d := NewAdafruit2327Driver(newI2cTestAdaptor(), WithBus(2)) + // assert + assert.Equal(t, 2, d.GetBusOrDefault(1)) +} + +func TestAdafruit2327SetServoMotorFreq(t *testing.T) { + // arrange + d, a := initTestAdafruit2327WithStubbedAdaptor() + a.written = []byte{} // reset writes of former test + const freq = 60.0 + // act + err := d.SetServoMotorFreq(freq) + // assert + assert.NoError(t, err) + assert.Equal(t, 9, len(a.written)) // detailed test, see "TestPCA9685SetPWMFreq" +} + +func TestAdafruit2327SetServoMotorFreqError(t *testing.T) { + // arrange + d, a := initTestAdafruit2327WithStubbedAdaptor() + a.i2cWriteImpl = func([]byte) (int, error) { + return 0, errors.New("write error") + } + const freq = 60.0 + // act & assert + assert.ErrorContains(t, d.SetServoMotorFreq(freq), "write error") +} + +func TestAdafruit2327SetServoMotorPulse(t *testing.T) { + // arrange + d, a := initTestAdafruit2327WithStubbedAdaptor() + a.written = []byte{} // reset writes of former test + const ( + channel byte = 7 + on int32 = 1234 + off int32 = 4321 + ) + // act + err := d.SetServoMotorPulse(channel, on, off) + // assert + assert.NoError(t, err) + assert.Equal(t, 8, len(a.written)) // detailed test, see "TestPCA9685SetPWM" +} + +func TestAdafruit2327SetServoMotorPulseError(t *testing.T) { + // arrange + d, a := initTestAdafruit2327WithStubbedAdaptor() + a.i2cWriteImpl = func([]byte) (int, error) { + return 0, errors.New("write error") + } + const ( + channel byte = 7 + on int32 = 1234 + off int32 = 4321 + ) + // act & assert + assert.ErrorContains(t, d.SetServoMotorPulse(channel, on, off), "write error") +} diff --git a/drivers/i2c/adafruit2348_driver.go b/drivers/i2c/adafruit2348_driver.go new file mode 100644 index 000000000..f6014b2b6 --- /dev/null +++ b/drivers/i2c/adafruit2348_driver.go @@ -0,0 +1,334 @@ +package i2c + +import ( + "errors" + "log" + "sync" + "time" + + "gobot.io/x/gobot/v2" +) + +const adafruit2348Debug = false // Set this to true to see debug output + +const ( + adafruit2348MotorHatDefaultAddress = 0x60 + adafruit2348StepperMicrosteps = 8 +) + +// Adafruit2348Direction declares a type for specification of the motor direction +type Adafruit2348Direction int + +// Adafruit2348StepStyle declares a type for specification of the stepper motor rotation +type Adafruit2348StepStyle int + +// constants for running the motor in different direction or release +const ( + Adafruit2348Forward Adafruit2348Direction = iota // 0 + Adafruit2348Backward // 1 + Adafruit2348Release // 2 +) + +// constants for running the stepper motor in different modes +const ( + Adafruit2348Single Adafruit2348StepStyle = iota // 0 + Adafruit2348Double // 1 + Adafruit2348Interleave // 2 + Adafruit2348Microstep // 3 +) + +type adafruit2348DCMotor struct { + pwmPin, in1Pin, in2Pin byte +} + +type adafruit2348StepperMotor struct { + pwmPinA, pwmPinB byte + ain1, ain2 byte + bin1, bin2 byte + secPerStep float64 + currentStep, revSteps int +} + +// Adafruit2348Driver is a driver for Adafruit DC and Stepper Motor HAT - a Raspberry Pi add-on, based on PCA9685. +// The HAT can drive up to 4 DC or 2 stepper motors with full PWM speed and direction control over I2C. +// This driver wraps the PCA9685Driver. +// Stacking 32 of them is possible (addresses 0x60..0x80), for controlling up to 64 stepper motors or 128 DC motors. +// datasheet: +// https://cdn-learn.adafruit.com/downloads/pdf/adafruit2348-dc-and-stepper-motor-hat-for-raspberry-pi.pdf +type Adafruit2348Driver struct { + *PCA9685Driver + dcMotors []adafruit2348DCMotor + stepperMotors []adafruit2348StepperMotor + stepperMicrostepCurve []int + step2coils map[int][]int32 + stepperSpeedMutex *sync.Mutex +} + +// NewAdafruit2348Driver initializes a new driver for DC and stepper motors. +// Params: +// +// c Connector - the Adaptor to use with this Driver +// +// Optional params: +// +// i2c.WithBus(int): bus to use with this driver +// i2c.WithAddress(int): address to use with this driver +func NewAdafruit2348Driver(c Connector, options ...func(Config)) *Adafruit2348Driver { + var dc []adafruit2348DCMotor + var st []adafruit2348StepperMotor + for i := 0; i < 4; i++ { + switch { + case i == 0: + dc = append(dc, adafruit2348DCMotor{pwmPin: 8, in1Pin: 10, in2Pin: 9}) + st = append(st, adafruit2348StepperMotor{ + pwmPinA: 8, pwmPinB: 13, + ain1: 10, ain2: 9, bin1: 11, bin2: 12, revSteps: 200, secPerStep: 0.1, + }) + case i == 1: + dc = append(dc, adafruit2348DCMotor{pwmPin: 13, in1Pin: 11, in2Pin: 12}) + st = append(st, adafruit2348StepperMotor{ + pwmPinA: 2, pwmPinB: 7, + ain1: 4, ain2: 3, bin1: 5, bin2: 6, revSteps: 200, secPerStep: 0.1, + }) + case i == 2: + dc = append(dc, adafruit2348DCMotor{pwmPin: 2, in1Pin: 4, in2Pin: 3}) + case i == 3: + dc = append(dc, adafruit2348DCMotor{pwmPin: 7, in1Pin: 5, in2Pin: 6}) + } + } + + // external given address must be able to override the default one + o := append([]func(Config){WithAddress(adafruit2348MotorHatDefaultAddress)}, options...) + pca := NewPCA9685Driver(c, o...) + pca.SetName(gobot.DefaultName("Adafruit2348MotorHat")) + d := &Adafruit2348Driver{ + PCA9685Driver: pca, + dcMotors: dc, + stepperMotors: st, + stepperMicrostepCurve: []int{0, 50, 98, 142, 180, 212, 236, 250, 255}, + step2coils: map[int][]int32{ + 0: {1, 0, 0, 0}, + 1: {1, 1, 0, 0}, + 2: {0, 1, 0, 0}, + 3: {0, 1, 1, 0}, + 4: {0, 0, 1, 0}, + 5: {0, 0, 1, 1}, + 6: {0, 0, 0, 1}, + 7: {1, 0, 0, 1}, + }, + stepperSpeedMutex: &sync.Mutex{}, + } + + // TODO: add API funcs + return d +} + +// SetDCMotorSpeed will set the appropriate pins to run the specified DC motor for the given speed. +func (a *Adafruit2348Driver) SetDCMotorSpeed(dcMotor int, speed int32) error { + return a.SetPWM(int(a.dcMotors[dcMotor].pwmPin), 0, uint16(speed*16)) +} + +// RunDCMotor will set the appropriate pins to run the specified DC motor for the given direction. +func (a *Adafruit2348Driver) RunDCMotor(dcMotor int, dir Adafruit2348Direction) error { + switch { + case dir == Adafruit2348Forward: + if err := a.setPin(a.dcMotors[dcMotor].in2Pin, 0); err != nil { + return err + } + if err := a.setPin(a.dcMotors[dcMotor].in1Pin, 1); err != nil { + return err + } + case dir == Adafruit2348Backward: + if err := a.setPin(a.dcMotors[dcMotor].in1Pin, 0); err != nil { + return err + } + if err := a.setPin(a.dcMotors[dcMotor].in2Pin, 1); err != nil { + return err + } + case dir == Adafruit2348Release: + if err := a.setPin(a.dcMotors[dcMotor].in1Pin, 0); err != nil { + return err + } + if err := a.setPin(a.dcMotors[dcMotor].in2Pin, 0); err != nil { + return err + } + } + return nil +} + +// SetStepperMotorSpeed sets the seconds-per-step for the given stepper motor. It is applied in the next cycle. +func (a *Adafruit2348Driver) SetStepperMotorSpeed(stepperMotor int, rpm int) error { + a.stepperSpeedMutex.Lock() + defer a.stepperSpeedMutex.Unlock() + + revSteps := a.stepperMotors[stepperMotor].revSteps + a.stepperMotors[stepperMotor].secPerStep = 60.0 / float64(revSteps*rpm) + return nil +} + +// Step will rotate the stepper motor the given number of steps, in the given direction and step style. +func (a *Adafruit2348Driver) Step(motor, steps int, dir Adafruit2348Direction, style Adafruit2348StepStyle) error { + a.stepperSpeedMutex.Lock() + defer a.stepperSpeedMutex.Unlock() + + secPerStep := a.stepperMotors[motor].secPerStep + var latestStep int + var err error + if style == Adafruit2348Interleave { + secPerStep = secPerStep / 2.0 + } + if style == Adafruit2348Microstep { + secPerStep /= float64(adafruit2348StepperMicrosteps) + steps *= adafruit2348StepperMicrosteps + } + if adafruit2348Debug { + log.Printf("[adafruit2348_driver] %f seconds per step", secPerStep) + } + for i := 0; i < steps; i++ { + if latestStep, err = a.oneStep(motor, dir, style); err != nil { + return err + } + time.Sleep(time.Duration(secPerStep) * time.Second) + } + // As documented in the Adafruit python driver: + // This is an edge case, if we are in between full steps, keep going to end on a full step + if style == Adafruit2348Microstep { + for latestStep != 0 && latestStep != adafruit2348StepperMicrosteps { + if latestStep, err = a.oneStep(motor, dir, style); err != nil { + return err + } + time.Sleep(time.Duration(secPerStep) * time.Second) + } + } + return nil +} + +func (a *Adafruit2348Driver) oneStep(motor int, dir Adafruit2348Direction, style Adafruit2348StepStyle) (int, error) { + pwmA := 255 + pwmB := 255 + + // Determine the stepping procedure + switch { + case style == Adafruit2348Single: + if (a.stepperMotors[motor].currentStep / (adafruit2348StepperMicrosteps / 2) % 2) != 0 { + // we're at an odd step + if dir == Adafruit2348Forward { + a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2 + } else { + a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2 + } + } else { + // go to next even step + if dir == Adafruit2348Forward { + a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps + } else { + a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps + } + } + case style == Adafruit2348Double: + if (a.stepperMotors[motor].currentStep / (adafruit2348StepperMicrosteps / 2) % 2) == 0 { + // we're at an even step, weird + if dir == Adafruit2348Forward { + a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2 + } else { + a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2 + } + } else { + // go to next odd step + if dir == Adafruit2348Forward { + a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps + } else { + a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps + } + } + case style == Adafruit2348Interleave: + if dir == Adafruit2348Forward { + a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2 + } else { + a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2 + } + case style == Adafruit2348Microstep: + if dir == Adafruit2348Forward { + a.stepperMotors[motor].currentStep++ + } else { + a.stepperMotors[motor].currentStep-- + } + // go to next step and wrap around + a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps * 4 + a.stepperMotors[motor].currentStep %= adafruit2348StepperMicrosteps * 4 + + pwmA = 0 + pwmB = 0 + currStep := a.stepperMotors[motor].currentStep + if currStep >= 0 && currStep < adafruit2348StepperMicrosteps { + pwmA = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps-currStep] + pwmB = a.stepperMicrostepCurve[currStep] + } else if currStep >= adafruit2348StepperMicrosteps && currStep < adafruit2348StepperMicrosteps*2 { + pwmA = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps] + pwmB = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*2-currStep] + } else if currStep >= adafruit2348StepperMicrosteps*2 && currStep < adafruit2348StepperMicrosteps*3 { + pwmA = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*3-currStep] + pwmB = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps*2] + } else if currStep >= adafruit2348StepperMicrosteps*3 && currStep < adafruit2348StepperMicrosteps*4 { + pwmA = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps*3] + pwmB = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*4-currStep] + } + } // switch + + // go to next 'step' and wrap around + a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps * 4 + a.stepperMotors[motor].currentStep %= adafruit2348StepperMicrosteps * 4 + + // only really used for microstepping, otherwise always on! + if err := a.SetPWM(int(a.stepperMotors[motor].pwmPinA), 0, uint16(pwmA*16)); err != nil { + return 0, err + } + if err := a.SetPWM(int(a.stepperMotors[motor].pwmPinB), 0, uint16(pwmB*16)); err != nil { + return 0, err + } + var coils []int32 + currStep := a.stepperMotors[motor].currentStep + if style == Adafruit2348Microstep { + switch { + case currStep >= 0 && currStep < adafruit2348StepperMicrosteps: + coils = []int32{1, 1, 0, 0} + case currStep >= adafruit2348StepperMicrosteps && currStep < adafruit2348StepperMicrosteps*2: + coils = []int32{0, 1, 1, 0} + case currStep >= adafruit2348StepperMicrosteps*2 && currStep < adafruit2348StepperMicrosteps*3: + coils = []int32{0, 0, 1, 1} + case currStep >= adafruit2348StepperMicrosteps*3 && currStep < adafruit2348StepperMicrosteps*4: + coils = []int32{1, 0, 0, 1} + } + } else { + // step-2-coils is initialized in init() + coils = a.step2coils[(currStep / (adafruit2348StepperMicrosteps / 2))] + } + if adafruit2348Debug { + log.Printf("[adafruit2348_driver] currStep: %d, index into step2coils: %d\n", + currStep, (currStep / (adafruit2348StepperMicrosteps / 2))) + log.Printf("[adafruit2348_driver] coils state = %v", coils) + } + if err := a.setPin(a.stepperMotors[motor].ain2, coils[0]); err != nil { + return 0, err + } + if err := a.setPin(a.stepperMotors[motor].bin1, coils[1]); err != nil { + return 0, err + } + if err := a.setPin(a.stepperMotors[motor].ain1, coils[2]); err != nil { + return 0, err + } + if err := a.setPin(a.stepperMotors[motor].bin2, coils[3]); err != nil { + return 0, err + } + return a.stepperMotors[motor].currentStep, nil +} + +func (a *Adafruit2348Driver) setPin(pin byte, value int32) error { + if value == 0 { + return a.SetPWM(int(pin), 0, 4096) + } + if value == 1 { + return a.SetPWM(int(pin), 4096, 0) + } + return errors.New("Invalid pin") +} diff --git a/drivers/i2c/adafruit2348_driver_test.go b/drivers/i2c/adafruit2348_driver_test.go new file mode 100644 index 000000000..d668034cf --- /dev/null +++ b/drivers/i2c/adafruit2348_driver_test.go @@ -0,0 +1,162 @@ +package i2c + +import ( + "errors" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" +) + +// this ensures that the implementation implements the gobot.Driver interface +var _ gobot.Driver = (*Adafruit2348Driver)(nil) + +func initTestAdafruit2348WithStubbedAdaptor() (*Adafruit2348Driver, *i2cTestAdaptor) { + a := newI2cTestAdaptor() + d := NewAdafruit2348Driver(a) + if err := d.Start(); err != nil { + panic(err) + } + return d, a +} + +func TestNewAdafruit2348Driver(t *testing.T) { + // arrange & act + d := NewAdafruit2348Driver(newI2cTestAdaptor()) + // assert + assert.IsType(t, &Adafruit2348Driver{}, d) + assert.True(t, strings.HasPrefix(d.Name(), "Adafruit2348MotorHat")) + assert.Equal(t, 0x40, d.defaultAddress) // the default address of PCA9685 driver + assert.Equal(t, 0x60, d.Config.GetAddressOrDefault(d.defaultAddress)) // the really used address +} + +func TestAdafruit2348Options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithBus() option and + // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". + // arrange & act + d := NewAdafruit2348Driver(newI2cTestAdaptor(), WithBus(2), WithAddress(0x45)) + // assert + assert.Equal(t, 2, d.GetBusOrDefault(1)) + assert.Equal(t, 0x45, d.GetAddressOrDefault(2)) +} + +func TestAdafruit2348SetDCMotorSpeed(t *testing.T) { + // arrange + d, a := initTestAdafruit2348WithStubbedAdaptor() + a.written = []byte{} // reset writes of former test + const ( + dcMotor = 1 + speed = 255 + ) + // act + err := d.SetDCMotorSpeed(dcMotor, speed) + // assert + assert.NoError(t, err) + assert.Equal(t, 8, len(a.written)) // detailed test, see "TestPCA9685SetPWM" +} + +func TestAdafruit2348SetDCMotorSpeedError(t *testing.T) { + // arrange + d, a := initTestAdafruit2348WithStubbedAdaptor() + a.i2cWriteImpl = func([]byte) (int, error) { + return 0, errors.New("write error") + } + // act & assert + assert.ErrorContains(t, d.SetDCMotorSpeed(1, 255), "write error") +} + +func TestAdafruit2348RunDCMotor(t *testing.T) { + // arrange + d, _ := initTestAdafruit2348WithStubbedAdaptor() + const dcMotor = 1 + // act & assert + assert.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Forward)) + assert.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Backward)) + assert.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Release)) +} + +func TestAdafruit2348RunDCMotorError(t *testing.T) { + // arrange + d, a := initTestAdafruit2348WithStubbedAdaptor() + a.i2cWriteImpl = func([]byte) (int, error) { + return 0, errors.New("write error") + } + const dcMotor = 1 + // act & assert + assert.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Forward), "write error") + assert.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Backward), "write error") + assert.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Release), "write error") +} + +func TestAdafruit2348SetStepperMotorSpeed(t *testing.T) { + // arrange + d, _ := initTestAdafruit2348WithStubbedAdaptor() + const ( + stepperMotor = 1 + rpm = 30 + ) + // act & assert + assert.NoError(t, d.SetStepperMotorSpeed(stepperMotor, rpm)) + assert.Equal(t, 0.01, d.stepperMotors[stepperMotor].secPerStep) // 60/(revSteps*rpm), revSteps=200 +} + +func TestAdafruit2348StepperSingleStep(t *testing.T) { + // arrange + d, _ := initTestAdafruit2348WithStubbedAdaptor() + const ( + stepperMotor = 0 + steps = 50 + back = 1 + single = 0 + ) + // act + err := d.Step(stepperMotor, steps, back, single) + // assert + assert.NoError(t, err) +} + +func TestAdafruit2348StepperDoubleStep(t *testing.T) { + // arrange + d, _ := initTestAdafruit2348WithStubbedAdaptor() + const ( + stepperMotor = 0 + steps = 50 + back = 1 + double = 1 + ) + // act + err := d.Step(stepperMotor, steps, back, double) + // assert + assert.NoError(t, err) +} + +func TestAdafruit2348StepperInterleaveStep(t *testing.T) { + // arrange + d, _ := initTestAdafruit2348WithStubbedAdaptor() + const ( + stepperMotor = 0 + steps = 50 + back = 1 + interleave = 2 + ) + // act + err := d.Step(stepperMotor, steps, back, interleave) + // assert + assert.NoError(t, err) +} + +func TestAdafruit2348StepperMicroStep(t *testing.T) { + // arrange + d, _ := initTestAdafruit2348WithStubbedAdaptor() + const ( + stepperMotor = 0 + steps = 50 + back = 1 + micro = 3 + ) + // act + err := d.Step(stepperMotor, steps, back, micro) + // assert + assert.NoError(t, err) +} diff --git a/drivers/i2c/adafruit_driver.go b/drivers/i2c/adafruit_driver.go deleted file mode 100644 index 3db354005..000000000 --- a/drivers/i2c/adafruit_driver.go +++ /dev/null @@ -1,567 +0,0 @@ -package i2c - -import ( - "errors" - "log" - "math" - "time" - - "gobot.io/x/gobot/v2" -) - -// AdafruitDirection declares a type for specification of the motor direction -type AdafruitDirection int - -// AdafruitStepStyle declares a type for specification of the stepper motor rotation -type AdafruitStepStyle int - -type adaFruitDCMotor struct { - pwmPin, in1Pin, in2Pin byte -} -type adaFruitStepperMotor struct { - pwmPinA, pwmPinB byte - ain1, ain2 byte - bin1, bin2 byte - secPerStep float64 - currentStep, stepCounter, revSteps int -} - -// AdafruitMotorHatDriver is a driver for the DC+Stepper Motor HAT from Adafruit. -// The HAT is a Raspberry Pi add-on that can drive up to 4 DC or 2 Stepper motors -// with full PWM speed control. It has a dedicated PWM driver chip onboard to -// control both motor direction and speed over I2C. -type AdafruitMotorHatDriver struct { - name string - connector Connector - motorHatConnection Connection - servoHatConnection Connection - Config - gobot.Commander - dcMotors []adaFruitDCMotor - stepperMotors []adaFruitStepperMotor -} - -var adafruitDebug = false // Set this to true to see debug output - -var ( - // Each Adafruit HAT must have a unique I2C address. The default address for - // the DC and Stepper Motor HAT is 0x60. The addresses of the Motor HATs can - // range from 0x60 to 0x80 for a total of 32 unique addresses. - // The base address for the Adafruit PWM-Servo HAT is 0x40. Please consult - // the Adafruit documentation for soldering and addressing stacked HATs. - motorHatAddress = 0x60 - servoHatAddress = 0x40 - stepperMicrosteps = 8 - stepperMicrostepCurve []int - step2coils = make(map[int][]int32) -) - -const ( - // Registers - _Mode1 = 0x00 - _Mode2 = 0x01 - _SubAdr1 = 0x02 - _SubAdr2 = 0x03 - _SubAdr3 = 0x04 - _Prescale = 0xFE - _LedZeroOnL = 0x06 - _LedZeroOnH = 0x07 - _LedZeroOffL = 0x08 - _LedZeroOffH = 0x09 - _AllLedOnL = 0xFA - _AllLedOnH = 0xFB - _AllLedOffL = 0xFC - _AllLedOffH = 0xFD - - // Bits - _Restart = 0x80 - _Sleep = 0x10 - _AllCall = 0x01 - _Invrt = 0x10 - _Outdrv = 0x04 -) - -const ( - AdafruitForward AdafruitDirection = iota // 0 - AdafruitBackward // 1 - AdafruitRelease // 2 -) - -const ( - AdafruitSingle AdafruitStepStyle = iota // 0 - AdafruitDouble // 1 - AdafruitInterleave // 2 - AdafruitMicrostep // 3 -) - -// NewAdafruitMotorHatDriver initializes the internal DCMotor and StepperMotor types. -// Again the Adafruit Motor Hat supports up to four DC motors and up to two stepper motors. -// Params: -// -// conn Connector - the Adaptor to use with this Driver -// -// Optional params: -// -// i2c.WithBus(int): bus to use with this driver -// i2c.WithAddress(int): address to use with this driver -func NewAdafruitMotorHatDriver(conn Connector, options ...func(Config)) *AdafruitMotorHatDriver { - var dc []adaFruitDCMotor - var st []adaFruitStepperMotor - for i := 0; i < 4; i++ { - switch { - case i == 0: - dc = append(dc, adaFruitDCMotor{pwmPin: 8, in1Pin: 10, in2Pin: 9}) - st = append(st, adaFruitStepperMotor{ - pwmPinA: 8, pwmPinB: 13, - ain1: 10, ain2: 9, bin1: 11, bin2: 12, revSteps: 200, secPerStep: 0.1, - }) - case i == 1: - dc = append(dc, adaFruitDCMotor{pwmPin: 13, in1Pin: 11, in2Pin: 12}) - st = append(st, adaFruitStepperMotor{ - pwmPinA: 2, pwmPinB: 7, - ain1: 4, ain2: 3, bin1: 5, bin2: 6, revSteps: 200, secPerStep: 0.1, - }) - case i == 2: - dc = append(dc, adaFruitDCMotor{pwmPin: 2, in1Pin: 4, in2Pin: 3}) - case i == 3: - dc = append(dc, adaFruitDCMotor{pwmPin: 7, in1Pin: 5, in2Pin: 6}) - } - } - - driver := &AdafruitMotorHatDriver{ - name: gobot.DefaultName("AdafruitMotorHat"), - connector: conn, - Config: NewConfig(), - Commander: gobot.NewCommander(), - dcMotors: dc, - stepperMotors: st, - } - - for _, option := range options { - option(driver) - } - - // TODO: add API funcs - return driver -} - -// SetMotorHatAddress sets the I2C address for the DC and Stepper Motor HAT. -// This addressing flexibility empowers "stacking" the HATs. -func (a *AdafruitMotorHatDriver) SetMotorHatAddress(addr int) (err error) { - motorHatAddress = addr - return -} - -// SetServoHatAddress sets the I2C address for the PWM-Servo Motor HAT. -// This addressing flexibility empowers "stacking" the HATs. -func (a *AdafruitMotorHatDriver) SetServoHatAddress(addr int) (err error) { - servoHatAddress = addr - return -} - -// Name identifies this driver object -func (a *AdafruitMotorHatDriver) Name() string { return a.name } - -// SetName sets nae for driver -func (a *AdafruitMotorHatDriver) SetName(n string) { a.name = n } - -// Connection identifies the particular adapter object -func (a *AdafruitMotorHatDriver) Connection() gobot.Connection { return a.connector.(gobot.Connection) } - -func (a *AdafruitMotorHatDriver) startDriver(connection Connection) (err error) { - if err = a.setAllPWM(connection, 0, 0); err != nil { - return - } - reg := byte(_Mode2) - val := byte(_Outdrv) - if _, err = connection.Write([]byte{reg, val}); err != nil { - return - } - reg = byte(_Mode1) - val = byte(_AllCall) - if _, err = connection.Write([]byte{reg, val}); err != nil { - return - } - time.Sleep(5 * time.Millisecond) - - // Read a byte from the I2C device. Note: no ability to read from a specified reg? - mode1 := []byte{0} - _, rerr := connection.Read(mode1) - if rerr != nil { - return rerr - } - if len(mode1) > 0 { - reg = byte(_Mode1) - val = mode1[0] & _Sleep - if _, err = connection.Write([]byte{reg, val}); err != nil { - return - } - time.Sleep(5 * time.Millisecond) - } - - return -} - -// Start initializes both I2C-addressable Adafruit Motor HAT drivers -func (a *AdafruitMotorHatDriver) Start() (err error) { - bus := a.GetBusOrDefault(a.connector.DefaultI2cBus()) - - err = a.startServoHat(bus) - if adafruitDebug && err != nil { - log.Printf("[adafruit_driver] start servohat error: %s\n", err) - } - - err = a.startMotorHat(bus) - if adafruitDebug && err != nil { - log.Printf("[adafruit_driver] start motorhat error: %s\n", err) - } - - return -} - -// startServoHat starts the Servo motors connection. -func (a *AdafruitMotorHatDriver) startServoHat(bus int) (err error) { - if a.servoHatConnection, err = a.connector.GetI2cConnection(servoHatAddress, bus); err != nil { - return - } - - if err = a.startDriver(a.servoHatConnection); err != nil { - return - } - - return -} - -// startMotorHat starts the DC motors connection. -func (a *AdafruitMotorHatDriver) startMotorHat(bus int) (err error) { - if a.motorHatConnection, err = a.connector.GetI2cConnection(motorHatAddress, bus); err != nil { - return - } - - if err = a.startDriver(a.motorHatConnection); err != nil { - return - } - - return -} - -// Halt returns true if devices is halted successfully -func (a *AdafruitMotorHatDriver) Halt() (err error) { return } - -// setPWM sets the start (on) and end (off) of the high-segment of the PWM pulse -// on the specific channel (pin). -func (a *AdafruitMotorHatDriver) setPWM(conn Connection, pin byte, on, off int32) (err error) { - // register and values to be written to that register - regVals := make(map[int][]byte) - regVals[0] = []byte{_LedZeroOnL + 4*pin, byte(on & 0xff)} - regVals[1] = []byte{_LedZeroOnH + 4*pin, byte(on >> 8)} - regVals[2] = []byte{_LedZeroOffL + 4*pin, byte(off & 0xff)} - regVals[3] = []byte{_LedZeroOffH + 4*pin, byte(off >> 8)} - for i := 0; i < len(regVals); i++ { - if _, err = conn.Write(regVals[i]); err != nil { - return - } - } - return -} - -// SetServoMotorFreq sets the frequency for the currently addressed PWM Servo HAT. -func (a *AdafruitMotorHatDriver) SetServoMotorFreq(freq float64) (err error) { - if err = a.setPWMFreq(a.servoHatConnection, freq); err != nil { - return - } - return -} - -// SetServoMotorPulse is a convenience function to specify the 'tick' value, -// between 0-4095, when the signal will turn on, and when it will turn off. -func (a *AdafruitMotorHatDriver) SetServoMotorPulse(channel byte, on, off int32) (err error) { - if err = a.setPWM(a.servoHatConnection, channel, on, off); err != nil { - return - } - return -} - -// setPWMFreq adjusts the PWM frequency which determines how many full -// pulses per second are generated by the integrated circuit. The frequency -// determines how "long" each pulse is in duration from start to finish, -// taking into account the high and low segments of the pulse. -func (a *AdafruitMotorHatDriver) setPWMFreq(conn Connection, freq float64) (err error) { - // 25MHz - preScaleVal := 25000000.0 - // 12-bit - preScaleVal /= 4096.0 - preScaleVal /= freq - preScaleVal -= 1.0 - preScale := math.Floor(preScaleVal + 0.5) - if adafruitDebug { - log.Printf("Setting PWM frequency to: %.2f Hz", freq) - log.Printf("Estimated pre-scale: %.2f", preScaleVal) - log.Printf("Final pre-scale: %.2f", preScale) - } - // default (and only) reads register 0 - oldMode := []byte{0} - _, err = conn.Read(oldMode) - if err != nil { - return - } - // sleep? - if len(oldMode) > 0 { - newMode := (oldMode[0] & 0x7F) | 0x10 - reg := byte(_Mode1) - if _, err = conn.Write([]byte{reg, newMode}); err != nil { - return - } - reg = byte(_Prescale) - val := byte(math.Floor(preScale)) - if _, err = conn.Write([]byte{reg, val}); err != nil { - return - } - reg = byte(_Mode1) - if _, err = conn.Write([]byte{reg, oldMode[0]}); err != nil { - return - } - time.Sleep(5 * time.Millisecond) - if _, err = conn.Write([]byte{reg, (oldMode[0] | 0x80)}); err != nil { - return - } - } - return -} - -// setAllPWM sets all PWM channels for the given address -func (a *AdafruitMotorHatDriver) setAllPWM(conn Connection, on, off int32) (err error) { - // register and values to be written to that register - regVals := make(map[int][]byte) - regVals[0] = []byte{byte(_AllLedOnL), byte(on & 0xff)} - regVals[1] = []byte{byte(_AllLedOnH), byte(on >> 8)} - regVals[2] = []byte{byte(_AllLedOffL), byte(off & 0xFF)} - regVals[3] = []byte{byte(_AllLedOffH), byte(off >> 8)} - for i := 0; i < len(regVals); i++ { - if _, err = conn.Write(regVals[i]); err != nil { - return - } - } - return -} - -func (a *AdafruitMotorHatDriver) setPin(conn Connection, pin byte, value int32) (err error) { - if value == 0 { - return a.setPWM(conn, pin, 0, 4096) - } - if value == 1 { - return a.setPWM(conn, pin, 4096, 0) - } - return errors.New("Invalid pin") -} - -// SetDCMotorSpeed will set the appropriate pins to run the specified DC motor -// for the given speed. -func (a *AdafruitMotorHatDriver) SetDCMotorSpeed(dcMotor int, speed int32) (err error) { - if err = a.setPWM(a.motorHatConnection, a.dcMotors[dcMotor].pwmPin, 0, speed*16); err != nil { - return - } - return -} - -// RunDCMotor will set the appropriate pins to run the specified DC motor for -// the given direction -func (a *AdafruitMotorHatDriver) RunDCMotor(dcMotor int, dir AdafruitDirection) (err error) { - switch { - case dir == AdafruitForward: - if err = a.setPin(a.motorHatConnection, a.dcMotors[dcMotor].in2Pin, 0); err != nil { - return - } - if err = a.setPin(a.motorHatConnection, a.dcMotors[dcMotor].in1Pin, 1); err != nil { - return - } - case dir == AdafruitBackward: - if err = a.setPin(a.motorHatConnection, a.dcMotors[dcMotor].in1Pin, 0); err != nil { - return - } - if err = a.setPin(a.motorHatConnection, a.dcMotors[dcMotor].in2Pin, 1); err != nil { - return - } - case dir == AdafruitRelease: - if err = a.setPin(a.motorHatConnection, a.dcMotors[dcMotor].in1Pin, 0); err != nil { - return - } - if err = a.setPin(a.motorHatConnection, a.dcMotors[dcMotor].in2Pin, 0); err != nil { - return - } - } - return -} - -func (a *AdafruitMotorHatDriver) oneStep(motor int, dir AdafruitDirection, style AdafruitStepStyle) (steps int, err error) { - pwmA := 255 - pwmB := 255 - - // Determine the stepping procedure - switch { - case style == AdafruitSingle: - if (a.stepperMotors[motor].currentStep / (stepperMicrosteps / 2) % 2) != 0 { - // we're at an odd step - if dir == AdafruitForward { - a.stepperMotors[motor].currentStep += stepperMicrosteps / 2 - } else { - a.stepperMotors[motor].currentStep -= stepperMicrosteps / 2 - } - } else { - // go to next even step - if dir == AdafruitForward { - a.stepperMotors[motor].currentStep += stepperMicrosteps - } else { - a.stepperMotors[motor].currentStep -= stepperMicrosteps - } - } - case style == AdafruitDouble: - if (a.stepperMotors[motor].currentStep / (stepperMicrosteps / 2) % 2) == 0 { - // we're at an even step, weird - if dir == AdafruitForward { - a.stepperMotors[motor].currentStep += stepperMicrosteps / 2 - } else { - a.stepperMotors[motor].currentStep -= stepperMicrosteps / 2 - } - } else { - // go to next odd step - if dir == AdafruitForward { - a.stepperMotors[motor].currentStep += stepperMicrosteps - } else { - a.stepperMotors[motor].currentStep -= stepperMicrosteps - } - } - case style == AdafruitInterleave: - if dir == AdafruitForward { - a.stepperMotors[motor].currentStep += stepperMicrosteps / 2 - } else { - a.stepperMotors[motor].currentStep -= stepperMicrosteps / 2 - } - case style == AdafruitMicrostep: - if dir == AdafruitForward { - a.stepperMotors[motor].currentStep++ - } else { - a.stepperMotors[motor].currentStep-- - } - // go to next step and wrap around - a.stepperMotors[motor].currentStep += stepperMicrosteps * 4 - a.stepperMotors[motor].currentStep %= stepperMicrosteps * 4 - - pwmA = 0 - pwmB = 0 - currStep := a.stepperMotors[motor].currentStep - if currStep >= 0 && currStep < stepperMicrosteps { - pwmA = stepperMicrostepCurve[stepperMicrosteps-currStep] - pwmB = stepperMicrostepCurve[currStep] - } else if currStep >= stepperMicrosteps && currStep < stepperMicrosteps*2 { - pwmA = stepperMicrostepCurve[currStep-stepperMicrosteps] - pwmB = stepperMicrostepCurve[stepperMicrosteps*2-currStep] - } else if currStep >= stepperMicrosteps*2 && currStep < stepperMicrosteps*3 { - pwmA = stepperMicrostepCurve[stepperMicrosteps*3-currStep] - pwmB = stepperMicrostepCurve[currStep-stepperMicrosteps*2] - } else if currStep >= stepperMicrosteps*3 && currStep < stepperMicrosteps*4 { - pwmA = stepperMicrostepCurve[currStep-stepperMicrosteps*3] - pwmB = stepperMicrostepCurve[stepperMicrosteps*4-currStep] - } - } // switch - - // go to next 'step' and wrap around - a.stepperMotors[motor].currentStep += stepperMicrosteps * 4 - a.stepperMotors[motor].currentStep %= stepperMicrosteps * 4 - - // only really used for microstepping, otherwise always on! - if err = a.setPWM(a.motorHatConnection, a.stepperMotors[motor].pwmPinA, 0, int32(pwmA*16)); err != nil { - return - } - if err = a.setPWM(a.motorHatConnection, a.stepperMotors[motor].pwmPinB, 0, int32(pwmB*16)); err != nil { - return - } - var coils []int32 - currStep := a.stepperMotors[motor].currentStep - if style == AdafruitMicrostep { - switch { - case currStep >= 0 && currStep < stepperMicrosteps: - coils = []int32{1, 1, 0, 0} - case currStep >= stepperMicrosteps && currStep < stepperMicrosteps*2: - coils = []int32{0, 1, 1, 0} - case currStep >= stepperMicrosteps*2 && currStep < stepperMicrosteps*3: - coils = []int32{0, 0, 1, 1} - case currStep >= stepperMicrosteps*3 && currStep < stepperMicrosteps*4: - coils = []int32{1, 0, 0, 1} - } - } else { - // step-2-coils is initialized in init() - coils = step2coils[(currStep / (stepperMicrosteps / 2))] - } - if adafruitDebug { - log.Printf("[adafruit_driver] currStep: %d, index into step2coils: %d\n", - currStep, (currStep / (stepperMicrosteps / 2))) - log.Printf("[adafruit_driver] coils state = %v", coils) - } - if err = a.setPin(a.motorHatConnection, a.stepperMotors[motor].ain2, coils[0]); err != nil { - return - } - if err = a.setPin(a.motorHatConnection, a.stepperMotors[motor].bin1, coils[1]); err != nil { - return - } - if err = a.setPin(a.motorHatConnection, a.stepperMotors[motor].ain1, coils[2]); err != nil { - return - } - if err = a.setPin(a.motorHatConnection, a.stepperMotors[motor].bin2, coils[3]); err != nil { - return - } - return a.stepperMotors[motor].currentStep, nil -} - -// SetStepperMotorSpeed sets the seconds-per-step for the given Stepper Motor. -func (a *AdafruitMotorHatDriver) SetStepperMotorSpeed(stepperMotor int, rpm int) (err error) { - revSteps := a.stepperMotors[stepperMotor].revSteps - a.stepperMotors[stepperMotor].secPerStep = 60.0 / float64(revSteps*rpm) - a.stepperMotors[stepperMotor].stepCounter = 0 - return -} - -// Step will rotate the stepper motor the given number of steps, in the given direction and step style. -func (a *AdafruitMotorHatDriver) Step(motor, steps int, dir AdafruitDirection, style AdafruitStepStyle) (err error) { - secPerStep := a.stepperMotors[motor].secPerStep - latestStep := 0 - if style == AdafruitInterleave { - secPerStep = secPerStep / 2.0 - } - if style == AdafruitMicrostep { - secPerStep /= float64(stepperMicrosteps) - steps *= stepperMicrosteps - } - if adafruitDebug { - log.Printf("[adafruit_driver] %f seconds per step", secPerStep) - } - for i := 0; i < steps; i++ { - if latestStep, err = a.oneStep(motor, dir, style); err != nil { - return - } - time.Sleep(time.Duration(secPerStep) * time.Second) - } - // As documented in the Adafruit python driver: - // This is an edge case, if we are in between full steps, keep going to end on a full step - if style == AdafruitMicrostep { - for latestStep != 0 && latestStep != stepperMicrosteps { - if latestStep, err = a.oneStep(motor, dir, style); err != nil { - return - } - time.Sleep(time.Duration(secPerStep) * time.Second) - } - } - return -} - -func init() { - stepperMicrostepCurve = []int{0, 50, 98, 142, 180, 212, 236, 250, 255} - step2coils[0] = []int32{1, 0, 0, 0} - step2coils[1] = []int32{1, 1, 0, 0} - step2coils[2] = []int32{0, 1, 0, 0} - step2coils[3] = []int32{0, 1, 1, 0} - step2coils[4] = []int32{0, 0, 1, 0} - step2coils[5] = []int32{0, 0, 1, 1} - step2coils[6] = []int32{0, 0, 0, 1} - step2coils[7] = []int32{1, 0, 0, 1} -} diff --git a/drivers/i2c/adafruit_driver_test.go b/drivers/i2c/adafruit_driver_test.go deleted file mode 100644 index e8f2570bb..000000000 --- a/drivers/i2c/adafruit_driver_test.go +++ /dev/null @@ -1,245 +0,0 @@ -package i2c - -import ( - "errors" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "gobot.io/x/gobot/v2" -) - -// this ensures that the implementation implements the gobot.Driver interface -var _ gobot.Driver = (*AdafruitMotorHatDriver)(nil) - -// --------- HELPERS -func initTestAdafruitMotorHatDriver() (driver *AdafruitMotorHatDriver) { - driver, _ = initTestAdafruitMotorHatDriverWithStubbedAdaptor() - return -} - -func initTestAdafruitMotorHatDriverWithStubbedAdaptor() (*AdafruitMotorHatDriver, *i2cTestAdaptor) { - adaptor := newI2cTestAdaptor() - return NewAdafruitMotorHatDriver(adaptor), adaptor -} - -// --------- TESTS -func TestNewAdafruitMotorHatDriver(t *testing.T) { - var di interface{} = NewAdafruitMotorHatDriver(newI2cTestAdaptor()) - d, ok := di.(*AdafruitMotorHatDriver) - if !ok { - t.Errorf("AdafruitMotorHatDriver() should have returned a *AdafruitMotorHatDriver") - } - assert.True(t, strings.HasPrefix(d.Name(), "AdafruitMotorHat")) -} - -// Methods -func TestAdafruitMotorHatDriverStart(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.NotNil(t, ada.Connection()) - assert.NoError(t, ada.Start()) -} - -func TestAdafruitMotorHatDriverStartWriteError(t *testing.T) { - d, adaptor := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - adaptor.i2cWriteImpl = func([]byte) (int, error) { - return 0, errors.New("write error") - } - assert.ErrorContains(t, d.Start(), "write error") -} - -func TestAdafruitMotorHatDriverStartReadError(t *testing.T) { - d, adaptor := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - adaptor.i2cReadImpl = func([]byte) (int, error) { - return 0, errors.New("read error") - } - assert.ErrorContains(t, d.Start(), "read error") -} - -func TestAdafruitMotorHatDriverStartConnectError(t *testing.T) { - d, adaptor := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - adaptor.Testi2cConnectErr(true) - assert.ErrorContains(t, d.Start(), "Invalid i2c connection") -} - -func TestAdafruitMotorHatDriverHalt(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Halt()) -} - -func TestSetHatAddresses(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - motorHatAddr := 0x61 - servoHatAddr := 0x41 - assert.NoError(t, ada.SetMotorHatAddress(motorHatAddr)) - assert.NoError(t, ada.SetServoHatAddress(servoHatAddr)) -} - -func TestAdafruitMotorHatDriverSetServoMotorFreq(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - freq := 60.0 - err := ada.SetServoMotorFreq(freq) - assert.NoError(t, err) -} - -func TestAdafruitMotorHatDriverSetServoMotorFreqError(t *testing.T) { - ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - a.i2cWriteImpl = func([]byte) (int, error) { - return 0, errors.New("write error") - } - - freq := 60.0 - assert.ErrorContains(t, ada.SetServoMotorFreq(freq), "write error") -} - -func TestAdafruitMotorHatDriverSetServoMotorPulse(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - var channel byte = 7 - var on int32 = 1234 - var off int32 = 4321 - err := ada.SetServoMotorPulse(channel, on, off) - assert.NoError(t, err) -} - -func TestAdafruitMotorHatDriverSetServoMotorPulseError(t *testing.T) { - ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - a.i2cWriteImpl = func([]byte) (int, error) { - return 0, errors.New("write error") - } - - var channel byte = 7 - var on int32 = 1234 - var off int32 = 4321 - assert.ErrorContains(t, ada.SetServoMotorPulse(channel, on, off), "write error") -} - -func TestAdafruitMotorHatDriverSetDCMotorSpeed(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - dcMotor := 1 - var speed int32 = 255 - err := ada.SetDCMotorSpeed(dcMotor, speed) - assert.NoError(t, err) -} - -func TestAdafruitMotorHatDriverSetDCMotorSpeedError(t *testing.T) { - ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - a.i2cWriteImpl = func([]byte) (int, error) { - return 0, errors.New("write error") - } - - assert.ErrorContains(t, ada.SetDCMotorSpeed(1, 255), "write error") -} - -func TestAdafruitMotorHatDriverRunDCMotor(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - dcMotor := 1 - assert.NoError(t, ada.RunDCMotor(dcMotor, AdafruitForward)) - assert.NoError(t, ada.RunDCMotor(dcMotor, AdafruitBackward)) - assert.NoError(t, ada.RunDCMotor(dcMotor, AdafruitRelease)) -} - -func TestAdafruitMotorHatDriverRunDCMotorError(t *testing.T) { - ada, a := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - assert.NoError(t, ada.Start()) - a.i2cWriteImpl = func([]byte) (int, error) { - return 0, errors.New("write error") - } - - dcMotor := 1 - assert.ErrorContains(t, ada.RunDCMotor(dcMotor, AdafruitForward), "write error") - assert.ErrorContains(t, ada.RunDCMotor(dcMotor, AdafruitBackward), "write error") - assert.ErrorContains(t, ada.RunDCMotor(dcMotor, AdafruitRelease), "write error") -} - -func TestAdafruitMotorHatDriverSetStepperMotorSpeed(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - stepperMotor := 1 - rpm := 30 - assert.NoError(t, ada.SetStepperMotorSpeed(stepperMotor, rpm)) -} - -func TestAdafruitMotorHatDriverStepperMicroStep(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - // NOTE: not using the direction and style constants to prevent importing - // the i2c package - stepperMotor := 0 - steps := 50 - err := ada.Step(stepperMotor, steps, 1, 3) - assert.NoError(t, err) -} - -func TestAdafruitMotorHatDriverStepperSingleStep(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - // NOTE: not using the direction and style constants to prevent importing - // the i2c package - stepperMotor := 0 - steps := 50 - err := ada.Step(stepperMotor, steps, 1, 0) - assert.NoError(t, err) -} - -func TestAdafruitMotorHatDriverStepperDoubleStep(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - // NOTE: not using the direction and style constants to prevent importing - // the i2c package - stepperMotor := 0 - steps := 50 - err := ada.Step(stepperMotor, steps, 1, 1) - assert.NoError(t, err) -} - -func TestAdafruitMotorHatDriverStepperInterleaveStep(t *testing.T) { - ada, _ := initTestAdafruitMotorHatDriverWithStubbedAdaptor() - - assert.NoError(t, ada.Start()) - - // NOTE: not using the direction and style constants to prevent importing - // the i2c package - stepperMotor := 0 - steps := 50 - err := ada.Step(stepperMotor, steps, 1, 2) - assert.NoError(t, err) -} - -func TestAdafruitMotorHatDriverSetName(t *testing.T) { - d := initTestAdafruitMotorHatDriver() - d.SetName("TESTME") - assert.Equal(t, "TESTME", d.Name()) -} - -func TestAdafruitMotorHatDriverOptions(t *testing.T) { - d := NewAdafruitMotorHatDriver(newI2cTestAdaptor(), WithBus(2)) - assert.Equal(t, 2, d.GetBusOrDefault(1)) -} diff --git a/drivers/i2c/pca9685_driver.go b/drivers/i2c/pca9685_driver.go index 74df04fed..b8c1eddd2 100644 --- a/drivers/i2c/pca9685_driver.go +++ b/drivers/i2c/pca9685_driver.go @@ -10,26 +10,27 @@ import ( const pca9685DefaultAddress = 0x40 const ( - PCA9685_MODE1 = 0x00 - PCA9685_MODE2 = 0x01 - PCA9685_PRESCALE = 0xFE - PCA9685_SUBADR1 = 0x02 - PCA9685_SUBADR2 = 0x03 - PCA9685_SUBADR3 = 0x04 - PCA9685_LED0_ON_L = 0x06 - PCA9685_LED0_ON_H = 0x07 - PCA9685_LED0_OFF_L = 0x08 - PCA9685_LED0_OFF_H = 0x09 - PCA9685_ALLLED_ON_L = 0xFA - PCA9685_ALLLED_ON_H = 0xFB - PCA9685_ALLLED_OFF_L = 0xFC - PCA9685_ALLLED_OFF_H = 0xFD - - PCA9685_RESTART = 0x80 - PCA9685_SLEEP = 0x10 - PCA9685_ALLCALL = 0x01 - PCA9685_INVRT = 0x10 - PCA9685_OUTDRV = 0x04 + pca9685Mode1Reg = 0x00 + pca9685Mode2Reg = 0x01 + pca9685Subadr1Reg = 0x02 + pca9685Subadr2Reg = 0x03 + pca9685Subadr3Reg = 0x04 + pca9685Led0OnLReg = 0x06 + pca9685Led0OnHReg = 0x07 + pca9685Led0OffLReg = 0x08 + pca9685Led0OffHReg = 0x09 + pca9685AllLedOnLReg = 0xFA + pca9685AllLedOnHReg = 0xFB + pca9685AllLedOffLReg = 0xFC + pca9685AllLedOffHReg = 0xFD + pca9685PrescaleReg = 0xFE + + pca9685Mode1RegRestartBit = 0x80 // bit 7 - 0: restart disabled (default) + pca9685Mode1RegSleepBit = 0x10 // bit 4 - 0: normal, 1: low power (default) + pca9685Mode1RegAllCallBit = 0x01 // bit 0 - 0: no response to all-call, 1: respond to all-call (default) + pca9685Mode2RegInvertBit = 0x10 // bit 4 - 0: outputs not inverted (default), 1: outputs inverted + pca9685Mode2RegOutdrvBit = 0x04 // bit 2 - 0: open-drain, 1: totem-pole (default) + pca9685AllLedOffHRegShutDown = 0x10 // bit 4 - 1: orderly shut down ) // PCA9685Driver is a Gobot Driver for the PCA9685 16-channel 12-bit PWM/Servo controller. @@ -93,19 +94,19 @@ func NewPCA9685Driver(c Connector, options ...func(Config)) *PCA9685Driver { // // Most typically you set "on" to a zero value, and then set "off" to your desired duty. func (p *PCA9685Driver) SetPWM(channel int, on uint16, off uint16) (err error) { - if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_ON_L + 4*channel), byte(on) & 0xFF}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685Led0OnLReg + 4*channel), byte(on) & 0xFF}); err != nil { return err } - if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_ON_H + 4*channel), byte(on >> 8)}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685Led0OnHReg + 4*channel), byte(on >> 8)}); err != nil { return err } - if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_OFF_L + 4*channel), byte(off) & 0xFF}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685Led0OffLReg + 4*channel), byte(off) & 0xFF}); err != nil { return err } - if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_OFF_H + 4*channel), byte(off >> 8)}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685Led0OffHReg + 4*channel), byte(off >> 8)}); err != nil { return err } @@ -120,38 +121,38 @@ func (p *PCA9685Driver) SetPWM(channel int, on uint16, off uint16) (err error) { // // Most typically you set "on" to a zero value, and then set "off" to your desired duty. func (p *PCA9685Driver) SetAllPWM(on uint16, off uint16) (err error) { - if _, err := p.connection.Write([]byte{byte(PCA9685_ALLLED_ON_L), byte(on) & 0xFF}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685AllLedOnLReg), byte(on) & 0xFF}); err != nil { return err } - if _, err := p.connection.Write([]byte{byte(PCA9685_ALLLED_ON_H), byte(on >> 8)}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685AllLedOnHReg), byte(on >> 8)}); err != nil { return err } - if _, err := p.connection.Write([]byte{byte(PCA9685_ALLLED_OFF_L), byte(off) & 0xFF}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685AllLedOffLReg), byte(off) & 0xFF}); err != nil { return err } - if _, err := p.connection.Write([]byte{byte(PCA9685_ALLLED_OFF_H), byte(off >> 8)}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685AllLedOffHReg), byte(off >> 8)}); err != nil { return err } return } -// SetPWMFreq sets the PWM frequency in Hz +// SetPWMFreq sets the PWM frequency in Hz between 24Hz and 1526Hz, the default is 200Hz. func (p *PCA9685Driver) SetPWMFreq(freq float32) error { - // IC oscillator frequency is 25 MHz + // internal IC oscillator frequency is 25 MHz var prescalevel float32 = 25000000 - // Find frequency of PWM waveform + // find frequency of PWM waveform prescalevel /= 4096 - // Ratio between desired frequency and maximum + // ratio between desired frequency and maximum prescalevel /= freq prescalevel-- - // Round value to nearest whole + // round value to nearest whole prescale := byte(prescalevel + 0.5) - if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1)}); err != nil { + if _, err := p.connection.Write([]byte{byte(pca9685Mode1Reg)}); err != nil { return err } oldmode, err := p.connection.ReadByte() @@ -159,25 +160,27 @@ func (p *PCA9685Driver) SetPWMFreq(freq float32) error { return err } - // Put oscillator in sleep mode, clear bit 7 here to avoid overwriting - // previous setting - newmode := (oldmode & 0x7F) | 0x10 - if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), newmode}); err != nil { + // put oscillator in sleep mode, clear the restart bit 7 here to prevent unneeded restart + sleepMode := (oldmode &^ pca9685Mode1RegRestartBit) | pca9685Mode1RegSleepBit + if _, err := p.connection.Write([]byte{byte(pca9685Mode1Reg), sleepMode}); err != nil { return err } - // Write prescaler value - if _, err := p.connection.Write([]byte{byte(PCA9685_PRESCALE), prescale}); err != nil { + // write prescaler value + if _, err := p.connection.Write([]byte{byte(pca9685PrescaleReg), prescale}); err != nil { return err } - // Put back to old settings - if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), oldmode}); err != nil { + // put back to old settings, ensure no sleep + noSleepMode := oldmode &^ pca9685Mode1RegSleepBit + if _, err := p.connection.Write([]byte{byte(pca9685Mode1Reg), noSleepMode}); err != nil { return err } + // wait >500us according to data sheet time.Sleep(5 * time.Millisecond) - // Enable response to All Call address, enable auto-increment, clear restart - if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), oldmode | 0x80}); err != nil { + // initiate a restart + restartMode := oldmode | pca9685Mode1RegRestartBit + if _, err := p.connection.Write([]byte{byte(pca9685Mode1Reg), restartMode}); err != nil { return err } @@ -208,31 +211,38 @@ func (p *PCA9685Driver) ServoWrite(pin string, val byte) (err error) { return p.SetPWM(i, 0, uint16(v)) } +// initialize the driver according to the data sheet section "7.3.1.1 Restart mode" +// * ensure the sleep bit is unset +// * wait > 500us +// * write a logic 1 to bit 7 (RESTART) of register "MODE1" func (p *PCA9685Driver) initialize() error { if err := p.SetAllPWM(0, 0); err != nil { return err } - if _, err := p.connection.Write([]byte{PCA9685_MODE2, PCA9685_OUTDRV}); err != nil { + // set not inverted (default), outputs change on stop (default), OE reaction to 0 (default), totem-pole (default) + if _, err := p.connection.Write([]byte{pca9685Mode2Reg, pca9685Mode2RegOutdrvBit}); err != nil { return err } - - if _, err := p.connection.Write([]byte{PCA9685_MODE1, PCA9685_ALLCALL}); err != nil { + // reset of sleep bit together with set of no restart (default), internal clock (default), no AI (default), + // no response to sub address 1, 2 or 3 (default), activate response to all-call (default) + if _, err := p.connection.Write([]byte{pca9685Mode1Reg, pca9685Mode1RegAllCallBit}); err != nil { return err } time.Sleep(5 * time.Millisecond) - if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1)}); err != nil { + // initiate the restart + if _, err := p.connection.Write([]byte{byte(pca9685Mode1Reg)}); err != nil { return err } oldmode, err := p.connection.ReadByte() if err != nil { return err } - oldmode = oldmode &^ byte(PCA9685_SLEEP) + oldmode = oldmode | byte(pca9685Mode1RegRestartBit) - if _, err := p.connection.Write([]byte{PCA9685_MODE1, oldmode}); err != nil { + if _, err := p.connection.Write([]byte{pca9685Mode1Reg, oldmode}); err != nil { return err } @@ -242,6 +252,6 @@ func (p *PCA9685Driver) initialize() error { } func (p *PCA9685Driver) shutdown() error { - _, err := p.connection.Write([]byte{PCA9685_ALLLED_OFF_H, 0x10}) + _, err := p.connection.Write([]byte{pca9685AllLedOffHReg, pca9685AllLedOffHRegShutDown}) return err } diff --git a/drivers/i2c/pca9685_driver_test.go b/drivers/i2c/pca9685_driver_test.go index d4c81c34f..b9a3b0730 100644 --- a/drivers/i2c/pca9685_driver_test.go +++ b/drivers/i2c/pca9685_driver_test.go @@ -20,7 +20,7 @@ var ( _ gpio.ServoWriter = (*PCA9685Driver)(nil) ) -func initTestPCA9685DriverWithStubbedAdaptor() (*PCA9685Driver, *i2cTestAdaptor) { +func initTestPCA9685WithStubbedAdaptor() (*PCA9685Driver, *i2cTestAdaptor) { a := newI2cTestAdaptor() d := NewPCA9685Driver(a) if err := d.Start(); err != nil { @@ -30,11 +30,10 @@ func initTestPCA9685DriverWithStubbedAdaptor() (*PCA9685Driver, *i2cTestAdaptor) } func TestNewPCA9685Driver(t *testing.T) { - var di interface{} = NewPCA9685Driver(newI2cTestAdaptor()) - d, ok := di.(*PCA9685Driver) - if !ok { - t.Errorf("NewPCA9685Driver() should have returned a *PCA9685Driver") - } + // arrange & act + d := NewPCA9685Driver(newI2cTestAdaptor()) + // assert + assert.IsType(t, &PCA9685Driver{}, d) assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "PCA9685")) assert.Equal(t, 0x40, d.defaultAddress) @@ -43,113 +42,308 @@ func TestNewPCA9685Driver(t *testing.T) { func TestPCA9685Options(t *testing.T) { // This is a general test, that options are applied in constructor by using the common WithBus() option and // least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". + // arrange & act d := NewPCA9685Driver(newI2cTestAdaptor(), WithBus(2)) + // assert assert.Equal(t, 2, d.GetBusOrDefault(1)) } func TestPCA9685Start(t *testing.T) { + // arrange a := newI2cTestAdaptor() d := NewPCA9685Driver(a) a.i2cReadImpl = func(b []byte) (int, error) { copy(b, []byte{0x01}) return 1, nil } + // act & assert assert.NoError(t, d.Start()) } +func TestPCA9685StartError(t *testing.T) { + // arrange + a := newI2cTestAdaptor() + d := NewPCA9685Driver(a) + a.i2cWriteImpl = func([]byte) (int, error) { + return 0, errors.New("write error") + } + // act & assert + assert.ErrorContains(t, d.Start(), "write error") +} + func TestPCA9685Halt(t *testing.T) { - d, a := initTestPCA9685DriverWithStubbedAdaptor() - a.i2cReadImpl = func(b []byte) (int, error) { - copy(b, []byte{0x01}) - return 1, nil + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() + a.written = []byte{} // reset writes of former test + // act + err := d.Halt() + // assert + assert.NoError(t, err) + assert.NoError(t, err) + assert.Equal(t, 2, len(a.written)) + assert.Equal(t, []byte{0xFD, 0x10}, a.written) +} + +func TestPCA9685HaltError(t *testing.T) { + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() + a.i2cWriteImpl = func([]byte) (int, error) { + return 0, errors.New("write error") } - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + // act & assert + assert.ErrorContains(t, d.Halt(), "write error") } func TestPCA9685SetPWM(t *testing.T) { - d, a := initTestPCA9685DriverWithStubbedAdaptor() - a.i2cReadImpl = func(b []byte) (int, error) { - copy(b, []byte{0x01}) - return 1, nil + // sequence to set PWM for PCA9685: + // * set LEDn ON-time register (n=0: 0x06, 0x07, n=1: 0x0A, 0x0B ... n=14: 0x3E, 0x3F, n=15: 0x42, 0x43) + // * set LEDn OFF-time register (n=0: 0x08, 0x09, n=1: 0x0C, 0x0D ... n=14: 0x40, 0x41, n=15: 0x44, 0x45) + tests := map[string]struct { + pin int + onCounts uint16 + offCounts uint16 + wantLedOnTimeOffTimeSet []uint8 + }{ + "example1_datasheet": { + pin: 0, + onCounts: 409, + offCounts: 1228, + wantLedOnTimeOffTimeSet: []uint8{0x06, 0x99, 0x07, 0x01, 0x08, 0xCC, 0x09, 0x04}, + }, + "example2_datasheet": { + pin: 4, + onCounts: 3685, + offCounts: 3275, + wantLedOnTimeOffTimeSet: []uint8{0x16, 0x65, 0x17, 0x0E, 0x18, 0xCB, 0x19, 0x0C}, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() + a.written = []byte{} // reset writes of former test + // act + err := d.SetPWM(tc.pin, tc.onCounts, tc.offCounts) + // assert + assert.NoError(t, err) + assert.Equal(t, 8, len(a.written)) + for writeIdx, wantVal := range tc.wantLedOnTimeOffTimeSet { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d differs", writeIdx) + } + }) } - assert.NoError(t, d.Start()) - assert.NoError(t, d.SetPWM(0, 0, 256)) } func TestPCA9685SetPWMError(t *testing.T) { - d, a := initTestPCA9685DriverWithStubbedAdaptor() - a.i2cReadImpl = func(b []byte) (int, error) { - copy(b, []byte{0x01}) - return 1, nil - } - assert.NoError(t, d.Start()) + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } + // act & assert assert.ErrorContains(t, d.SetPWM(0, 0, 256), "write error") } -func TestPCA9685SetPWMFreq(t *testing.T) { - d, a := initTestPCA9685DriverWithStubbedAdaptor() - a.i2cReadImpl = func(b []byte) (int, error) { - copy(b, []byte{0x01}) - return 1, nil +func TestPCA9685SetAllPWM(t *testing.T) { + // sequence to set PWM for PCA9685: + // * set LEDn ON-time register (n=0: 0x06, 0x07, n=1: 0x0A, 0x0B ... n=14: 0x3E, 0x3F, n=15: 0x42, 0x43) + // * set LEDn OFF-time register (n=0: 0x08, 0x09, n=1: 0x0C, 0x0D ... n=14: 0x40, 0x41, n=15: 0x44, 0x45) + tests := map[string]struct { + pin byte + onCounts uint16 + offCounts uint16 + wantLedOnTimeOffTimeSet []uint8 + }{ + "example1_datasheet": { + onCounts: 409, + offCounts: 1228, + wantLedOnTimeOffTimeSet: []uint8{0xFA, 0x99, 0xFB, 0x01, 0xFC, 0xCC, 0xFD, 0x04}, + }, + "example2_datasheet": { + onCounts: 3685, + offCounts: 3275, + wantLedOnTimeOffTimeSet: []uint8{0xFA, 0x65, 0xFB, 0x0E, 0xFC, 0xCB, 0xFD, 0x0C}, + }, + "own_example": { + onCounts: 1234, + offCounts: 4321, + wantLedOnTimeOffTimeSet: []uint8{0xFA, 0xD2, 0xFB, 0x04, 0xFC, 0xE1, 0xFD, 0x10}, + }, } - assert.NoError(t, d.Start()) - a.i2cReadImpl = func(b []byte) (int, error) { - copy(b, []byte{0x01}) - return 1, nil + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() + a.written = []byte{} // reset writes of former test + // act + err := d.SetAllPWM(tc.onCounts, tc.offCounts) + // assert + assert.NoError(t, err) + assert.Equal(t, 8, len(a.written)) + for writeIdx, wantVal := range tc.wantLedOnTimeOffTimeSet { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d differs", writeIdx) + } + }) } - assert.NoError(t, d.SetPWMFreq(60)) } -func TestPCA9685SetPWMFreqReadError(t *testing.T) { - d, a := initTestPCA9685DriverWithStubbedAdaptor() - a.i2cReadImpl = func(b []byte) (int, error) { - copy(b, []byte{0x01}) - return 1, nil +func TestPCA9685SetAllPWMError(t *testing.T) { + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() + a.i2cWriteImpl = func([]byte) (int, error) { + return 0, errors.New("write error") } - assert.NoError(t, d.Start()) + // act & assert + assert.ErrorContains(t, d.SetAllPWM(0, 256), "write error") +} +func TestPCA9685SetPWMFreq(t *testing.T) { + // sequence to set PWM frequency prescaler for PCA9685 (can only be set in sleep mode): + // * read MODE1 register (0x00) + // * prepare MODE1 register with sleep mode set (bit 4 - 0x10, no stopping of PWM channels done before) + // * write MODE1 register + // * write the prescaler value to PRE_SCALE register (0xFE) + // * prepare MIODE1 register with sleep mode bit reset + // * write MODE1 register + // * wait > 500us + // * prepare the MODE1 register with set of reset bit + // * write MODE1 register + const readMode1Val = 0x0F // to check for only sleep mode bit (0x10) or reset bit (0x80) will be set + var ( + wantMode1SleepSequence = []uint8{0x00, 0x1F} + wantMode1NoSleepSequence = []uint8{0x00, readMode1Val} + wantMode1ResetSequence = []uint8{0x00, 0x8F} + ) + tests := map[string]struct { + freq float32 + wantPrescalerSequence []uint8 + }{ + "example_datasheet": { + freq: 200, + wantPrescalerSequence: []uint8{0xFE, 0x1E}, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() + // arrange read for MODE1 register + numCallsRead := 0 + a.i2cReadImpl = func(b []byte) (int, error) { + numCallsRead++ + b[0] = readMode1Val + return len(b), nil + } + a.written = []byte{} // reset writes of former test + // act + err := d.SetPWMFreq(tc.freq) + // assert + assert.NoError(t, err) + assert.Equal(t, 9, len(a.written)) + var writeIdx int + // for read old mode: + assert.Equal(t, wantMode1SleepSequence[0], a.written[writeIdx], "index %d differs", writeIdx) + writeIdx++ + for idx, wantVal := range wantMode1SleepSequence { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) + writeIdx++ + } + for idx, wantVal := range tc.wantPrescalerSequence { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) + writeIdx++ + } + for idx, wantVal := range wantMode1NoSleepSequence { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) + writeIdx++ + } + for idx, wantVal := range wantMode1ResetSequence { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) + writeIdx++ + } + assert.Equal(t, 1, numCallsRead) + }) + } +} + +func TestPCA9685SetPWMFreqReadError(t *testing.T) { + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } + // act & assert assert.ErrorContains(t, d.SetPWMFreq(60), "read error") } func TestPCA9685SetPWMFreqWriteError(t *testing.T) { - d, a := initTestPCA9685DriverWithStubbedAdaptor() - a.i2cReadImpl = func(b []byte) (int, error) { - copy(b, []byte{0x01}) - return 1, nil - } - assert.NoError(t, d.Start()) - + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } + // act & assert assert.ErrorContains(t, d.SetPWMFreq(60), "write error") } func TestPCA9685Commands(t *testing.T) { - d, a := initTestPCA9685DriverWithStubbedAdaptor() + // arrange + d, _ := initTestPCA9685WithStubbedAdaptor() + // act & assert + assert.Nil(t, d.Command("PwmWrite")(map[string]interface{}{"pin": "1", "val": "1"})) + assert.Nil(t, d.Command("ServoWrite")(map[string]interface{}{"pin": "1", "val": "1"})) + assert.Nil(t, d.Command("SetPWM")(map[string]interface{}{"channel": "1", "on": "0", "off": "1024"})) + assert.Nil(t, d.Command("SetPWMFreq")(map[string]interface{}{"freq": "60"})) +} + +func TestPCA9685_initialize(t *testing.T) { + // sequence to reset the PCA9685 in initialize(): + // * set all LED ON-time and OFF-time registers (0xFA..0xFD for 16 channels, each for low and high byte) + // * set MODE2 register (0x01) to defaults: not inverted, outputs change on stop, OE reaction to 0, totem-pole + // * set MODE1 register (0x00) to defaults, except sleep: no restart, internal clock, no AI, no sleep (not default), + // no response to sub address 1, 2 or 3, activate response to all-call + // * wait > 500us, read back the MODE1 register + // * prepare the MODE1 register with set of reset bit + // * write MODE1 register + // arrange + d, a := initTestPCA9685WithStubbedAdaptor() + a.written = []byte{} // reset writes of former test + wantAllLedOnTimeOffTimeSequence := []uint8{0xFA, 0x00, 0xFB, 0x00, 0xFC, 0x00, 0xFD, 0x00} + wantMode2RegSetDefaultsSequence := []uint8{0x01, 0x04} + wantMode1RegSetDefaultsNoSleepSequence := []uint8{0x00, 0x01} + wantMode1RegResetSequence := []uint8{0x00, 0x81} + // arrange read for MODE1 register + numCallsRead := 0 a.i2cReadImpl = func(b []byte) (int, error) { - copy(b, []byte{0x01}) - return 1, nil + numCallsRead++ + b[0] = wantMode1RegSetDefaultsNoSleepSequence[1] + return len(b), nil } - _ = d.Start() - - err := d.Command("PwmWrite")(map[string]interface{}{"pin": "1", "val": "1"}) - assert.Nil(t, err) - - err = d.Command("ServoWrite")(map[string]interface{}{"pin": "1", "val": "1"}) - assert.Nil(t, err) - - err = d.Command("SetPWM")(map[string]interface{}{"channel": "1", "on": "0", "off": "1024"}) - assert.Nil(t, err) - - err = d.Command("SetPWMFreq")(map[string]interface{}{"freq": "60"}) - assert.Nil(t, err) + // act, assert - initialize() must be called on Start() + err := d.Start() + // assert + assert.NoError(t, err) + assert.Equal(t, 15, len(a.written)) + var writeIdx int + for idx, wantVal := range wantAllLedOnTimeOffTimeSequence { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) + writeIdx++ + } + for idx, wantVal := range wantMode2RegSetDefaultsSequence { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) + writeIdx++ + } + for idx, wantVal := range wantMode1RegSetDefaultsNoSleepSequence { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) + writeIdx++ + } + // for read old mode: + assert.Equal(t, wantMode1RegSetDefaultsNoSleepSequence[0], a.written[writeIdx], "index %d differs", writeIdx) + writeIdx++ + for idx, wantVal := range wantMode1RegResetSequence { + assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) + writeIdx++ + } + assert.Equal(t, 1, numCallsRead) } diff --git a/examples/raspi_adafruit_servo.go b/examples/raspi_adafruit2327_servo.go similarity index 90% rename from examples/raspi_adafruit_servo.go rename to examples/raspi_adafruit2327_servo.go index 1d56311b0..b34f1b6c4 100644 --- a/examples/raspi_adafruit_servo.go +++ b/examples/raspi_adafruit2327_servo.go @@ -15,7 +15,7 @@ import ( "gobot.io/x/gobot/v2/platforms/raspi" ) -var ( +const ( // Min pulse length out of 4096 servoMin = 150 // Max pulse length out of 4096 @@ -27,23 +27,36 @@ var ( yawDeg = 90 ) -func degree2pulse(deg int) int32 { - pulse := servoMin - pulse += ((servoMax - servoMin) / maxDegree) * deg - return int32(pulse) -} +func main() { + r := raspi.NewAdaptor() -func adafruitServoMotorRunner(a *i2c.AdafruitMotorHatDriver) (err error) { - log.Printf("Servo Motor Run Loop...\n") // Changing from the default 0x40 address because this configuration involves // a Servo HAT stacked on top of a DC/Stepper Motor HAT on top of the Pi. stackedHatAddr := 0x41 + + adaFruit := i2c.NewAdafruit2327Driver(r, i2c.WithAddress(stackedHatAddr)) + + work := func() { + gobot.Every(5*time.Second, func() { + adafruitServoMotorRunner(adaFruit) + }) + } + + robot := gobot.NewRobot("adaFruitBot", + []gobot.Connection{r}, + []gobot.Device{adaFruit}, + work, + ) + + robot.Start() +} + +func adafruitServoMotorRunner(a *i2c.Adafruit2327Driver) (err error) { + log.Printf("Servo Motor Run Loop...\n") + var channel byte = 1 deg := 90 - // update the I2C address state - a.SetServoHatAddress(stackedHatAddr) - // Do not need to set this every run loop freq := 60.0 if err = a.SetServoMotorFreq(freq); err != nil { @@ -72,21 +85,8 @@ func adafruitServoMotorRunner(a *i2c.AdafruitMotorHatDriver) (err error) { return } -func main() { - r := raspi.NewAdaptor() - adaFruit := i2c.NewAdafruitMotorHatDriver(r) - - work := func() { - gobot.Every(5*time.Second, func() { - adafruitServoMotorRunner(adaFruit) - }) - } - - robot := gobot.NewRobot("adaFruitBot", - []gobot.Connection{r}, - []gobot.Device{adaFruit}, - work, - ) - - robot.Start() +func degree2pulse(deg int) int32 { + pulse := servoMin + pulse += ((servoMax - servoMin) / maxDegree) * deg + return int32(pulse) } diff --git a/examples/raspi_adafruit_dcmotor.go b/examples/raspi_adafruit2348_dcmotor.go similarity index 64% rename from examples/raspi_adafruit_dcmotor.go rename to examples/raspi_adafruit2348_dcmotor.go index 9c3b668cc..c617d0b48 100644 --- a/examples/raspi_adafruit_dcmotor.go +++ b/examples/raspi_adafruit2348_dcmotor.go @@ -15,7 +15,29 @@ import ( "gobot.io/x/gobot/v2/platforms/raspi" ) -func adafruitDCMotorRunner(a *i2c.AdafruitMotorHatDriver, dcMotor int) (err error) { +func main() { + r := raspi.NewAdaptor() + + // we use the default address 0x60 for DC/Stepper Motor HAT on top of the Pi + adaFruit := i2c.NewAdafruit2348Driver(r) + + work := func() { + gobot.Every(5*time.Second, func() { + dcMotor := 2 // 0-based + adafruitDCMotorRunner(adaFruit, dcMotor) + }) + } + + robot := gobot.NewRobot("adaFruitBot", + []gobot.Connection{r}, + []gobot.Device{adaFruit}, + work, + ) + + robot.Start() +} + +func adafruitDCMotorRunner(a *i2c.Adafruit2348Driver, dcMotor int) (err error) { log.Printf("DC Motor Run Loop...\n") // set the speed: var speed int32 = 255 // 255 = full speed! @@ -23,42 +45,22 @@ func adafruitDCMotorRunner(a *i2c.AdafruitMotorHatDriver, dcMotor int) (err erro return } // run FORWARD - if err = a.RunDCMotor(dcMotor, i2c.AdafruitForward); err != nil { + if err = a.RunDCMotor(dcMotor, i2c.Adafruit2348Forward); err != nil { return } // Sleep and RELEASE time.Sleep(2000 * time.Millisecond) - if err = a.RunDCMotor(dcMotor, i2c.AdafruitRelease); err != nil { + if err = a.RunDCMotor(dcMotor, i2c.Adafruit2348Release); err != nil { return } // run BACKWARD - if err = a.RunDCMotor(dcMotor, i2c.AdafruitBackward); err != nil { + if err = a.RunDCMotor(dcMotor, i2c.Adafruit2348Backward); err != nil { return } // Sleep and RELEASE time.Sleep(2000 * time.Millisecond) - if err = a.RunDCMotor(dcMotor, i2c.AdafruitRelease); err != nil { + if err = a.RunDCMotor(dcMotor, i2c.Adafruit2348Release); err != nil { return } return } - -func main() { - r := raspi.NewAdaptor() - adaFruit := i2c.NewAdafruitMotorHatDriver(r) - - work := func() { - gobot.Every(5*time.Second, func() { - dcMotor := 2 // 0-based - adafruitDCMotorRunner(adaFruit, dcMotor) - }) - } - - robot := gobot.NewRobot("adaFruitBot", - []gobot.Connection{r}, - []gobot.Device{adaFruit}, - work, - ) - - robot.Start() -} diff --git a/examples/raspi_adafruit_stepper.go b/examples/raspi_adafruit2348_stepper.go similarity index 65% rename from examples/raspi_adafruit_stepper.go rename to examples/raspi_adafruit2348_stepper.go index 205b1d265..cbac4bc6e 100644 --- a/examples/raspi_adafruit_stepper.go +++ b/examples/raspi_adafruit2348_stepper.go @@ -15,29 +15,11 @@ import ( "gobot.io/x/gobot/v2/platforms/raspi" ) -func adafruitStepperMotorRunner(a *i2c.AdafruitMotorHatDriver, motor int) (err error) { - log.Printf("Stepper Motor Run Loop...\n") - // set the speed state: - speed := 30 // rpm - style := i2c.AdafruitDouble - steps := 20 - - a.SetStepperMotorSpeed(motor, speed) - - if err = a.Step(motor, steps, i2c.AdafruitForward, style); err != nil { - log.Printf(err.Error()) - return - } - if err = a.Step(motor, steps, i2c.AdafruitBackward, style); err != nil { - log.Printf(err.Error()) - return - } - return -} - func main() { r := raspi.NewAdaptor() - adaFruit := i2c.NewAdafruitMotorHatDriver(r) + + // we use the default address 0x60 for DC/Stepper Motor HAT on top of the Pi + adaFruit := i2c.NewAdafruit2348Driver(r) work := func() { gobot.Every(5*time.Second, func() { @@ -54,3 +36,23 @@ func main() { robot.Start() } + +func adafruitStepperMotorRunner(a *i2c.Adafruit2348Driver, motor int) (err error) { + log.Printf("Stepper Motor Run Loop...\n") + // set the speed state: + speed := 30 // rpm + style := i2c.Adafruit2348Double + steps := 20 + + a.SetStepperMotorSpeed(motor, speed) + + if err = a.Step(motor, steps, i2c.Adafruit2348Forward, style); err != nil { + log.Printf(err.Error()) + return + } + if err = a.Step(motor, steps, i2c.Adafruit2348Backward, style); err != nil { + log.Printf(err.Error()) + return + } + return +} From 24f064568c7f1507cc0c7cfa027ee64c15948d7a Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Mon, 30 Oct 2023 17:36:05 +0100 Subject: [PATCH 19/57] docs(core): prepare for release v2.2.0 (#1022) --- .chglog/README.md | 8 +++--- .chglog/config_gobot.yml | 2 +- CHANGELOG.md | 57 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/.chglog/README.md b/.chglog/README.md index eb0b0af63..7c81e3bd5 100644 --- a/.chglog/README.md +++ b/.chglog/README.md @@ -8,7 +8,7 @@ It is possible to test the tool by `git-chglog --init` without overriding anythi ## Usage -Example for a new release "v2.1.1": +Example for a new release "v2.2.0": ```sh git checkout release @@ -16,14 +16,14 @@ git pull git fetch --tags git checkout dev git pull upstream dev -git checkout -b rel/prepare_for_release_v211 -git-chglog --config .chglog/config_gobot.yml --no-case --next-tag v2.1.1 v2.1.0.. > .chglog/chglog_tmp.md +git checkout -b rel/prepare_for_release_v220 +git-chglog --config .chglog/config_gobot.yml --no-case --next-tag v2.2.0 v2.1.1.. > .chglog/chglog_tmp.md ``` ## Compare If unsure about any result of running git-chglog, just use: -`git log --since=2023-05-28 --pretty="- %s"` +`git log --since=2023-07-07 --pretty="- %s"` ## Manual adjustment diff --git a/.chglog/config_gobot.yml b/.chglog/config_gobot.yml index cd54029c9..fe03802f1 100755 --- a/.chglog/config_gobot.yml +++ b/.chglog/config_gobot.yml @@ -5,7 +5,7 @@ info: repository_url: https://github.com/hybridgroup/gobot options: header: - pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:?\\s(.*)$" + pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\,\\-\\*\\s]*)\\))?\\:?\\s(.*)$" pattern_maps: - Type - Scope diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b185e628..3fd63f0a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,61 @@ # CHANGELOG -## [Unreleased](https://github.com/hybridgroup/gobot/compare/v2.1.1...HEAD) +## [Unreleased](https://github.com/hybridgroup/gobot/compare/v2.2.0...HEAD) + +## [v2.2.0](https://github.com/hybridgroup/gobot/compare/v2.1.1...v2.2.0) (2023-10-29) + +### Adaptors + +* **PWM:** fix wrong duty cycle after kill program ([#994](https://github.com/hybridgroup/gobot/issues/994)) + +### Beaglebone + +* **doc:** fix preceding typo ([#985](https://github.com/hybridgroup/gobot/issues/985)) + +### Build + +* **deps:** module update ([#992](https://github.com/hybridgroup/gobot/issues/992)) +* **go, deps:** switch to Go 1.19 and update modules ([#1008](https://github.com/hybridgroup/gobot/issues/1008)) +* **style:** switch to gofumpt and add linters ([#1009](https://github.com/hybridgroup/gobot/issues/1009)) + +### Doc + +* **roadmap:** remove file ROADMAP.md after creating issues ([#1005](https://github.com/hybridgroup/gobot/issues/1005)) + +### Dragonboard + +* fix example and documentation ([#977](https://github.com/hybridgroup/gobot/issues/977)) + +### Gpio + +* **hcsr04:** add driver for ultrasonic ranging module ([#1012](https://github.com/hybridgroup/gobot/issues/1012)) + +### I2c + +* **PCA9685, adafruit, adafruit2327, adafruit2348:** clean up architecture and fix init ([#1021](https://github.com/hybridgroup/gobot/issues/1021)) + +### Jetson + +* **PWM:** fix set period ([#1019](https://github.com/hybridgroup/gobot/issues/1019)) + +### Joystick + +* **core:** replace sdl with 0xcafed00d/joystick package ([#988](https://github.com/hybridgroup/gobot/issues/988)) + +### Sphero + +* Add support for calibration + +### System + +* **gpio:** add edge polling function ([#1015](https://github.com/hybridgroup/gobot/issues/1015)) + +### Test + +* **all:** substitude assert.Nil by assert.NoError if useful ([#1016](https://github.com/hybridgroup/gobot/issues/1016)) +* **all:** substitude assert.Error by assert.ErrorContains ([#1014](https://github.com/hybridgroup/gobot/issues/1014), [#1011](https://github.com/hybridgroup/gobot/issues/1011)) +* **all:** switch to test package stretchr testify ([#1006](https://github.com/hybridgroup/gobot/issues/1006)) +* **gpio, aio:** cleanup helper_test ([#1018](https://github.com/hybridgroup/gobot/issues/1018)) ## [v2.1.1](https://github.com/hybridgroup/gobot/compare/v2.1.0...v2.1.1) (2023-07-07) From 458a1f43b8a3da2d9d7154bd5dc6cb6d69f2a2cd Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Mon, 30 Oct 2023 19:11:58 +0100 Subject: [PATCH 20/57] aio: fix data race in AnalogSensorDriver (#1024) --- drivers/aio/analog_sensor_driver.go | 61 ++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/drivers/aio/analog_sensor_driver.go b/drivers/aio/analog_sensor_driver.go index 450265955..81abba4af 100644 --- a/drivers/aio/analog_sensor_driver.go +++ b/drivers/aio/analog_sensor_driver.go @@ -1,6 +1,7 @@ package aio import ( + "sync" "time" "gobot.io/x/gobot/v2" @@ -18,6 +19,7 @@ type AnalogSensorDriver struct { rawValue int value float64 scale func(input int) (value float64) + mutex *sync.Mutex // to prevent data race between cyclic and single shot write/read to values and scaler } // NewAnalogSensorDriver returns a new AnalogSensorDriver with a polling interval of @@ -43,6 +45,7 @@ func NewAnalogSensorDriver(a AnalogReader, pin string, v ...time.Duration) *Anal interval: 10 * time.Millisecond, halt: make(chan bool), scale: func(input int) (value float64) { return float64(input) }, + mutex: &sync.Mutex{}, } if len(v) > 0 { @@ -83,17 +86,17 @@ func (a *AnalogSensorDriver) Start() (err error) { timer := time.NewTimer(a.interval) timer.Stop() for { - _, err := a.Read() + rawValue, value, err := a.analogRead() if err != nil { a.Publish(a.Event(Error), err) } else { - if a.rawValue != oldRawValue && a.rawValue != -1 { - a.Publish(a.Event(Data), a.rawValue) - oldRawValue = a.rawValue + if rawValue != oldRawValue && rawValue != -1 { + a.Publish(a.Event(Data), rawValue) + oldRawValue = rawValue } - if a.value != oldValue && a.value != -1 { - a.Publish(a.Event(Value), a.value) - oldValue = a.value + if value != oldValue && value != -1 { + a.Publish(a.Event(Value), value) + oldValue = value } } @@ -131,40 +134,62 @@ func (a *AnalogSensorDriver) Pin() string { return a.pin } // Connection returns the AnalogSensorDrivers Connection func (a *AnalogSensorDriver) Connection() gobot.Connection { return a.connection.(gobot.Connection) } -// Read returns the current reading from the sensor -func (a *AnalogSensorDriver) Read() (val float64, err error) { - if a.rawValue, err = a.ReadRaw(); err != nil { - return - } - a.value = a.scale(a.rawValue) - return a.value, nil +// Read returns the current reading from the sensor, scaled by the current scaler +func (a *AnalogSensorDriver) Read() (float64, error) { + _, value, err := a.analogRead() + return value, err } // ReadRaw returns the current reading from the sensor without scaling -func (a *AnalogSensorDriver) ReadRaw() (val int, err error) { - return a.connection.AnalogRead(a.Pin()) +func (a *AnalogSensorDriver) ReadRaw() (int, error) { + rawValue, _, err := a.analogRead() + return rawValue, err } // SetScaler substitute the default 1:1 return value function by a new scaling function func (a *AnalogSensorDriver) SetScaler(scaler func(int) float64) { + a.mutex.Lock() + defer a.mutex.Unlock() + a.scale = scaler } // Value returns the last read value from the sensor func (a *AnalogSensorDriver) Value() float64 { + a.mutex.Lock() + defer a.mutex.Unlock() + return a.value } // RawValue returns the last read raw value from the sensor func (a *AnalogSensorDriver) RawValue() int { + a.mutex.Lock() + defer a.mutex.Unlock() + return a.rawValue } +// analogRead performs an reading from the sensor and sets the internal attributes and returns the raw and scaled value +func (a *AnalogSensorDriver) analogRead() (int, float64, error) { + a.mutex.Lock() + defer a.mutex.Unlock() + + rawValue, err := a.connection.AnalogRead(a.Pin()) + if err != nil { + return 0, 0, err + } + + a.rawValue = rawValue + a.value = a.scale(a.rawValue) + return a.rawValue, a.value, nil +} + // AnalogSensorLinearScaler creates a linear scaler function from the given values. -func AnalogSensorLinearScaler(fromMin, fromMax int, toMin, toMax float64) func(input int) (value float64) { +func AnalogSensorLinearScaler(fromMin, fromMax int, toMin, toMax float64) func(int) float64 { m := (toMax - toMin) / float64(fromMax-fromMin) n := toMin - m*float64(fromMin) - return func(input int) (value float64) { + return func(input int) float64 { if input <= fromMin { return toMin } From 6ef7450e2e2e81cd98ba038a4e3f419e8aad192b Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 31 Oct 2023 18:12:07 +0100 Subject: [PATCH 21/57] gpio: fix data race in EasyDriver (#1025) --- drivers/gpio/easy_driver.go | 292 ++++++++----- drivers/gpio/easy_driver_test.go | 719 +++++++++++++++++++++++++------ drivers/gpio/gpio_driver_test.go | 7 +- 3 files changed, 761 insertions(+), 257 deletions(-) diff --git a/drivers/gpio/easy_driver.go b/drivers/gpio/easy_driver.go index fdde14f2a..26687d71b 100644 --- a/drivers/gpio/easy_driver.go +++ b/drivers/gpio/easy_driver.go @@ -1,8 +1,10 @@ package gpio import ( - "errors" + "fmt" + "log" "strconv" + "sync" "time" "github.com/hashicorp/go-multierror" @@ -11,25 +13,24 @@ import ( // EasyDriver object type EasyDriver struct { - gobot.Commander - - name string - connection DigitalWriter - stepPin string - dirPin string - enPin string - sleepPin string - - angle float32 - rpm uint - dir int8 - moving bool - stepNum int - enabled bool - sleeping bool + *Driver + + stepPin string + dirPin string + enPin string + sleepPin string + + angle float32 + rpm uint + dir int8 + stepNum int + enabled bool + sleeping bool + runStopChan chan struct{} + runStopWaitGroup *sync.WaitGroup } -// NewEasyDriver returns a new EasyDriver from SparkFun (https://www.sparkfun.com/products/12779) +// NewEasyDriver returns a new driver for EasyDriver from SparkFun (https://www.sparkfun.com/products/12779) // TODO: Support selecting phase input instead of hard-wiring MS1 and MS2 to board truth table // This should also work for the BigEasyDriver (untested) // A - DigitalWriter @@ -38,22 +39,36 @@ type EasyDriver struct { // enPin - Pin corresponding to enabled input on EasyDriver. Optional // sleepPin - Pin corresponding to sleep input on EasyDriver. Optional // angle - Step angle of motor -func NewEasyDriver(a DigitalWriter, angle float32, stepPin string, dirPin string, enPin string, sleepPin string) *EasyDriver { +func NewEasyDriver( + a DigitalWriter, + angle float32, + stepPin string, + dirPin string, + enPin string, + sleepPin string, +) *EasyDriver { + if angle <= 0 { + panic("angle needs to be greater than zero") + } d := &EasyDriver{ - Commander: gobot.NewCommander(), - name: gobot.DefaultName("EasyDriver"), - connection: a, - stepPin: stepPin, - dirPin: dirPin, - enPin: enPin, - sleepPin: sleepPin, - + Driver: NewDriver(a.(gobot.Connection), "EasyDriver"), + stepPin: stepPin, + dirPin: dirPin, + enPin: enPin, + sleepPin: sleepPin, angle: angle, rpm: 1, dir: 1, enabled: true, sleeping: false, } + d.beforeHalt = func() error { + if err := d.Stop(); err != nil { + fmt.Printf("no need to stop motion: %v\n", err) + } + + return nil + } // panic if step pin isn't set if stepPin == "" { @@ -61,7 +76,7 @@ func NewEasyDriver(a DigitalWriter, angle float32, stepPin string, dirPin string } // 1/4 of max speed. Not too fast, not too slow - d.rpm = d.GetMaxSpeed() / 4 + d.rpm = d.MaxSpeed() / 4 d.AddCommand("Move", func(params map[string]interface{}) interface{} { degs, _ := strconv.Atoi(params["degs"].(string)) @@ -80,121 +95,142 @@ func NewEasyDriver(a DigitalWriter, angle float32, stepPin string, dirPin string return d } -// Name of EasyDriver -func (d *EasyDriver) Name() string { return d.name } +// Move the motor given number of degrees at current speed. The move can be stopped asynchronously. +func (d *EasyDriver) Move(degs int) error { + // ensure that move and run can not interfere + d.mutex.Lock() + defer d.mutex.Unlock() -// SetName sets name for EasyDriver -func (d *EasyDriver) SetName(n string) { d.name = n } + if !d.enabled { + return fmt.Errorf("motor '%s' is disabled and can not be running", d.name) + } -// Connection returns EasyDriver's connection -func (d *EasyDriver) Connection() gobot.Connection { return d.connection.(gobot.Connection) } + if d.runStopChan != nil { + return fmt.Errorf("motor '%s' already running or moving", d.name) + } -// Start implements the Driver interface -func (d *EasyDriver) Start() error { return nil } + d.runStopChan = make(chan struct{}) + d.runStopWaitGroup = &sync.WaitGroup{} + d.runStopWaitGroup.Add(1) -// Halt implements the Driver interface; stops running the stepper -func (d *EasyDriver) Halt() error { - return d.Stop() -} + defer func() { + close(d.runStopChan) + d.runStopChan = nil + d.runStopWaitGroup.Done() + }() -// Move the motor given number of degrees at current speed. -func (d *EasyDriver) Move(degs int) error { - if d.moving { - // don't do anything if already moving - return nil + steps := int(float32(degs) / d.angle) + if steps <= 0 { + fmt.Printf("steps are smaller than zero, no move for '%s'\n", d.name) } - d.moving = true - - steps := int(float32(degs) / d.angle) for i := 0; i < steps; i++ { - if !d.moving { + select { + case <-d.runStopChan: // don't continue to step if driver is stopped - break - } - - if err := d.Step(); err != nil { - return err + log.Println("stop happen") + return nil + default: + if err := d.step(); err != nil { + return err + } } } - d.moving = false - return nil } -// Step the stepper 1 step -func (d *EasyDriver) Step() error { - stepsPerRev := d.GetMaxSpeed() +// Run the stepper continuously. +func (d *EasyDriver) Run() error { + // ensure that run, can not interfere with step or move + d.mutex.Lock() + defer d.mutex.Unlock() - // a valid steps occurs for a low to high transition - if err := d.connection.DigitalWrite(d.stepPin, 0); err != nil { - return err - } - // 1 minute / steps per revolution / revolutions per minute - // let's keep it as Microseconds so we only have to do integer math - time.Sleep(time.Duration(60*1000*1000/stepsPerRev/d.rpm) * time.Microsecond) - if err := d.connection.DigitalWrite(d.stepPin, 1); err != nil { - return err + if !d.enabled { + return fmt.Errorf("motor '%s' is disabled and can not be moving", d.name) } - // increment or decrement the number of steps by 1 - d.stepNum += int(d.dir) - - return nil -} - -// Run the stepper continuously -func (d *EasyDriver) Run() error { - if d.moving { - // don't do anything if already moving - return nil + if d.runStopChan != nil { + return fmt.Errorf("motor '%s' already running or moving", d.name) } - d.moving = true - - go func() { - for d.moving { - if err := d.Step(); err != nil { - panic(err) + d.runStopChan = make(chan struct{}) + d.runStopWaitGroup = &sync.WaitGroup{} + d.runStopWaitGroup.Add(1) + + go func(name string) { + defer d.runStopWaitGroup.Done() + for { + select { + case <-d.runStopChan: + d.runStopChan = nil + return + default: + if err := d.step(); err != nil { + fmt.Printf("motor step skipped for '%s': %v\n", name, err) + } } } - }() + }(d.name) return nil } +// IsMoving returns a bool stating whether motor is currently in motion +func (d *EasyDriver) IsMoving() bool { + return d.runStopChan != nil +} + // Stop running the stepper func (d *EasyDriver) Stop() error { - d.moving = false + if !d.IsMoving() { + return fmt.Errorf("motor '%s' is not yet started", d.name) + } + + d.runStopChan <- struct{}{} + d.runStopWaitGroup.Wait() + return nil } +// Step the stepper 1 step +func (d *EasyDriver) Step() error { + // ensure that move and step can not interfere + d.mutex.Lock() + defer d.mutex.Unlock() + + if d.IsMoving() { + return fmt.Errorf("motor '%s' already running or moving", d.name) + } + + return d.step() +} + // SetDirection sets the direction to be moving. Valid directions are "cw" or "ccw" func (d *EasyDriver) SetDirection(dir string) error { // can't change direct if dirPin isn't set if d.dirPin == "" { - return errors.New("dirPin is not set") + return fmt.Errorf("dirPin is not set for '%s'", d.name) } if dir == "ccw" { d.dir = -1 // high is ccw - return d.connection.DigitalWrite(d.dirPin, 1) + return d.connection.(DigitalWriter).DigitalWrite(d.dirPin, 1) } // default to cw, even if user specified wrong value d.dir = 1 // low is cw - return d.connection.DigitalWrite(d.dirPin, 0) + return d.connection.(DigitalWriter).DigitalWrite(d.dirPin, 0) } -// SetSpeed sets the speed of the motor in RPMs. 1 is the lowest and GetMaxSpeed is the highest +// SetSpeed sets the speed of the motor in RPMs. 1 is the lowest and GetMaxSpeed is the highest func (d *EasyDriver) SetSpeed(rpm uint) error { if rpm < 1 { d.rpm = 1 - } else if rpm > d.GetMaxSpeed() { - d.rpm = d.GetMaxSpeed() + } else if rpm > d.MaxSpeed() { + d.rpm = d.MaxSpeed() } else { d.rpm = rpm } @@ -202,30 +238,26 @@ func (d *EasyDriver) SetSpeed(rpm uint) error { return nil } -// GetMaxSpeed returns the max speed of the stepper -func (d *EasyDriver) GetMaxSpeed() uint { +// MaxSpeed returns the max speed of the stepper +func (d *EasyDriver) MaxSpeed() uint { return uint(360 / d.angle) } -// GetCurrentStep returns current step number -func (d *EasyDriver) GetCurrentStep() int { +// CurrentStep returns current step number +func (d *EasyDriver) CurrentStep() int { return d.stepNum } -// IsMoving returns a bool stating whether motor is currently in motion -func (d *EasyDriver) IsMoving() bool { - return d.moving -} - // Enable enables all motor output func (d *EasyDriver) Enable() error { // can't enable if enPin isn't set. This is fine normally since it will be enabled by default if d.enPin == "" { - return errors.New("enPin is not set. Board is enabled by default") + d.enabled = true + return fmt.Errorf("enPin is not set - board '%s' is enabled by default", d.name) } // enPin is active low - if err := d.connection.DigitalWrite(d.enPin, 0); err != nil { + if err := d.connection.(DigitalWriter).DigitalWrite(d.enPin, 0); err != nil { return err } @@ -237,14 +269,14 @@ func (d *EasyDriver) Enable() error { func (d *EasyDriver) Disable() error { // can't disable if enPin isn't set if d.enPin == "" { - return errors.New("enPin is not set") + return fmt.Errorf("enPin is not set for '%s'", d.name) } - // let's stop the motor first, but do not return on error - err := d.Stop() + // stop the motor if running + err := d.tryStop() // enPin is active low - if e := d.connection.DigitalWrite(d.enPin, 1); e != nil { + if e := d.connection.(DigitalWriter).DigitalWrite(d.enPin, 1); e != nil { err = multierror.Append(err, e) } else { d.enabled = false @@ -262,14 +294,14 @@ func (d *EasyDriver) IsEnabled() bool { func (d *EasyDriver) Sleep() error { // can't sleep if sleepPin isn't set if d.sleepPin == "" { - return errors.New("sleepPin is not set") + return fmt.Errorf("sleepPin is not set for '%s'", d.name) } - // let's stop the motor first - err := d.Stop() + // stop the motor if running + err := d.tryStop() // sleepPin is active low - if e := d.connection.DigitalWrite(d.sleepPin, 0); e != nil { + if e := d.connection.(DigitalWriter).DigitalWrite(d.sleepPin, 0); e != nil { err = multierror.Append(err, e) } else { d.sleeping = true @@ -282,24 +314,52 @@ func (d *EasyDriver) Sleep() error { func (d *EasyDriver) Wake() error { // can't wake if sleepPin isn't set if d.sleepPin == "" { - return errors.New("sleepPin is not set") + return fmt.Errorf("sleepPin is not set for '%s'", d.name) } // sleepPin is active low - if err := d.connection.DigitalWrite(d.sleepPin, 1); err != nil { + if err := d.connection.(DigitalWriter).DigitalWrite(d.sleepPin, 1); err != nil { return err } d.sleeping = false // we need to wait 1ms after sleeping before doing a step to charge the step pump (according to data sheet) - // this will ensure that happens time.Sleep(1 * time.Millisecond) return nil } -// IsSleeping returns a bool stating whether motor is enabled +// IsSleeping returns a bool stating whether motor is sleeping func (d *EasyDriver) IsSleeping() bool { return d.sleeping } + +func (d *EasyDriver) step() error { + stepsPerRev := d.MaxSpeed() + + // a valid steps occurs for a low to high transition + if err := d.connection.(DigitalWriter).DigitalWrite(d.stepPin, 0); err != nil { + return err + } + // 1 minute / steps per revolution / revolutions per minute + // let's keep it as Microseconds so we only have to do integer math + time.Sleep(time.Duration(60*1000*1000/stepsPerRev/d.rpm) * time.Microsecond) + if err := d.connection.(DigitalWriter).DigitalWrite(d.stepPin, 1); err != nil { + return err + } + + // increment or decrement the number of steps by 1 + d.stepNum += int(d.dir) + + return nil +} + +// tryStop stop the stepper if moving or running +func (d *EasyDriver) tryStop() error { + if !d.IsMoving() { + return nil + } + + return d.Stop() +} diff --git a/drivers/gpio/easy_driver_test.go b/drivers/gpio/easy_driver_test.go index 669aeeb7b..087848d8d 100644 --- a/drivers/gpio/easy_driver_test.go +++ b/drivers/gpio/easy_driver_test.go @@ -1,11 +1,14 @@ package gpio import ( + "fmt" "strings" + "sync" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -13,174 +16,618 @@ const ( stepsPerRev = 720 ) -var adapter *gpioTestAdaptor - -func initEasyDriver() *EasyDriver { - adapter = newGpioTestAdaptor() - return NewEasyDriver(adapter, stepAngle, "1", "2", "3", "4") -} - -func TestEasyDriver_Connection(t *testing.T) { - d := initEasyDriver() - assert.Equal(t, adapter, d.Connection()) -} - -func TestEasyDriverDefaultName(t *testing.T) { - d := initEasyDriver() - assert.True(t, strings.HasPrefix(d.Name(), "EasyDriver")) +func initTestEasyDriverWithStubbedAdaptor() (*EasyDriver, *gpioTestAdaptor) { + a := newGpioTestAdaptor() + d := NewEasyDriver(a, stepAngle, "1", "2", "3", "4") + return d, a } -func TestEasyDriverSetName(t *testing.T) { - d := initEasyDriver() - d.SetName("OtherDriver") - assert.True(t, strings.HasPrefix(d.Name(), "OtherDriver")) -} - -func TestEasyDriverStart(t *testing.T) { - d := initEasyDriver() - _ = d.Start() - // noop - no error occurred +func TestNewEasyDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewEasyDriver(a, stepAngle, "1", "2", "3", "4") + // assert + assert.IsType(t, &EasyDriver{}, d) + assert.True(t, strings.HasPrefix(d.name, "EasyDriver")) + assert.Equal(t, a, d.connection) + assert.NoError(t, d.afterStart()) + assert.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + assert.Equal(t, "1", d.stepPin) + assert.Equal(t, "2", d.dirPin) + assert.Equal(t, "3", d.enPin) + assert.Equal(t, "4", d.sleepPin) + assert.Equal(t, float32(stepAngle), d.angle) + assert.Equal(t, uint(180), d.rpm) + assert.Equal(t, int8(1), d.dir) + assert.Equal(t, 0, d.stepNum) + assert.Equal(t, true, d.enabled) + assert.Equal(t, false, d.sleeping) + assert.Nil(t, d.runStopChan) } func TestEasyDriverHalt(t *testing.T) { - d := initEasyDriver() - _ = d.Run() - assert.True(t, d.IsMoving()) - _ = d.Halt() + // arrange + d, _ := initTestEasyDriverWithStubbedAdaptor() + require.NoError(t, d.Run()) + require.True(t, d.IsMoving()) + // act + err := d.Halt() + // assert + assert.NoError(t, err) assert.False(t, d.IsMoving()) } func TestEasyDriverMove(t *testing.T) { - d := initEasyDriver() - _ = d.Move(2) - time.Sleep(2 * time.Millisecond) - assert.Equal(t, 4, d.GetCurrentStep()) - assert.False(t, d.IsMoving()) + tests := map[string]struct { + inputSteps int + simulateDisabled bool + simulateAlreadyRunning bool + simulateWriteErr bool + wantWrites int + wantSteps int + wantMoving bool + wantErr string + }{ + "move_one": { + inputSteps: 1, + wantWrites: 4, + wantSteps: 2, + wantMoving: false, + }, + "move_more": { + inputSteps: 20, + wantWrites: 80, + wantSteps: 40, + wantMoving: false, + }, + "error_disabled": { + simulateDisabled: true, + wantMoving: false, + wantErr: "is disabled", + }, + "error_already_running": { + simulateAlreadyRunning: true, + wantMoving: true, + wantErr: "already running or moving", + }, + "error_write": { + inputSteps: 1, + simulateWriteErr: true, + wantWrites: 1, + wantMoving: false, + wantErr: "write error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, a := initTestEasyDriverWithStubbedAdaptor() + d.enabled = !tc.simulateDisabled + if tc.simulateAlreadyRunning { + d.runStopChan = make(chan struct{}) + defer func() { close(d.runStopChan); d.runStopChan = nil }() + } + var numCallsWrite int + a.digitalWriteFunc = func(string, byte) error { + numCallsWrite++ + if tc.simulateWriteErr { + return fmt.Errorf("write error") + } + return nil + } + // act + err := d.Move(tc.inputSteps) + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.wantSteps, d.stepNum) + assert.Equal(t, tc.wantWrites, numCallsWrite) + assert.Equal(t, tc.wantMoving, d.IsMoving()) + }) + } } -func TestEasyDriverRun(t *testing.T) { - d := initEasyDriver() - _ = d.Run() - assert.True(t, d.IsMoving()) - _ = d.Run() - assert.True(t, d.IsMoving()) +func TestEasyDriverRun_IsMoving(t *testing.T) { + tests := map[string]struct { + simulateDisabled bool + simulateAlreadyRunning bool + simulateWriteErr bool + wantMoving bool + wantErr string + }{ + "run": { + wantMoving: true, + }, + "error_disabled": { + simulateDisabled: true, + wantMoving: false, + wantErr: "is disabled", + }, + "write_error_skipped": { + simulateWriteErr: true, + wantMoving: true, + }, + "error_already_running": { + simulateAlreadyRunning: true, + wantMoving: true, + wantErr: "already running or moving", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, a := initTestEasyDriverWithStubbedAdaptor() + d.enabled = !tc.simulateDisabled + if tc.simulateAlreadyRunning { + d.runStopChan = make(chan struct{}) + defer func() { close(d.runStopChan); d.runStopChan = nil }() + } + simWriteErr := tc.simulateWriteErr // to prevent data race in write function (go-called) + a.digitalWriteFunc = func(string, byte) error { + if simWriteErr { + simWriteErr = false // to prevent to much output + return fmt.Errorf("write error") + } + return nil + } + // act + err := d.Run() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.wantMoving, d.IsMoving()) + }) + } } -func TestEasyDriverStop(t *testing.T) { - d := initEasyDriver() - _ = d.Run() - assert.True(t, d.IsMoving()) - _ = d.Stop() +func TestEasyDriverStop_IsMoving(t *testing.T) { + // arrange + d, _ := initTestEasyDriverWithStubbedAdaptor() + require.NoError(t, d.Run()) + require.True(t, d.IsMoving()) + // act + err := d.Stop() + // assert + assert.NoError(t, err) assert.False(t, d.IsMoving()) } func TestEasyDriverStep(t *testing.T) { - d := initEasyDriver() - _ = d.Step() - assert.Equal(t, 1, d.GetCurrentStep()) - _ = d.Step() - _ = d.Step() - _ = d.Step() - assert.Equal(t, 4, d.GetCurrentStep()) - _ = d.SetDirection("ccw") - _ = d.Step() - assert.Equal(t, 3, d.GetCurrentStep()) + tests := map[string]struct { + countCallsForth int + countCallsBack int + simulateAlreadyRunning bool + simulateWriteErr bool + wantSteps int + wantWritten []byte + wantErr string + }{ + "single": { + countCallsForth: 1, + wantSteps: 1, + wantWritten: []byte{0x00, 0x01}, + }, + "many": { + countCallsForth: 4, + wantSteps: 4, + wantWritten: []byte{0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1}, + }, + "forth_and_back": { + countCallsForth: 5, + countCallsBack: 3, + wantSteps: 2, + wantWritten: []byte{0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1}, + }, + "reverse": { + countCallsBack: 3, + wantSteps: -3, + wantWritten: []byte{0x0, 0x1, 0x0, 0x1, 0x0, 0x1}, + }, + "error_already_running": { + countCallsForth: 1, + simulateAlreadyRunning: true, + wantErr: "already running or moving", + }, + "error_write": { + simulateWriteErr: true, + wantWritten: []byte{0x00, 0x00}, + countCallsBack: 2, + wantErr: "write error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, a := initTestEasyDriverWithStubbedAdaptor() + if tc.simulateAlreadyRunning { + d.runStopChan = make(chan struct{}) + defer func() { close(d.runStopChan); d.runStopChan = nil }() + } + var writtenValues []byte + a.digitalWriteFunc = func(pin string, val byte) error { + assert.Equal(t, d.stepPin, pin) + writtenValues = append(writtenValues, val) + if tc.simulateWriteErr { + return fmt.Errorf("write error") + } + return nil + } + var errs []string + // act + for i := 0; i < tc.countCallsForth; i++ { + if err := d.Step(); err != nil { + errs = append(errs, err.Error()) + } + } + d.dir = -1 + for i := 0; i < tc.countCallsBack; i++ { + if err := d.Step(); err != nil { + errs = append(errs, err.Error()) + } + } + // assert + if tc.wantErr != "" { + assert.Contains(t, strings.Join(errs, ","), tc.wantErr) + } else { + assert.Nil(t, errs) + } + assert.Equal(t, tc.wantSteps, d.stepNum) + assert.Equal(t, tc.wantSteps, d.CurrentStep()) + assert.Equal(t, tc.wantWritten, writtenValues) + }) + } } func TestEasyDriverSetDirection(t *testing.T) { - d := initEasyDriver() - assert.Equal(t, int8(1), d.dir) - _ = d.SetDirection("cw") - assert.Equal(t, int8(1), d.dir) - _ = d.SetDirection("ccw") - assert.Equal(t, int8(-1), d.dir) - _ = d.SetDirection("nothing") - assert.Equal(t, int8(1), d.dir) -} - -func TestEasyDriverSetDirectionNoPin(t *testing.T) { - d := initEasyDriver() - d.dirPin = "" - err := d.SetDirection("cw") - assert.NotNil(t, err) + tests := map[string]struct { + dirPin string + input string + wantVal int8 + wantErr string + }{ + "cw": { + input: "cw", + dirPin: "10", + wantVal: 1, + }, + "ccw": { + input: "ccw", + dirPin: "11", + wantVal: -1, + }, + "unknown": { + input: "unknown", + dirPin: "12", + wantVal: 1, + }, + "error_no_pin": { + dirPin: "", + wantVal: 1, + wantErr: "dirPin is not set", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + d := NewEasyDriver(a, stepAngle, "1", tc.dirPin, "3", "4") + require.Equal(t, int8(1), d.dir) + // act + err := d.SetDirection(tc.input) + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.wantVal, d.dir) + }) + } } func TestEasyDriverSetSpeed(t *testing.T) { - d := initEasyDriver() - assert.Equal(t, uint(stepsPerRev/4), d.rpm) // default speed of 720/4 - _ = d.SetSpeed(0) - assert.Equal(t, uint(1), d.rpm) - _ = d.SetSpeed(200) - assert.Equal(t, uint(200), d.rpm) - _ = d.SetSpeed(1000) - assert.Equal(t, uint(stepsPerRev), d.rpm) -} + const ( + angle = 10 + max = 36 // 360/angle + ) -func TestEasyDriverGetMaxSpeed(t *testing.T) { - d := initEasyDriver() - assert.Equal(t, uint(stepsPerRev), d.GetMaxSpeed()) + tests := map[string]struct { + input uint + want uint + }{ + "below_minimum": { + input: 0, + want: 1, + }, + "minimum": { + input: 1, + want: 1, + }, + "maximum": { + input: max, + want: max, + }, + "above_maximum": { + input: max + 1, + want: max, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := EasyDriver{angle: angle} + // act + err := d.SetSpeed(tc.input) + // assert + assert.NoError(t, err) + assert.Equal(t, tc.want, d.rpm) + }) + } } -func TestEasyDriverSleep(t *testing.T) { - // let's test basic functionality - d := initEasyDriver() - _ = d.Sleep() - assert.True(t, d.IsSleeping()) - - // let's make sure it stops first - d = initEasyDriver() - _ = d.Run() - _ = d.Sleep() - assert.True(t, d.IsSleeping()) - assert.False(t, d.IsMoving()) -} - -func TestEasyDriverSleepNoPin(t *testing.T) { - d := initEasyDriver() - d.sleepPin = "" - err := d.Sleep() - assert.NotNil(t, err) - err = d.Wake() - assert.NotNil(t, err) +func TestEasyDriverMaxSpeed(t *testing.T) { + tests := map[string]struct { + angle float32 + want uint + }{ + "180": { + angle: 2.0, + want: 180, + }, + "360": { + angle: 1.0, + want: 360, + }, + "720": { + angle: 0.5, + want: 720, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := EasyDriver{angle: tc.angle} + // act & assert + assert.Equal(t, tc.want, d.MaxSpeed()) + }) + } } -func TestEasyDriverWake(t *testing.T) { - // let's test basic functionality - d := initEasyDriver() - _ = d.Sleep() - assert.True(t, d.IsSleeping()) - _ = d.Wake() - assert.False(t, d.IsSleeping()) +func TestEasyDriverEnable_IsEnabled(t *testing.T) { + tests := map[string]struct { + enPin string + simulateWriteErr bool + wantWrites int + wantEnabled bool + wantErr string + }{ + "basic": { + enPin: "10", + wantWrites: 1, + wantEnabled: true, + }, + "with_run": { + enPin: "11", + wantWrites: 1, + wantEnabled: true, + }, + "error_no_pin": { + enPin: "", + wantWrites: 0, + wantEnabled: true, // is enabled by default + wantErr: "enPin is not set", + }, + "error_write": { + enPin: "12", + simulateWriteErr: true, + wantWrites: 1, + wantEnabled: false, + wantErr: "write error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + d := NewEasyDriver(a, stepAngle, "1", "2", tc.enPin, "4") + var numCallsWrite int + var writtenPin string + writtenValue := byte(0xFF) + a.digitalWriteFunc = func(pin string, val byte) error { + numCallsWrite++ + writtenPin = pin + writtenValue = val + if tc.simulateWriteErr { + return fmt.Errorf("write error") + } + return nil + } + d.enabled = false + require.False(t, d.IsEnabled()) + // act + err := d.Enable() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + assert.Equal(t, byte(0), writtenValue) // enable pin is active low + } + assert.Equal(t, tc.wantEnabled, d.IsEnabled()) + assert.Equal(t, tc.wantWrites, numCallsWrite) + assert.Equal(t, tc.enPin, writtenPin) + }) + } } -func TestEasyDriverEnable(t *testing.T) { - // let's test basic functionality - d := initEasyDriver() - _ = d.Disable() - assert.False(t, d.IsEnabled()) - _ = d.Enable() - assert.True(t, d.IsEnabled()) +func TestEasyDriverDisable_IsEnabled(t *testing.T) { + tests := map[string]struct { + enPin string + runBefore bool + simulateWriteErr string + wantWrites int + wantEnabled bool + wantErr string + }{ + "basic": { + enPin: "10", + wantWrites: 1, + wantEnabled: false, + }, + "with_run": { + enPin: "10", + runBefore: true, + wantWrites: 1, + wantEnabled: false, + }, + "error_no_pin": { + enPin: "", + wantWrites: 0, + wantEnabled: true, // is enabled by default + wantErr: "enPin is not set", + }, + "error_write": { + enPin: "12", + simulateWriteErr: "write error", + wantWrites: 1, + wantEnabled: true, + wantErr: "write error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + d := NewEasyDriver(a, stepAngle, "1", "2", tc.enPin, "4") + writeMutex := sync.Mutex{} + var numCallsWrite int + var writtenPin string + writtenValue := byte(0xFF) + a.digitalWriteFunc = func(pin string, val byte) error { + writeMutex.Lock() + defer writeMutex.Unlock() + if pin == d.stepPin { + // we do not consider call of step() + return nil + } + numCallsWrite++ + writtenPin = pin + writtenValue = val + if tc.simulateWriteErr != "" { + return fmt.Errorf(tc.simulateWriteErr) + } + return nil + } + if tc.runBefore { + require.NoError(t, d.Run()) + require.True(t, d.IsMoving()) + time.Sleep(time.Millisecond) + } + d.enabled = true + require.True(t, d.IsEnabled()) + // act + err := d.Disable() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + assert.Equal(t, byte(1), writtenValue) // enable pin is active low + } + assert.Equal(t, tc.wantEnabled, d.IsEnabled()) + assert.False(t, d.IsMoving()) + assert.Equal(t, tc.wantWrites, numCallsWrite) + assert.Equal(t, tc.enPin, writtenPin) + }) + } } -func TestEasyDriverEnableNoPin(t *testing.T) { - d := initEasyDriver() - d.enPin = "" - err := d.Disable() - assert.NotNil(t, err) - err = d.Enable() - assert.NotNil(t, err) +func TestEasyDriverSleep_IsSleeping(t *testing.T) { + tests := map[string]struct { + sleepPin string + runBefore bool + wantSleep bool + wantErr string + }{ + "basic": { + sleepPin: "10", + wantSleep: true, + }, + "with_run": { + sleepPin: "11", + runBefore: true, + wantSleep: true, + }, + "error_no_pin": { + sleepPin: "", + wantSleep: false, + wantErr: "sleepPin is not set", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + d := NewEasyDriver(a, stepAngle, "1", "2", "3", tc.sleepPin) + if tc.runBefore { + require.NoError(t, d.Run()) + } + d.sleeping = false + require.False(t, d.IsSleeping()) + // act + err := d.Sleep() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.wantSleep, d.IsSleeping()) + }) + } } -func TestEasyDriverDisable(t *testing.T) { - // let's test basic functionality - d := initEasyDriver() - _ = d.Disable() - assert.False(t, d.IsEnabled()) - - // let's make sure it stops first - d = initEasyDriver() - _ = d.Run() - _ = d.Disable() - assert.False(t, d.IsEnabled()) - assert.False(t, d.IsMoving()) +func TestEasyDriverWake_IsSleeping(t *testing.T) { + tests := map[string]struct { + sleepPin string + wantSleep bool + wantErr string + }{ + "basic": { + sleepPin: "10", + wantSleep: false, + }, + "error_no_pin": { + sleepPin: "", + wantSleep: true, + wantErr: "sleepPin is not set", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + d := NewEasyDriver(a, stepAngle, "1", "2", "3", tc.sleepPin) + d.sleeping = true + require.True(t, d.IsSleeping()) + // act + err := d.Wake() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.wantSleep, d.IsSleeping()) + }) + } } diff --git a/drivers/gpio/gpio_driver_test.go b/drivers/gpio/gpio_driver_test.go index 30ae59bbc..da26d6b14 100644 --- a/drivers/gpio/gpio_driver_test.go +++ b/drivers/gpio/gpio_driver_test.go @@ -25,12 +25,9 @@ func TestNewDriver(t *testing.T) { // arrange a := newGpioTestAdaptor() // act - var di interface{} = NewDriver(a, "GPIO_BASIC") + d := NewDriver(a, "GPIO_BASIC") // assert - d, ok := di.(*Driver) - if !ok { - t.Errorf("NewDriver() should have returned a *Driver") - } + assert.IsType(t, &Driver{}, d) assert.Contains(t, d.name, "GPIO_BASIC") assert.Equal(t, a, d.connection) assert.NoError(t, d.afterStart()) From c41604f5f9a86ca80dd4fbe0f02b81bf5b011ddb Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Wed, 1 Nov 2023 14:51:07 +0100 Subject: [PATCH 22/57] gpio: fix data race in ButtonDriver (#1027) --- README.md | 2 +- drivers/gpio/README.md | 2 +- drivers/gpio/button_driver.go | 76 ++++++---- drivers/gpio/button_driver_test.go | 185 +++++++++++++++-------- drivers/gpio/makey_button_driver.go | 101 ------------- drivers/gpio/makey_button_driver_test.go | 117 -------------- examples/beaglebone_makey_button.go | 38 ----- examples/firmata_makey_button.go | 46 ------ 8 files changed, 169 insertions(+), 398 deletions(-) delete mode 100644 drivers/gpio/makey_button_driver.go delete mode 100644 drivers/gpio/makey_button_driver_test.go delete mode 100644 examples/beaglebone_makey_button.go delete mode 100644 examples/firmata_makey_button.go diff --git a/README.md b/README.md index 8a1a4310a..2becbb603 100644 --- a/README.md +++ b/README.md @@ -284,7 +284,7 @@ a shared set of drivers provided using the `gobot/drivers/gpio` package: - HC-SR04 Ultrasonic Ranging Module - HD44780 LCD controller - LED - - Makey Button + - Makey Button (by using driver for Button) - MAX7219 LED Dot Matrix - Motor - Proximity Infra Red (PIR) Motion Sensor diff --git a/drivers/gpio/README.md b/drivers/gpio/README.md index fbd8fe192..8426a02c0 100644 --- a/drivers/gpio/README.md +++ b/drivers/gpio/README.md @@ -26,7 +26,7 @@ Gobot has a extensible system for connecting to hardware devices. The following - HC-SR04 Ultrasonic Ranging Module - HD44780 LCD controller - LED -- Makey Button +- Makey Button (by using driver for Button) - MAX7219 LED Dot Matrix - Motor - Proximity Infra Red (PIR) Motion Sensor diff --git a/drivers/gpio/button_driver.go b/drivers/gpio/button_driver.go index b5451de09..978ae375b 100644 --- a/drivers/gpio/button_driver.go +++ b/drivers/gpio/button_driver.go @@ -8,14 +8,13 @@ import ( // ButtonDriver Represents a digital Button type ButtonDriver struct { - Active bool - DefaultState int + *Driver + gobot.Eventer pin string - name string + active bool + defaultState int halt chan bool interval time.Duration - connection DigitalReader - gobot.Eventer } // NewButtonDriver returns a new ButtonDriver with a polling interval of @@ -26,15 +25,16 @@ type ButtonDriver struct { // time.Duration: Interval at which the ButtonDriver is polled for new information func NewButtonDriver(a DigitalReader, pin string, v ...time.Duration) *ButtonDriver { b := &ButtonDriver{ - name: gobot.DefaultName("Button"), - connection: a, - pin: pin, - Active: false, - DefaultState: 0, + Driver: NewDriver(a.(gobot.Connection), "Button"), Eventer: gobot.NewEventer(), + pin: pin, + active: false, + defaultState: 0, interval: 10 * time.Millisecond, halt: make(chan bool), } + b.afterStart = b.initialize + b.beforeHalt = b.shutdown if len(v) > 0 { b.interval = v[0] @@ -47,18 +47,39 @@ func NewButtonDriver(a DigitalReader, pin string, v ...time.Duration) *ButtonDri return b } -// Start starts the ButtonDriver and polls the state of the button at the given interval. +// Pin returns the ButtonDrivers pin +func (b *ButtonDriver) Pin() string { return b.pin } + +// Active gets the current state +func (b *ButtonDriver) Active() bool { + // ensure that read and write can not interfere + b.mutex.Lock() + defer b.mutex.Unlock() + + return b.active +} + +// SetDefaultState for the next start. +func (b *ButtonDriver) SetDefaultState(s int) { + // ensure that read and write can not interfere + b.mutex.Lock() + defer b.mutex.Unlock() + + b.defaultState = s +} + +// initialize the ButtonDriver and polls the state of the button at the given interval. // // Emits the Events: // // Push int - On button push // Release int - On button release // Error error - On button error -func (b *ButtonDriver) Start() (err error) { - state := b.DefaultState +func (b *ButtonDriver) initialize() (err error) { + state := b.defaultState go func() { for { - newValue, err := b.connection.DigitalRead(b.Pin()) + newValue, err := b.connection.(DigitalReader).DigitalRead(b.Pin()) if err != nil { b.Publish(Error, err) } else if newValue != state && newValue != -1 { @@ -75,30 +96,21 @@ func (b *ButtonDriver) Start() (err error) { return } -// Halt stops polling the button for new information -func (b *ButtonDriver) Halt() (err error) { +func (b *ButtonDriver) shutdown() (err error) { b.halt <- true - return + return nil } -// Name returns the ButtonDrivers name -func (b *ButtonDriver) Name() string { return b.name } - -// SetName sets the ButtonDrivers name -func (b *ButtonDriver) SetName(n string) { b.name = n } - -// Pin returns the ButtonDrivers pin -func (b *ButtonDriver) Pin() string { return b.pin } - -// Connection returns the ButtonDrivers Connection -func (b *ButtonDriver) Connection() gobot.Connection { return b.connection.(gobot.Connection) } - func (b *ButtonDriver) update(newValue int) { - if newValue != b.DefaultState { - b.Active = true + // ensure that read and write can not interfere + b.mutex.Lock() + defer b.mutex.Unlock() + + if newValue != b.defaultState { + b.active = true b.Publish(ButtonPush, newValue) } else { - b.Active = false + b.active = false b.Publish(ButtonRelease, newValue) } } diff --git a/drivers/gpio/button_driver_test.go b/drivers/gpio/button_driver_test.go index 7455418cd..681c02ffe 100644 --- a/drivers/gpio/button_driver_test.go +++ b/drivers/gpio/button_driver_test.go @@ -3,10 +3,12 @@ package gpio import ( "errors" "strings" + "sync" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -14,43 +16,66 @@ var _ gobot.Driver = (*ButtonDriver)(nil) const buttonTestDelay = 250 -func initTestButtonDriver() *ButtonDriver { - return NewButtonDriver(newGpioTestAdaptor(), "1") -} - -func TestButtonDriverHalt(t *testing.T) { - d := initTestButtonDriver() - go func() { - <-d.halt - }() - assert.NoError(t, d.Halt()) +func initTestButtonDriverWithStubbedAdaptor() (*ButtonDriver, *gpioTestAdaptor) { + a := newGpioTestAdaptor() + d := NewButtonDriver(a, "1") + return d, a } -func TestButtonDriver(t *testing.T) { - d := NewButtonDriver(newGpioTestAdaptor(), "1") - assert.NotNil(t, d.Connection()) - +func TestNewButtonDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewButtonDriver(a, "1") + // assert + assert.IsType(t, &ButtonDriver{}, d) + assert.True(t, strings.HasPrefix(d.name, "Button")) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + assert.NotNil(t, d.Eventer) + assert.Equal(t, "1", d.pin) + assert.Equal(t, false, d.active) + assert.Equal(t, 0, d.defaultState) + assert.Equal(t, 10*time.Millisecond, d.interval) + assert.NotNil(t, d.halt) + // act & assert other interval d = NewButtonDriver(newGpioTestAdaptor(), "1", 30*time.Second) assert.Equal(t, 30*time.Second, d.interval) } -func TestButtonDriverStart(t *testing.T) { +func TestButtonStart(t *testing.T) { + // arrange sem := make(chan bool) - a := newGpioTestAdaptor() - d := NewButtonDriver(a, "1") + nextVal := make(chan int, 1) + d, a := initTestButtonDriverWithStubbedAdaptor() + + a.digitalReadFunc = func(string) (int, error) { + val := 1 + var err error + select { + case val = <-nextVal: + if val < 0 { + err = errors.New("digital read error") + } + return val, err + default: + return val, err + } + } _ = d.Once(ButtonPush, func(data interface{}) { - assert.True(t, d.Active) + assert.True(t, d.Active()) + nextVal <- 0 sem <- true }) - a.digitalReadFunc = func(string) (val int, err error) { - val = 1 - return - } - + // act assert.NoError(t, d.Start()) + // assert & rearrange select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): @@ -58,15 +83,11 @@ func TestButtonDriverStart(t *testing.T) { } _ = d.Once(ButtonRelease, func(data interface{}) { - assert.False(t, d.Active) + assert.False(t, d.Active()) + nextVal <- -1 sem <- true }) - a.digitalReadFunc = func(string) (val int, err error) { - val = 0 - return - } - select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): @@ -77,11 +98,6 @@ func TestButtonDriverStart(t *testing.T) { sem <- true }) - a.digitalReadFunc = func(string) (val int, err error) { - err = errors.New("digital read error") - return - } - select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): @@ -93,11 +109,7 @@ func TestButtonDriverStart(t *testing.T) { }) d.halt <- true - - a.digitalReadFunc = func(string) (val int, err error) { - val = 1 - return - } + nextVal <- 1 select { case <-sem: @@ -106,22 +118,32 @@ func TestButtonDriverStart(t *testing.T) { } } -func TestButtonDriverDefaultState(t *testing.T) { +func TestButtonSetDefaultState(t *testing.T) { + // arrange sem := make(chan bool) - a := newGpioTestAdaptor() - d := NewButtonDriver(a, "1") - d.DefaultState = 1 - + nextVal := make(chan int, 1) + d, a := initTestButtonDriverWithStubbedAdaptor() + + a.digitalReadFunc = func(string) (int, error) { + val := 0 + select { + case val = <-nextVal: + return val, nil + default: + return val, nil + } + } _ = d.Once(ButtonPush, func(data interface{}) { - assert.True(t, d.Active) + assert.True(t, d.Active()) + nextVal <- 1 sem <- true }) - a.digitalReadFunc = func(string) (val int, err error) { - val = 0 - return - } + // act + d.SetDefaultState(1) + // assert & rearrange + require.Equal(t, 1, d.defaultState) assert.NoError(t, d.Start()) select { @@ -131,15 +153,11 @@ func TestButtonDriverDefaultState(t *testing.T) { } _ = d.Once(ButtonRelease, func(data interface{}) { - assert.False(t, d.Active) + assert.False(t, d.Active()) + sem <- true }) - a.digitalReadFunc = func(string) (val int, err error) { - val = 1 - return - } - select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): @@ -147,13 +165,56 @@ func TestButtonDriverDefaultState(t *testing.T) { } } -func TestButtonDriverDefaultName(t *testing.T) { - g := initTestButtonDriver() - assert.True(t, strings.HasPrefix(g.Name(), "Button")) +func TestButtonHalt(t *testing.T) { + // arrange + d, _ := initTestButtonDriverWithStubbedAdaptor() + const timeout = 10 * time.Microsecond + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + select { + case <-d.halt: // wait until halt was set to the channel + case <-time.After(timeout): // otherwise run into the timeout + t.Errorf("halt was not received within %s", timeout) + } + }() + // act & assert + assert.NoError(t, d.Halt()) + wg.Wait() // wait until the go function was really finished } -func TestButtonDriverSetName(t *testing.T) { - g := initTestButtonDriver() - g.SetName("mybot") - assert.Equal(t, "mybot", g.Name()) +func TestButtonPin(t *testing.T) { + tests := map[string]struct { + want string + }{ + "10": {want: "10"}, + "36": {want: "36"}, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := ButtonDriver{pin: name} + // act & assert + assert.Equal(t, tc.want, d.Pin()) + }) + } +} + +func TestButtonActive(t *testing.T) { + tests := map[string]struct { + want bool + }{ + "active_true": {want: true}, + "active_false": {want: false}, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := ButtonDriver{Driver: NewDriver(nil, "Button")} // just for mutex + d.active = tc.want + // act & assert + assert.Equal(t, tc.want, d.Active()) + }) + } } diff --git a/drivers/gpio/makey_button_driver.go b/drivers/gpio/makey_button_driver.go deleted file mode 100644 index fa3a31464..000000000 --- a/drivers/gpio/makey_button_driver.go +++ /dev/null @@ -1,101 +0,0 @@ -package gpio - -import ( - "time" - - "gobot.io/x/gobot/v2" -) - -// MakeyButtonDriver Represents a Makey Button -type MakeyButtonDriver struct { - name string - pin string - halt chan bool - connection DigitalReader - Active bool - interval time.Duration - gobot.Eventer -} - -// NewMakeyButtonDriver returns a new MakeyButtonDriver with a polling interval of -// 10 Milliseconds given a DigitalReader and pin. -// -// Optionally accepts: -// -// time.Duration: Interval at which the ButtonDriver is polled for new information -func NewMakeyButtonDriver(a DigitalReader, pin string, v ...time.Duration) *MakeyButtonDriver { - m := &MakeyButtonDriver{ - name: gobot.DefaultName("MakeyButton"), - connection: a, - pin: pin, - Active: false, - Eventer: gobot.NewEventer(), - interval: 10 * time.Millisecond, - halt: make(chan bool), - } - - if len(v) > 0 { - m.interval = v[0] - } - - m.AddEvent(Error) - m.AddEvent(ButtonPush) - m.AddEvent(ButtonRelease) - - return m -} - -// Name returns the MakeyButtonDrivers name -func (b *MakeyButtonDriver) Name() string { return b.name } - -// SetName sets the MakeyButtonDrivers name -func (b *MakeyButtonDriver) SetName(n string) { b.name = n } - -// Pin returns the MakeyButtonDrivers pin -func (b *MakeyButtonDriver) Pin() string { return b.pin } - -// Connection returns the MakeyButtonDrivers Connection -func (b *MakeyButtonDriver) Connection() gobot.Connection { return b.connection.(gobot.Connection) } - -// Start starts the MakeyButtonDriver and polls the state of the button at the given interval. -// -// Emits the Events: -// -// Push int - On button push -// Release int - On button release -// Error error - On button error -func (b *MakeyButtonDriver) Start() (err error) { - state := 1 - go func() { - timer := time.NewTimer(b.interval) - timer.Stop() - for { - newValue, err := b.connection.DigitalRead(b.Pin()) - if err != nil { - b.Publish(Error, err) - } else if newValue != state && newValue != -1 { - state = newValue - if newValue == 0 { - b.Active = true - b.Publish(ButtonPush, newValue) - } else { - b.Active = false - b.Publish(ButtonRelease, newValue) - } - } - timer.Reset(b.interval) - select { - case <-timer.C: - case <-b.halt: - return - } - } - }() - return -} - -// Halt stops polling the makey button for new information -func (b *MakeyButtonDriver) Halt() (err error) { - b.halt <- true - return -} diff --git a/drivers/gpio/makey_button_driver_test.go b/drivers/gpio/makey_button_driver_test.go deleted file mode 100644 index 996e6a39a..000000000 --- a/drivers/gpio/makey_button_driver_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package gpio - -import ( - "errors" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "gobot.io/x/gobot/v2" -) - -var _ gobot.Driver = (*MakeyButtonDriver)(nil) - -const makeyTestDelay = 250 - -func initTestMakeyButtonDriver() *MakeyButtonDriver { - return NewMakeyButtonDriver(newGpioTestAdaptor(), "1") -} - -func TestMakeyButtonDriverHalt(t *testing.T) { - d := initTestMakeyButtonDriver() - done := make(chan struct{}) - go func() { - <-d.halt - close(done) - }() - assert.NoError(t, d.Halt()) - select { - case <-done: - case <-time.After(makeyTestDelay * time.Millisecond): - t.Errorf("MakeyButton was not halted") - } -} - -func TestMakeyButtonDriver(t *testing.T) { - d := initTestMakeyButtonDriver() - assert.Equal(t, "1", d.Pin()) - assert.NotNil(t, d.Connection()) - assert.Equal(t, 10*time.Millisecond, d.interval) - - d = NewMakeyButtonDriver(newGpioTestAdaptor(), "1", 30*time.Second) - assert.Equal(t, 30*time.Second, d.interval) -} - -func TestMakeyButtonDriverStart(t *testing.T) { - sem := make(chan bool) - a := newGpioTestAdaptor() - d := NewMakeyButtonDriver(a, "1") - - assert.NoError(t, d.Start()) - - _ = d.Once(ButtonPush, func(data interface{}) { - assert.True(t, d.Active) - sem <- true - }) - - a.digitalReadFunc = func(string) (val int, err error) { - val = 0 - return - } - - select { - case <-sem: - case <-time.After(makeyTestDelay * time.Millisecond): - t.Errorf("MakeyButton Event \"Push\" was not published") - } - - _ = d.Once(ButtonRelease, func(data interface{}) { - assert.False(t, d.Active) - sem <- true - }) - - a.digitalReadFunc = func(string) (val int, err error) { - val = 1 - return - } - - select { - case <-sem: - case <-time.After(makeyTestDelay * time.Millisecond): - t.Errorf("MakeyButton Event \"Release\" was not published") - } - - _ = d.Once(Error, func(data interface{}) { - assert.Equal(t, "digital read error", data.(error).Error()) - sem <- true - }) - - a.digitalReadFunc = func(string) (val int, err error) { - err = errors.New("digital read error") - return - } - - select { - case <-sem: - case <-time.After(makeyTestDelay * time.Millisecond): - t.Errorf("MakeyButton Event \"Error\" was not published") - } - - // send a halt message - _ = d.Once(ButtonRelease, func(data interface{}) { - sem <- true - }) - - a.digitalReadFunc = func(string) (val int, err error) { - val = 1 - return - } - - d.halt <- true - - select { - case <-sem: - t.Errorf("MakeyButton Event should not have been published") - case <-time.After(makeyTestDelay * time.Millisecond): - } -} diff --git a/examples/beaglebone_makey_button.go b/examples/beaglebone_makey_button.go deleted file mode 100644 index f51e172d6..000000000 --- a/examples/beaglebone_makey_button.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build example -// +build example - -// -// Do not build by default. - -package main - -import ( - "fmt" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/beaglebone" -) - -func main() { - beagleboneAdaptor := beaglebone.NewAdaptor() - button := gpio.NewMakeyButtonDriver(beagleboneAdaptor, "P8_09") - - work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - fmt.Println("button pressed") - }) - - button.On(gpio.ButtonRelease, func(data interface{}) { - fmt.Println("button released") - }) - } - - robot := gobot.NewRobot("makeyBot", - []gobot.Connection{beagleboneAdaptor}, - []gobot.Device{button}, - work, - ) - - robot.Start() -} diff --git a/examples/firmata_makey_button.go b/examples/firmata_makey_button.go deleted file mode 100644 index ff3985937..000000000 --- a/examples/firmata_makey_button.go +++ /dev/null @@ -1,46 +0,0 @@ -//go:build example -// +build example - -// -// Do not build by default. - -/* - How to run - Pass serial port to use as the first param: - - go run examples/firmata_makey_button.go /dev/ttyACM0 -*/ - -package main - -import ( - "os" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/firmata" -) - -func main() { - firmataAdaptor := firmata.NewAdaptor(os.Args[1]) - button := gpio.NewMakeyButtonDriver(firmataAdaptor, "2") - led := gpio.NewLedDriver(firmataAdaptor, "13") - - work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - led.On() - }) - - button.On(gpio.ButtonRelease, func(data interface{}) { - led.Off() - }) - } - - robot := gobot.NewRobot("makeyBot", - []gobot.Connection{firmataAdaptor}, - []gobot.Device{button, led}, - work, - ) - - robot.Start() -} From 9e311b28e41d3393aeb066a32e11d1b314b25bd2 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Wed, 1 Nov 2023 15:49:02 +0100 Subject: [PATCH 23/57] gpio: fix data race in PIRMotionDriver (#1028) --- drivers/gpio/button_driver.go | 6 +- drivers/gpio/button_driver_test.go | 8 +- drivers/gpio/pir_motion_driver.go | 93 ++++++++------- drivers/gpio/pir_motion_driver_test.go | 151 ++++++++++++++++++------- 4 files changed, 170 insertions(+), 88 deletions(-) diff --git a/drivers/gpio/button_driver.go b/drivers/gpio/button_driver.go index 978ae375b..72c62d320 100644 --- a/drivers/gpio/button_driver.go +++ b/drivers/gpio/button_driver.go @@ -75,7 +75,7 @@ func (b *ButtonDriver) SetDefaultState(s int) { // Push int - On button push // Release int - On button release // Error error - On button error -func (b *ButtonDriver) initialize() (err error) { +func (b *ButtonDriver) initialize() error { state := b.defaultState go func() { for { @@ -93,10 +93,10 @@ func (b *ButtonDriver) initialize() (err error) { } } }() - return + return nil } -func (b *ButtonDriver) shutdown() (err error) { +func (b *ButtonDriver) shutdown() error { b.halt <- true return nil } diff --git a/drivers/gpio/button_driver_test.go b/drivers/gpio/button_driver_test.go index 681c02ffe..c9112e42a 100644 --- a/drivers/gpio/button_driver_test.go +++ b/drivers/gpio/button_driver_test.go @@ -1,7 +1,7 @@ package gpio import ( - "errors" + "fmt" "strings" "sync" "testing" @@ -58,7 +58,7 @@ func TestButtonStart(t *testing.T) { select { case val = <-nextVal: if val < 0 { - err = errors.New("digital read error") + err = fmt.Errorf("digital read error") } return val, err default: @@ -73,9 +73,11 @@ func TestButtonStart(t *testing.T) { }) // act - assert.NoError(t, d.Start()) + err := d.Start() // assert & rearrange + assert.NoError(t, err) + select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): diff --git a/drivers/gpio/pir_motion_driver.go b/drivers/gpio/pir_motion_driver.go index f64d8b589..aa32b50e5 100644 --- a/drivers/gpio/pir_motion_driver.go +++ b/drivers/gpio/pir_motion_driver.go @@ -8,13 +8,12 @@ import ( // PIRMotionDriver represents a digital Proximity Infra Red (PIR) motion detecter type PIRMotionDriver struct { - Active bool - pin string - name string - halt chan bool - interval time.Duration - connection DigitalReader + *Driver gobot.Eventer + pin string + active bool + halt chan bool + interval time.Duration } // NewPIRMotionDriver returns a new PIRMotionDriver with a polling interval of @@ -25,14 +24,15 @@ type PIRMotionDriver struct { // time.Duration: Interval at which the PIRMotionDriver is polled for new information func NewPIRMotionDriver(a DigitalReader, pin string, v ...time.Duration) *PIRMotionDriver { b := &PIRMotionDriver{ - name: gobot.DefaultName("PIRMotion"), - connection: a, - pin: pin, - Active: false, - Eventer: gobot.NewEventer(), - interval: 10 * time.Millisecond, - halt: make(chan bool), + Driver: NewDriver(a.(gobot.Connection), "PIRMotion"), + Eventer: gobot.NewEventer(), + pin: pin, + active: false, + interval: 10 * time.Millisecond, + halt: make(chan bool), } + b.afterStart = b.initialize + b.beforeHalt = b.shutdown if len(v) > 0 { b.interval = v[0] @@ -45,7 +45,19 @@ func NewPIRMotionDriver(a DigitalReader, pin string, v ...time.Duration) *PIRMot return b } -// Start starts the PIRMotionDriver and polls the state of the sensor at the given interval. +// Pin returns the PIRMotionDriver pin +func (p *PIRMotionDriver) Pin() string { return p.pin } + +// Active gets the current state +func (p *PIRMotionDriver) Active() bool { + // ensure that read and write can not interfere + p.mutex.Lock() + defer p.mutex.Unlock() + + return p.active +} + +// initialize the PIRMotionDriver and polls the state of the sensor at the given interval. // // Emits the Events: // @@ -57,26 +69,14 @@ func NewPIRMotionDriver(a DigitalReader, pin string, v ...time.Duration) *PIRMot // just as long as motion is still being detected. // It will only send the MotionStopped event once, however, until // motion starts being detected again -func (p *PIRMotionDriver) Start() (err error) { +func (p *PIRMotionDriver) initialize() error { go func() { for { - newValue, err := p.connection.DigitalRead(p.Pin()) + newValue, err := p.connection.(DigitalReader).DigitalRead(p.Pin()) if err != nil { p.Publish(Error, err) } - switch newValue { - case 1: - if !p.Active { - p.Active = true - p.Publish(MotionDetected, newValue) - } - case 0: - if p.Active { - p.Active = false - p.Publish(MotionStopped, newValue) - } - } - + p.update(newValue) select { case <-time.After(p.interval): case <-p.halt: @@ -84,23 +84,30 @@ func (p *PIRMotionDriver) Start() (err error) { } } }() - return + return nil } -// Halt stops polling the button for new information -func (p *PIRMotionDriver) Halt() (err error) { +// shutdown stops polling +func (p *PIRMotionDriver) shutdown() error { p.halt <- true - return + return nil } -// Name returns the PIRMotionDriver name -func (p *PIRMotionDriver) Name() string { return p.name } +func (p *PIRMotionDriver) update(newValue int) { + // ensure that read and write can not interfere + p.mutex.Lock() + defer p.mutex.Unlock() -// SetName sets the PIRMotionDriver name -func (p *PIRMotionDriver) SetName(n string) { p.name = n } - -// Pin returns the PIRMotionDriver pin -func (p *PIRMotionDriver) Pin() string { return p.pin } - -// Connection returns the PIRMotionDriver Connection -func (p *PIRMotionDriver) Connection() gobot.Connection { return p.connection.(gobot.Connection) } + switch newValue { + case 1: + if !p.active { + p.active = true + p.Publish(MotionDetected, newValue) + } + case 0: + if p.active { + p.active = false + p.Publish(MotionStopped, newValue) + } + } +} diff --git a/drivers/gpio/pir_motion_driver_test.go b/drivers/gpio/pir_motion_driver_test.go index 79ab0d710..b1ad17cd3 100644 --- a/drivers/gpio/pir_motion_driver_test.go +++ b/drivers/gpio/pir_motion_driver_test.go @@ -1,8 +1,9 @@ package gpio import ( - "errors" + "fmt" "strings" + "sync" "testing" "time" @@ -14,42 +15,67 @@ var _ gobot.Driver = (*PIRMotionDriver)(nil) const motionTestDelay = 150 -func initTestPIRMotionDriver() *PIRMotionDriver { - return NewPIRMotionDriver(newGpioTestAdaptor(), "1") -} - -func TestPIRMotionDriverHalt(t *testing.T) { - d := initTestPIRMotionDriver() - go func() { - <-d.halt - }() - assert.NoError(t, d.Halt()) +func initTestPIRMotionDriverWithStubbedAdaptor() (*PIRMotionDriver, *gpioTestAdaptor) { + a := newGpioTestAdaptor() + d := NewPIRMotionDriver(a, "1") + return d, a } -func TestPIRMotionDriver(t *testing.T) { - d := NewPIRMotionDriver(newGpioTestAdaptor(), "1") - assert.NotNil(t, d.Connection()) - +func TestNewPIRMotionDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewPIRMotionDriver(a, "1") + // assert + assert.IsType(t, &PIRMotionDriver{}, d) + assert.True(t, strings.HasPrefix(d.name, "PIRMotion")) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + assert.NotNil(t, d.Eventer) + assert.Equal(t, "1", d.pin) + assert.Equal(t, false, d.active) + assert.Equal(t, 10*time.Millisecond, d.interval) + assert.NotNil(t, d.halt) + // act & assert other interval d = NewPIRMotionDriver(newGpioTestAdaptor(), "1", 30*time.Second) assert.Equal(t, 30*time.Second, d.interval) } -func TestPIRMotionDriverStart(t *testing.T) { +func TestPIRMotionStart(t *testing.T) { + // arrange sem := make(chan bool) + nextVal := make(chan int, 1) a := newGpioTestAdaptor() d := NewPIRMotionDriver(a, "1") - assert.NoError(t, d.Start()) + a.digitalReadFunc = func(string) (int, error) { + val := 1 + var err error + select { + case val = <-nextVal: + if val < 0 { + err = fmt.Errorf("digital read error") + } + return val, err + default: + return val, err + } + } _ = d.Once(MotionDetected, func(data interface{}) { - assert.True(t, d.Active) + assert.True(t, d.active) + nextVal <- 0 sem <- true }) - a.digitalReadFunc = func(string) (val int, err error) { - val = 1 - return - } + // act + err := d.Start() + + // assert & rearrange + assert.NoError(t, err) select { case <-sem: @@ -58,15 +84,11 @@ func TestPIRMotionDriverStart(t *testing.T) { } _ = d.Once(MotionStopped, func(data interface{}) { - assert.False(t, d.Active) + assert.False(t, d.active) + nextVal <- -1 sem <- true }) - a.digitalReadFunc = func(string) (val int, err error) { - val = 0 - return - } - select { case <-sem: case <-time.After(motionTestDelay * time.Millisecond): @@ -77,25 +99,76 @@ func TestPIRMotionDriverStart(t *testing.T) { sem <- true }) - a.digitalReadFunc = func(string) (val int, err error) { - err = errors.New("digital read error") - return + select { + case <-sem: + case <-time.After(motionTestDelay * time.Millisecond): + t.Errorf("PIRMotionDriver Event \"Error\" was not published") } + _ = d.Once(MotionDetected, func(data interface{}) { + sem <- true + }) + + d.halt <- true + nextVal <- 1 + select { case <-sem: + t.Errorf("PIRMotion Event \"MotionDetected\" should not published") case <-time.After(motionTestDelay * time.Millisecond): - t.Errorf("PIRMotionDriver Event \"Error\" was not published") } } -func TestPIRDriverDefaultName(t *testing.T) { - d := initTestPIRMotionDriver() - assert.True(t, strings.HasPrefix(d.Name(), "PIR")) +func TestPIRMotionHalt(t *testing.T) { + // arrange + d, _ := initTestPIRMotionDriverWithStubbedAdaptor() + const timeout = 10 * time.Microsecond + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + select { + case <-d.halt: // wait until halt was set to the channel + case <-time.After(timeout): // otherwise run into the timeout + t.Errorf("halt was not received within %s", timeout) + } + }() + // act & assert + assert.NoError(t, d.Halt()) + wg.Wait() // wait until the go function was really finished +} + +func TestPIRMotionPin(t *testing.T) { + tests := map[string]struct { + want string + }{ + "10": {want: "10"}, + "36": {want: "36"}, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := PIRMotionDriver{pin: name} + // act & assert + assert.Equal(t, tc.want, d.Pin()) + }) + } } -func TestPIRDriverSetName(t *testing.T) { - d := initTestPIRMotionDriver() - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) +func TestPIRMotionActive(t *testing.T) { + tests := map[string]struct { + want bool + }{ + "active_true": {want: true}, + "active_false": {want: false}, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := PIRMotionDriver{Driver: NewDriver(nil, "PIRMotion")} // just for mutex + d.active = tc.want + // act & assert + assert.Equal(t, tc.want, d.Active()) + }) + } } From a04ce8a7f24b8127b2e83a19cd903364a7925e2e Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Thu, 9 Nov 2023 20:31:18 +0100 Subject: [PATCH 24/57] gpio: fix data race in StepperDriver (#1029) --- Makefile | 1 + drivers/gpio/easy_driver.go | 332 +++++----------- drivers/gpio/easy_driver_test.go | 567 +++++++++++++++++----------- drivers/gpio/helpers_test.go | 28 +- drivers/gpio/stepper_driver.go | 511 ++++++++++++++++++------- drivers/gpio/stepper_driver_test.go | 469 +++++++++++++++++++---- examples/raspi_stepper_move.go | 59 ++- 7 files changed, 1269 insertions(+), 698 deletions(-) diff --git a/Makefile b/Makefile index b83504e45..85cfec583 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ fmt_check: fmt_fix: $(MAKE) version_check || true gofumpt -l -w . + golangci-lint run -v --fix examples: $(EXAMPLES) diff --git a/drivers/gpio/easy_driver.go b/drivers/gpio/easy_driver.go index 26687d71b..c7c01a8ed 100644 --- a/drivers/gpio/easy_driver.go +++ b/drivers/gpio/easy_driver.go @@ -2,257 +2,111 @@ package gpio import ( "fmt" - "log" - "strconv" - "sync" + "strings" "time" - "github.com/hashicorp/go-multierror" "gobot.io/x/gobot/v2" ) -// EasyDriver object +const easyDriverDebug = false + +// EasyDriver is an driver for stepper hardware board from SparkFun (https://www.sparkfun.com/products/12779) +// This should also work for the BigEasyDriver (untested). It is basically a wrapper for the common StepperDriver{} +// with the specific additions for the board, e.g. direction, enable and sleep outputs. type EasyDriver struct { - *Driver - - stepPin string - dirPin string - enPin string - sleepPin string - - angle float32 - rpm uint - dir int8 - stepNum int - enabled bool - sleeping bool - runStopChan chan struct{} - runStopWaitGroup *sync.WaitGroup + *StepperDriver + + stepPin string + dirPin string + enPin string + sleepPin string + anglePerStep float32 + + sleeping bool } -// NewEasyDriver returns a new driver for EasyDriver from SparkFun (https://www.sparkfun.com/products/12779) +// NewEasyDriver returns a new driver // TODO: Support selecting phase input instead of hard-wiring MS1 and MS2 to board truth table -// This should also work for the BigEasyDriver (untested) // A - DigitalWriter +// anglePerStep - Step angle of motor // stepPin - Pin corresponding to step input on EasyDriver // dirPin - Pin corresponding to dir input on EasyDriver. Optional // enPin - Pin corresponding to enabled input on EasyDriver. Optional // sleepPin - Pin corresponding to sleep input on EasyDriver. Optional -// angle - Step angle of motor func NewEasyDriver( a DigitalWriter, - angle float32, + anglePerStep float32, stepPin string, dirPin string, enPin string, sleepPin string, ) *EasyDriver { - if angle <= 0 { - panic("angle needs to be greater than zero") - } - d := &EasyDriver{ - Driver: NewDriver(a.(gobot.Connection), "EasyDriver"), - stepPin: stepPin, - dirPin: dirPin, - enPin: enPin, - sleepPin: sleepPin, - angle: angle, - rpm: 1, - dir: 1, - enabled: true, - sleeping: false, - } - d.beforeHalt = func() error { - if err := d.Stop(); err != nil { - fmt.Printf("no need to stop motion: %v\n", err) - } - - return nil + if anglePerStep <= 0 { + panic("angle per step needs to be greater than zero") } - // panic if step pin isn't set if stepPin == "" { panic("Step pin is not set") } - // 1/4 of max speed. Not too fast, not too slow - d.rpm = d.MaxSpeed() / 4 - - d.AddCommand("Move", func(params map[string]interface{}) interface{} { - degs, _ := strconv.Atoi(params["degs"].(string)) - return d.Move(degs) - }) - d.AddCommand("Step", func(params map[string]interface{}) interface{} { - return d.Step() - }) - d.AddCommand("Run", func(params map[string]interface{}) interface{} { - return d.Run() - }) - d.AddCommand("Stop", func(params map[string]interface{}) interface{} { - return d.Stop() - }) - - return d -} - -// Move the motor given number of degrees at current speed. The move can be stopped asynchronously. -func (d *EasyDriver) Move(degs int) error { - // ensure that move and run can not interfere - d.mutex.Lock() - defer d.mutex.Unlock() - - if !d.enabled { - return fmt.Errorf("motor '%s' is disabled and can not be running", d.name) - } - - if d.runStopChan != nil { - return fmt.Errorf("motor '%s' already running or moving", d.name) - } - - d.runStopChan = make(chan struct{}) - d.runStopWaitGroup = &sync.WaitGroup{} - d.runStopWaitGroup.Add(1) - - defer func() { - close(d.runStopChan) - d.runStopChan = nil - d.runStopWaitGroup.Done() - }() - - steps := int(float32(degs) / d.angle) - if steps <= 0 { - fmt.Printf("steps are smaller than zero, no move for '%s'\n", d.name) - } - - for i := 0; i < steps; i++ { - select { - case <-d.runStopChan: - // don't continue to step if driver is stopped - log.Println("stop happen") - return nil - default: - if err := d.step(); err != nil { - return err - } - } - } - - return nil -} - -// Run the stepper continuously. -func (d *EasyDriver) Run() error { - // ensure that run, can not interfere with step or move - d.mutex.Lock() - defer d.mutex.Unlock() - - if !d.enabled { - return fmt.Errorf("motor '%s' is disabled and can not be moving", d.name) - } - - if d.runStopChan != nil { - return fmt.Errorf("motor '%s' already running or moving", d.name) - } - - d.runStopChan = make(chan struct{}) - d.runStopWaitGroup = &sync.WaitGroup{} - d.runStopWaitGroup.Add(1) - - go func(name string) { - defer d.runStopWaitGroup.Done() - for { - select { - case <-d.runStopChan: - d.runStopChan = nil - return - default: - if err := d.step(); err != nil { - fmt.Printf("motor step skipped for '%s': %v\n", name, err) - } - } - } - }(d.name) - - return nil -} - -// IsMoving returns a bool stating whether motor is currently in motion -func (d *EasyDriver) IsMoving() bool { - return d.runStopChan != nil -} + stepper := NewStepperDriver(a, [4]string{}, nil, 1) + stepper.name = gobot.DefaultName("EasyDriver") + stepper.stepperDebug = easyDriverDebug + stepper.haltIfRunning = false + stepper.stepsPerRev = 360.0 / anglePerStep + d := &EasyDriver{ + StepperDriver: stepper, + stepPin: stepPin, + dirPin: dirPin, + enPin: enPin, + sleepPin: sleepPin, + anglePerStep: anglePerStep, -// Stop running the stepper -func (d *EasyDriver) Stop() error { - if !d.IsMoving() { - return fmt.Errorf("motor '%s' is not yet started", d.name) + sleeping: false, } + d.stepFunc = d.onePinStepping + d.sleepFunc = d.sleepWithSleepPin + d.beforeHalt = d.shutdown - d.runStopChan <- struct{}{} - d.runStopWaitGroup.Wait() + // 1/4 of max speed. Not too fast, not too slow + d.speedRpm = d.MaxSpeed() / 4 - return nil + return d } -// Step the stepper 1 step -func (d *EasyDriver) Step() error { - // ensure that move and step can not interfere - d.mutex.Lock() - defer d.mutex.Unlock() - - if d.IsMoving() { - return fmt.Errorf("motor '%s' already running or moving", d.name) +// SetDirection sets the direction to be moving. +func (d *EasyDriver) SetDirection(direction string) error { + direction = strings.ToLower(direction) + if direction != StepperDriverForward && direction != StepperDriverBackward { + return fmt.Errorf("Invalid direction '%s'. Value should be '%s' or '%s'", + direction, StepperDriverForward, StepperDriverBackward) } - return d.step() -} - -// SetDirection sets the direction to be moving. Valid directions are "cw" or "ccw" -func (d *EasyDriver) SetDirection(dir string) error { - // can't change direct if dirPin isn't set if d.dirPin == "" { return fmt.Errorf("dirPin is not set for '%s'", d.name) } - if dir == "ccw" { - d.dir = -1 - // high is ccw - return d.connection.(DigitalWriter).DigitalWrite(d.dirPin, 1) + writeVal := byte(0) // low is forward + if direction == StepperDriverBackward { + writeVal = 1 // high is backward } - // default to cw, even if user specified wrong value - d.dir = 1 - // low is cw - return d.connection.(DigitalWriter).DigitalWrite(d.dirPin, 0) -} - -// SetSpeed sets the speed of the motor in RPMs. 1 is the lowest and GetMaxSpeed is the highest -func (d *EasyDriver) SetSpeed(rpm uint) error { - if rpm < 1 { - d.rpm = 1 - } else if rpm > d.MaxSpeed() { - d.rpm = d.MaxSpeed() - } else { - d.rpm = rpm + if err := d.connection.(DigitalWriter).DigitalWrite(d.dirPin, writeVal); err != nil { + return err } - return nil -} - -// MaxSpeed returns the max speed of the stepper -func (d *EasyDriver) MaxSpeed() uint { - return uint(360 / d.angle) -} + // ensure that write of variable can not interfere with read in step() + d.valueMutex.Lock() + defer d.valueMutex.Unlock() + d.direction = direction -// CurrentStep returns current step number -func (d *EasyDriver) CurrentStep() int { - return d.stepNum + return nil } // Enable enables all motor output func (d *EasyDriver) Enable() error { - // can't enable if enPin isn't set. This is fine normally since it will be enabled by default if d.enPin == "" { - d.enabled = true + d.disabled = false return fmt.Errorf("enPin is not set - board '%s' is enabled by default", d.name) } @@ -261,58 +115,34 @@ func (d *EasyDriver) Enable() error { return err } - d.enabled = true + d.disabled = false return nil } // Disable disables all motor output func (d *EasyDriver) Disable() error { - // can't disable if enPin isn't set if d.enPin == "" { return fmt.Errorf("enPin is not set for '%s'", d.name) } - // stop the motor if running - err := d.tryStop() + _ = d.stopIfRunning() // drop step errors // enPin is active low - if e := d.connection.(DigitalWriter).DigitalWrite(d.enPin, 1); e != nil { - err = multierror.Append(err, e) - } else { - d.enabled = false + if err := d.connection.(DigitalWriter).DigitalWrite(d.enPin, 1); err != nil { + return err } + d.disabled = true - return err + return nil } // IsEnabled returns a bool stating whether motor is enabled func (d *EasyDriver) IsEnabled() bool { - return d.enabled -} - -// Sleep puts the driver to sleep and disables all motor output. Low power mode. -func (d *EasyDriver) Sleep() error { - // can't sleep if sleepPin isn't set - if d.sleepPin == "" { - return fmt.Errorf("sleepPin is not set for '%s'", d.name) - } - - // stop the motor if running - err := d.tryStop() - - // sleepPin is active low - if e := d.connection.(DigitalWriter).DigitalWrite(d.sleepPin, 0); e != nil { - err = multierror.Append(err, e) - } else { - d.sleeping = true - } - - return err + return !d.disabled } // Wake wakes up the driver func (d *EasyDriver) Wake() error { - // can't wake if sleepPin isn't set if d.sleepPin == "" { return fmt.Errorf("sleepPin is not set for '%s'", d.name) } @@ -335,31 +165,43 @@ func (d *EasyDriver) IsSleeping() bool { return d.sleeping } -func (d *EasyDriver) step() error { - stepsPerRev := d.MaxSpeed() +func (d *EasyDriver) onePinStepping() error { + // ensure that read and write of variables (direction, stepNum) can not interfere + d.valueMutex.Lock() + defer d.valueMutex.Unlock() // a valid steps occurs for a low to high transition if err := d.connection.(DigitalWriter).DigitalWrite(d.stepPin, 0); err != nil { return err } - // 1 minute / steps per revolution / revolutions per minute - // let's keep it as Microseconds so we only have to do integer math - time.Sleep(time.Duration(60*1000*1000/stepsPerRev/d.rpm) * time.Microsecond) + + time.Sleep(d.getDelayPerStep()) if err := d.connection.(DigitalWriter).DigitalWrite(d.stepPin, 1); err != nil { return err } - // increment or decrement the number of steps by 1 - d.stepNum += int(d.dir) + if d.direction == StepperDriverForward { + d.stepNum++ + } else { + d.stepNum-- + } return nil } -// tryStop stop the stepper if moving or running -func (d *EasyDriver) tryStop() error { - if !d.IsMoving() { - return nil +// sleepWithSleepPin puts the driver to sleep and disables all motor output. Low power mode. +func (d *EasyDriver) sleepWithSleepPin() error { + if d.sleepPin == "" { + return fmt.Errorf("sleepPin is not set for '%s'", d.name) } - return d.Stop() + _ = d.stopIfRunning() // drop step errors + + // sleepPin is active low + if err := d.connection.(DigitalWriter).DigitalWrite(d.sleepPin, 0); err != nil { + return err + } + d.sleeping = true + + return nil } diff --git a/drivers/gpio/easy_driver_test.go b/drivers/gpio/easy_driver_test.go index 087848d8d..5e978ed68 100644 --- a/drivers/gpio/easy_driver_test.go +++ b/drivers/gpio/easy_driver_test.go @@ -3,7 +3,6 @@ package gpio import ( "fmt" "strings" - "sync" "testing" "time" @@ -11,22 +10,21 @@ import ( "github.com/stretchr/testify/require" ) -const ( - stepAngle = 0.5 // use non int step angle to check int math - stepsPerRev = 720 -) - func initTestEasyDriverWithStubbedAdaptor() (*EasyDriver, *gpioTestAdaptor) { + const anglePerStep = 0.5 // use non int step angle to check int math + a := newGpioTestAdaptor() - d := NewEasyDriver(a, stepAngle, "1", "2", "3", "4") + d := NewEasyDriver(a, anglePerStep, "1", "2", "3", "4") return d, a } func TestNewEasyDriver(t *testing.T) { // arrange + const anglePerStep = 0.5 // use non int step angle to check int math + a := newGpioTestAdaptor() // act - d := NewEasyDriver(a, stepAngle, "1", "2", "3", "4") + d := NewEasyDriver(a, anglePerStep, "1", "2", "3", "4") // assert assert.IsType(t, &EasyDriver{}, d) assert.True(t, strings.HasPrefix(d.name, "EasyDriver")) @@ -39,30 +37,18 @@ func TestNewEasyDriver(t *testing.T) { assert.Equal(t, "2", d.dirPin) assert.Equal(t, "3", d.enPin) assert.Equal(t, "4", d.sleepPin) - assert.Equal(t, float32(stepAngle), d.angle) - assert.Equal(t, uint(180), d.rpm) - assert.Equal(t, int8(1), d.dir) + assert.Equal(t, float32(anglePerStep), d.anglePerStep) + assert.Equal(t, uint(14), d.speedRpm) + assert.Equal(t, "forward", d.direction) assert.Equal(t, 0, d.stepNum) - assert.Equal(t, true, d.enabled) + assert.Equal(t, false, d.disabled) assert.Equal(t, false, d.sleeping) - assert.Nil(t, d.runStopChan) -} - -func TestEasyDriverHalt(t *testing.T) { - // arrange - d, _ := initTestEasyDriverWithStubbedAdaptor() - require.NoError(t, d.Run()) - require.True(t, d.IsMoving()) - // act - err := d.Halt() - // assert - assert.NoError(t, err) - assert.False(t, d.IsMoving()) + assert.Nil(t, d.stopAsynchRunFunc) } -func TestEasyDriverMove(t *testing.T) { +func TestEasyDriverMoveDeg_IsMoving(t *testing.T) { tests := map[string]struct { - inputSteps int + inputDeg int simulateDisabled bool simulateAlreadyRunning bool simulateWriteErr bool @@ -72,13 +58,13 @@ func TestEasyDriverMove(t *testing.T) { wantErr string }{ "move_one": { - inputSteps: 1, + inputDeg: 1, wantWrites: 4, wantSteps: 2, wantMoving: false, }, "move_more": { - inputSteps: 20, + inputDeg: 20, wantWrites: 80, wantSteps: 40, wantMoving: false, @@ -94,9 +80,9 @@ func TestEasyDriverMove(t *testing.T) { wantErr: "already running or moving", }, "error_write": { - inputSteps: 1, + inputDeg: 1, simulateWriteErr: true, - wantWrites: 1, + wantWrites: 0, wantMoving: false, wantErr: "write error", }, @@ -105,21 +91,23 @@ func TestEasyDriverMove(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange d, a := initTestEasyDriverWithStubbedAdaptor() - d.enabled = !tc.simulateDisabled - if tc.simulateAlreadyRunning { - d.runStopChan = make(chan struct{}) - defer func() { close(d.runStopChan); d.runStopChan = nil }() - } - var numCallsWrite int - a.digitalWriteFunc = func(string, byte) error { - numCallsWrite++ - if tc.simulateWriteErr { - return fmt.Errorf("write error") + defer func() { + // for cleanup dangling channels + if d.stopAsynchRunFunc != nil { + err := d.stopAsynchRunFunc(true) + assert.NoError(t, err) } - return nil + }() + // arrange: different behavior + d.disabled = tc.simulateDisabled + if tc.simulateAlreadyRunning { + d.stopAsynchRunFunc = func(bool) error { return nil } } + // arrange: writes + a.written = nil // reset writes of Start() + a.simulateWriteError = tc.simulateWriteErr // act - err := d.Move(tc.inputSteps) + err := d.MoveDeg(tc.inputDeg) // assert if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) @@ -127,7 +115,7 @@ func TestEasyDriverMove(t *testing.T) { assert.NoError(t, err) } assert.Equal(t, tc.wantSteps, d.stepNum) - assert.Equal(t, tc.wantWrites, numCallsWrite) + assert.Equal(t, tc.wantWrites, len(a.written)) assert.Equal(t, tc.wantMoving, d.IsMoving()) }) } @@ -163,10 +151,10 @@ func TestEasyDriverRun_IsMoving(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange d, a := initTestEasyDriverWithStubbedAdaptor() - d.enabled = !tc.simulateDisabled + d.skipStepErrors = true + d.disabled = tc.simulateDisabled if tc.simulateAlreadyRunning { - d.runStopChan = make(chan struct{}) - defer func() { close(d.runStopChan); d.runStopChan = nil }() + d.stopAsynchRunFunc = func(bool) error { return nil } } simWriteErr := tc.simulateWriteErr // to prevent data race in write function (go-called) a.digitalWriteFunc = func(string, byte) error { @@ -201,208 +189,289 @@ func TestEasyDriverStop_IsMoving(t *testing.T) { assert.False(t, d.IsMoving()) } -func TestEasyDriverStep(t *testing.T) { +func TestEasyDriverHalt_IsMoving(t *testing.T) { + // arrange + d, _ := initTestEasyDriverWithStubbedAdaptor() + require.NoError(t, d.Run()) + require.True(t, d.IsMoving()) + // act + err := d.Halt() + // assert + assert.NoError(t, err) + assert.False(t, d.IsMoving()) +} + +func TestEasyDriverSetDirection(t *testing.T) { + const anglePerStep = 0.5 // use non int step angle to check int math + tests := map[string]struct { - countCallsForth int - countCallsBack int - simulateAlreadyRunning bool - simulateWriteErr bool - wantSteps int - wantWritten []byte - wantErr string + input string + dirPin string + simulateWriteErr bool + wantVal string + wantWritten byte + wantErr string }{ - "single": { - countCallsForth: 1, - wantSteps: 1, - wantWritten: []byte{0x00, 0x01}, - }, - "many": { - countCallsForth: 4, - wantSteps: 4, - wantWritten: []byte{0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1}, + "forward": { + input: "forward", + dirPin: "10", + wantWritten: 0, + wantVal: "forward", + }, + "backward": { + input: "backward", + dirPin: "11", + wantWritten: 1, + wantVal: "backward", }, - "forth_and_back": { - countCallsForth: 5, - countCallsBack: 3, - wantSteps: 2, - wantWritten: []byte{0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1}, - }, - "reverse": { - countCallsBack: 3, - wantSteps: -3, - wantWritten: []byte{0x0, 0x1, 0x0, 0x1, 0x0, 0x1}, + "unknown": { + input: "unknown", + dirPin: "12", + wantWritten: 0xFF, + wantVal: "forward", + wantErr: "Invalid direction 'unknown'", }, - "error_already_running": { - countCallsForth: 1, - simulateAlreadyRunning: true, - wantErr: "already running or moving", + "error_no_pin": { + input: "forward", + dirPin: "", + wantWritten: 0xFF, + wantVal: "forward", + wantErr: "dirPin is not set", }, "error_write": { + input: "backward", + dirPin: "13", simulateWriteErr: true, - wantWritten: []byte{0x00, 0x00}, - countCallsBack: 2, + wantWritten: 0xFF, + wantVal: "forward", wantErr: "write error", }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - d, a := initTestEasyDriverWithStubbedAdaptor() - if tc.simulateAlreadyRunning { - d.runStopChan = make(chan struct{}) - defer func() { close(d.runStopChan); d.runStopChan = nil }() - } - var writtenValues []byte - a.digitalWriteFunc = func(pin string, val byte) error { - assert.Equal(t, d.stepPin, pin) - writtenValues = append(writtenValues, val) - if tc.simulateWriteErr { - return fmt.Errorf("write error") - } - return nil - } - var errs []string + a := newGpioTestAdaptor() + d := NewEasyDriver(a, anglePerStep, "1", tc.dirPin, "3", "4") + a.written = nil // reset writes of Start() + a.simulateWriteError = tc.simulateWriteErr + require.Equal(t, "forward", d.direction) // act - for i := 0; i < tc.countCallsForth; i++ { - if err := d.Step(); err != nil { - errs = append(errs, err.Error()) - } - } - d.dir = -1 - for i := 0; i < tc.countCallsBack; i++ { - if err := d.Step(); err != nil { - errs = append(errs, err.Error()) - } - } + err := d.SetDirection(tc.input) // assert if tc.wantErr != "" { - assert.Contains(t, strings.Join(errs, ","), tc.wantErr) + assert.ErrorContains(t, err, tc.wantErr) } else { - assert.Nil(t, errs) + assert.NoError(t, err) + assert.Equal(t, tc.dirPin, a.written[0].pin) + assert.Equal(t, tc.wantWritten, a.written[0].val) } - assert.Equal(t, tc.wantSteps, d.stepNum) - assert.Equal(t, tc.wantSteps, d.CurrentStep()) - assert.Equal(t, tc.wantWritten, writtenValues) + assert.Equal(t, tc.wantVal, d.direction) }) } } -func TestEasyDriverSetDirection(t *testing.T) { +func TestEasyDriverMaxSpeed(t *testing.T) { + const delayForMaxSpeed = 1428 * time.Microsecond // 1/700Hz + tests := map[string]struct { - dirPin string - input string - wantVal int8 - wantErr string + anglePerStep float32 + want uint }{ - "cw": { - input: "cw", - dirPin: "10", - wantVal: 1, + "maxspeed_for_20spr": { + anglePerStep: 360.0 / 20.0, + want: 2100, }, - "ccw": { - input: "ccw", - dirPin: "11", - wantVal: -1, + "maxspeed_for_36spr": { + anglePerStep: 360.0 / 36.0, + want: 1166, }, - "unknown": { - input: "unknown", - dirPin: "12", - wantVal: 1, + "maxspeed_for_50spr": { + anglePerStep: 360.0 / 50.0, + want: 840, }, - "error_no_pin": { - dirPin: "", - wantVal: 1, - wantErr: "dirPin is not set", + "maxspeed_for_100spr": { + anglePerStep: 360.0 / 100.0, + want: 420, + }, + "maxspeed_for_400spr": { + anglePerStep: 360.0 / 400.0, + want: 105, }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - a := newGpioTestAdaptor() - d := NewEasyDriver(a, stepAngle, "1", tc.dirPin, "3", "4") - require.Equal(t, int8(1), d.dir) + d, _ := initTestEasyDriverWithStubbedAdaptor() + d.anglePerStep = tc.anglePerStep + d.stepsPerRev = 360.0 / tc.anglePerStep // act - err := d.SetDirection(tc.input) + got := d.MaxSpeed() + d.speedRpm = got + got2 := d.getDelayPerStep() // assert - if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) - } else { - assert.NoError(t, err) - } - assert.Equal(t, tc.wantVal, d.dir) + assert.Equal(t, tc.want, got) + assert.Equal(t, delayForMaxSpeed.Microseconds()/10, got2.Microseconds()/10) }) } } func TestEasyDriverSetSpeed(t *testing.T) { const ( - angle = 10 - max = 36 // 360/angle + anglePerStep = 10 + maxRpm = 1166 ) tests := map[string]struct { - input uint - want uint + input uint + want uint + wantErr string }{ "below_minimum": { - input: 0, - want: 1, + input: 0, + want: 0, + wantErr: "RPM (0) cannot be a zero or negative value", }, "minimum": { input: 1, want: 1, }, "maximum": { - input: max, - want: max, + input: maxRpm, + want: maxRpm, }, "above_maximum": { - input: max + 1, - want: max, + input: maxRpm + 1, + want: maxRpm, + wantErr: "cannot be greater then maximal value 1166", }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - d := EasyDriver{angle: angle} + d, _ := initTestEasyDriverWithStubbedAdaptor() + d.speedRpm = 0 + d.anglePerStep = anglePerStep + d.stepsPerRev = 360.0 / anglePerStep // act err := d.SetSpeed(tc.input) // assert - assert.NoError(t, err) - assert.Equal(t, tc.want, d.rpm) + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.want, d.speedRpm) }) } } -func TestEasyDriverMaxSpeed(t *testing.T) { +func TestEasyDriver_onePinStepping(t *testing.T) { tests := map[string]struct { - angle float32 - want uint + countCallsForth int + countCallsBack int + simulateWriteErr bool + wantSteps int + wantWritten []gpioTestWritten + wantErr string }{ - "180": { - angle: 2.0, - want: 180, + "single": { + countCallsForth: 1, + wantSteps: 1, + wantWritten: []gpioTestWritten{ + {pin: "1", val: 0x00}, + {pin: "1", val: 0x01}, + }, }, - "360": { - angle: 1.0, - want: 360, + "many": { + countCallsForth: 4, + wantSteps: 4, + wantWritten: []gpioTestWritten{ + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + }, }, - "720": { - angle: 0.5, - want: 720, + "forth_and_back": { + countCallsForth: 5, + countCallsBack: 3, + wantSteps: 2, + wantWritten: []gpioTestWritten{ + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + }, + }, + "reverse": { + countCallsBack: 3, + wantSteps: -3, + wantWritten: []gpioTestWritten{ + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + {pin: "1", val: 0x0}, + {pin: "1", val: 0x1}, + }, + }, + "error_write": { + simulateWriteErr: true, + countCallsBack: 2, + wantErr: "write error", }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - d := EasyDriver{angle: tc.angle} - // act & assert - assert.Equal(t, tc.want, d.MaxSpeed()) + d, a := initTestEasyDriverWithStubbedAdaptor() + a.written = nil // reset writes of Start() + a.simulateWriteError = tc.simulateWriteErr + var errs []string + // act + for i := 0; i < tc.countCallsForth; i++ { + if err := d.onePinStepping(); err != nil { + errs = append(errs, err.Error()) + } + } + d.direction = "backward" + for i := 0; i < tc.countCallsBack; i++ { + if err := d.onePinStepping(); err != nil { + errs = append(errs, err.Error()) + } + } + // assert + if tc.wantErr != "" { + assert.Contains(t, strings.Join(errs, ","), tc.wantErr) + } else { + assert.Nil(t, errs) + } + assert.Equal(t, tc.wantSteps, d.stepNum) + assert.Equal(t, tc.wantSteps, d.CurrentStep()) + assert.Equal(t, tc.wantWritten, a.written) }) } } func TestEasyDriverEnable_IsEnabled(t *testing.T) { + const anglePerStep = 0.5 // use non int step angle to check int math + tests := map[string]struct { enPin string simulateWriteErr bool @@ -429,7 +498,7 @@ func TestEasyDriverEnable_IsEnabled(t *testing.T) { "error_write": { enPin: "12", simulateWriteErr: true, - wantWrites: 1, + wantWrites: 0, wantEnabled: false, wantErr: "write error", }, @@ -438,42 +507,34 @@ func TestEasyDriverEnable_IsEnabled(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, stepAngle, "1", "2", tc.enPin, "4") - var numCallsWrite int - var writtenPin string - writtenValue := byte(0xFF) - a.digitalWriteFunc = func(pin string, val byte) error { - numCallsWrite++ - writtenPin = pin - writtenValue = val - if tc.simulateWriteErr { - return fmt.Errorf("write error") - } - return nil - } - d.enabled = false + d := NewEasyDriver(a, anglePerStep, "1", "2", tc.enPin, "4") + a.written = nil // reset writes of Start() + a.simulateWriteError = tc.simulateWriteErr + d.disabled = true require.False(t, d.IsEnabled()) // act err := d.Enable() // assert + assert.Equal(t, tc.wantWrites, len(a.written)) if tc.wantErr != "" { assert.ErrorContains(t, err, tc.wantErr) } else { assert.NoError(t, err) - assert.Equal(t, byte(0), writtenValue) // enable pin is active low + assert.Equal(t, tc.enPin, a.written[0].pin) + assert.Equal(t, byte(0), a.written[0].val) // enable pin is active low } assert.Equal(t, tc.wantEnabled, d.IsEnabled()) - assert.Equal(t, tc.wantWrites, numCallsWrite) - assert.Equal(t, tc.enPin, writtenPin) }) } } func TestEasyDriverDisable_IsEnabled(t *testing.T) { + const anglePerStep = 0.5 // use non int step angle to check int math + tests := map[string]struct { enPin string runBefore bool - simulateWriteErr string + simulateWriteErr bool wantWrites int wantEnabled bool wantErr string @@ -497,7 +558,7 @@ func TestEasyDriverDisable_IsEnabled(t *testing.T) { }, "error_write": { enPin: "12", - simulateWriteErr: "write error", + simulateWriteErr: true, wantWrites: 1, wantEnabled: true, wantErr: "write error", @@ -507,14 +568,11 @@ func TestEasyDriverDisable_IsEnabled(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, stepAngle, "1", "2", tc.enPin, "4") - writeMutex := sync.Mutex{} + d := NewEasyDriver(a, anglePerStep, "1", "2", tc.enPin, "4") var numCallsWrite int var writtenPin string writtenValue := byte(0xFF) a.digitalWriteFunc = func(pin string, val byte) error { - writeMutex.Lock() - defer writeMutex.Unlock() if pin == d.stepPin { // we do not consider call of step() return nil @@ -522,8 +580,8 @@ func TestEasyDriverDisable_IsEnabled(t *testing.T) { numCallsWrite++ writtenPin = pin writtenValue = val - if tc.simulateWriteErr != "" { - return fmt.Errorf(tc.simulateWriteErr) + if tc.simulateWriteErr { + return fmt.Errorf("write error") } return nil } @@ -532,7 +590,7 @@ func TestEasyDriverDisable_IsEnabled(t *testing.T) { require.True(t, d.IsMoving()) time.Sleep(time.Millisecond) } - d.enabled = true + d.disabled = false require.True(t, d.IsEnabled()) // act err := d.Disable() @@ -552,37 +610,68 @@ func TestEasyDriverDisable_IsEnabled(t *testing.T) { } func TestEasyDriverSleep_IsSleeping(t *testing.T) { + const anglePerStep = 0.5 // use non int step angle to check int math + tests := map[string]struct { - sleepPin string - runBefore bool - wantSleep bool - wantErr string + sleepPin string + runBefore bool + simulateWriteErr bool + wantWrites int + wantSleep bool + wantErr string }{ "basic": { - sleepPin: "10", - wantSleep: true, + sleepPin: "10", + wantWrites: 1, + wantSleep: true, }, "with_run": { - sleepPin: "11", - runBefore: true, - wantSleep: true, + sleepPin: "11", + runBefore: true, + wantWrites: 1, + wantSleep: true, }, "error_no_pin": { - sleepPin: "", - wantSleep: false, - wantErr: "sleepPin is not set", + sleepPin: "", + wantSleep: false, + wantWrites: 0, + wantErr: "sleepPin is not set", + }, + "error_write": { + sleepPin: "12", + simulateWriteErr: true, + wantWrites: 1, + wantSleep: false, + wantErr: "write error", }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, stepAngle, "1", "2", "3", tc.sleepPin) + d := NewEasyDriver(a, anglePerStep, "1", "2", "3", tc.sleepPin) + d.sleeping = false + require.False(t, d.IsSleeping()) + // arrange: writes + var numCallsWrite int + var writtenPin string + writtenValue := byte(0xFF) + a.digitalWriteFunc = func(pin string, val byte) error { + if pin == d.stepPin { + // we do not consider call of step() + return nil + } + numCallsWrite++ + writtenPin = pin + writtenValue = val + if tc.simulateWriteErr { + return fmt.Errorf("write error") + } + return nil + } if tc.runBefore { require.NoError(t, d.Run()) } - d.sleeping = false - require.False(t, d.IsSleeping()) // act err := d.Sleep() // assert @@ -590,35 +679,68 @@ func TestEasyDriverSleep_IsSleeping(t *testing.T) { assert.ErrorContains(t, err, tc.wantErr) } else { assert.NoError(t, err) + assert.Equal(t, byte(0), writtenValue) // sleep pin is active low } assert.Equal(t, tc.wantSleep, d.IsSleeping()) + assert.Equal(t, tc.wantWrites, numCallsWrite) + assert.Equal(t, tc.sleepPin, writtenPin) }) } } func TestEasyDriverWake_IsSleeping(t *testing.T) { + const anglePerStep = 0.5 // use non int step angle to check int math + tests := map[string]struct { - sleepPin string - wantSleep bool - wantErr string + sleepPin string + simulateWriteErr bool + wantWrites int + wantSleep bool + wantErr string }{ "basic": { - sleepPin: "10", - wantSleep: false, + sleepPin: "10", + wantWrites: 1, + wantSleep: false, }, "error_no_pin": { - sleepPin: "", - wantSleep: true, - wantErr: "sleepPin is not set", + sleepPin: "", + wantWrites: 0, + wantSleep: true, + wantErr: "sleepPin is not set", + }, + "error_write": { + sleepPin: "12", + simulateWriteErr: true, + wantWrites: 1, + wantSleep: true, + wantErr: "write error", }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, stepAngle, "1", "2", "3", tc.sleepPin) + d := NewEasyDriver(a, anglePerStep, "1", "2", "3", tc.sleepPin) d.sleeping = true require.True(t, d.IsSleeping()) + // arrange: writes + var numCallsWrite int + var writtenPin string + writtenValue := byte(0xFF) + a.digitalWriteFunc = func(pin string, val byte) error { + if pin == d.stepPin { + // we do not consider call of step() + return nil + } + numCallsWrite++ + writtenPin = pin + writtenValue = val + if tc.simulateWriteErr { + return fmt.Errorf("write error") + } + return nil + } // act err := d.Wake() // assert @@ -626,8 +748,11 @@ func TestEasyDriverWake_IsSleeping(t *testing.T) { assert.ErrorContains(t, err, tc.wantErr) } else { assert.NoError(t, err) + assert.Equal(t, byte(1), writtenValue) // sleep pin is active low } assert.Equal(t, tc.wantSleep, d.IsSleeping()) + assert.Equal(t, tc.wantWrites, numCallsWrite) + assert.Equal(t, tc.sleepPin, writtenPin) }) } } diff --git a/drivers/gpio/helpers_test.go b/drivers/gpio/helpers_test.go index 41c051159..a12fa3983 100644 --- a/drivers/gpio/helpers_test.go +++ b/drivers/gpio/helpers_test.go @@ -18,15 +18,22 @@ type digitalPinMock struct { writeFunc func(val int) (err error) } +type gpioTestWritten struct { + pin string + val byte +} + type gpioTestAdaptor struct { - name string - pinMap map[string]gobot.DigitalPinner - port string - mtx sync.Mutex - digitalReadFunc func(ping string) (val int, err error) - digitalWriteFunc func(pin string, val byte) (err error) - pwmWriteFunc func(pin string, val byte) (err error) - servoWriteFunc func(pin string, val byte) (err error) + name string + pinMap map[string]gobot.DigitalPinner + port string + written []gpioTestWritten + simulateWriteError bool + mtx sync.Mutex + digitalReadFunc func(ping string) (val int, err error) + digitalWriteFunc func(pin string, val byte) (err error) + pwmWriteFunc func(pin string, val byte) (err error) + servoWriteFunc func(pin string, val byte) (err error) } func newGpioTestAdaptor() *gpioTestAdaptor { @@ -62,6 +69,11 @@ func (t *gpioTestAdaptor) DigitalRead(pin string) (val int, err error) { func (t *gpioTestAdaptor) DigitalWrite(pin string, val byte) (err error) { t.mtx.Lock() defer t.mtx.Unlock() + if t.simulateWriteError { + return fmt.Errorf("write error") + } + w := gpioTestWritten{pin: pin, val: val} + t.written = append(t.written, w) return t.digitalWriteFunc(pin, val) } diff --git a/drivers/gpio/stepper_driver.go b/drivers/gpio/stepper_driver.go index 1a9469a33..626302f8e 100644 --- a/drivers/gpio/stepper_driver.go +++ b/drivers/gpio/stepper_driver.go @@ -1,8 +1,11 @@ package gpio import ( - "errors" + "fmt" + "log" "math" + "os" + "os/signal" "strconv" "strings" "sync" @@ -11,30 +14,39 @@ import ( "gobot.io/x/gobot/v2" ) +const ( + stepperDriverDebug = false + + // StepperDriverForward is to set the stepper to run in forward direction (e.g. turn clock wise) + StepperDriverForward = "forward" + // StepperDriverBackward is to set the stepper to run in backward direction (e.g. turn counter clock wise) + StepperDriverBackward = "backward" +) + type phase [][4]byte // StepperModes to decide on Phase and Stepping var StepperModes = struct { - SinglePhaseStepping [][4]byte - DualPhaseStepping [][4]byte - HalfStepping [][4]byte + SinglePhaseStepping phase + DualPhaseStepping phase + HalfStepping phase }{ // 1 cycle = 4 steps with lesser torque - SinglePhaseStepping: [][4]byte{ + SinglePhaseStepping: phase{ {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, }, // 1 cycle = 4 steps with higher torque and current - DualPhaseStepping: [][4]byte{ + DualPhaseStepping: phase{ {1, 0, 0, 1}, {1, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 1}, }, // 1 cycle = 8 steps with lesser torque than full stepping - HalfStepping: [][4]byte{ + HalfStepping: phase{ {1, 0, 0, 1}, {1, 0, 0, 0}, {1, 1, 0, 0}, @@ -46,19 +58,26 @@ var StepperModes = struct { }, } -// StepperDriver object +// StepperDriver is a common driver for stepper motors. It supports 3 different stepping modes. type StepperDriver struct { - name string + *Driver + pins [4]string - connection DigitalWriter phase phase - stepsPerRev uint - moving bool - direction string - stepNum int - speed uint - mutex *sync.Mutex - gobot.Commander + stepsPerRev float32 + + stepperDebug bool + speedRpm uint + direction string + skipStepErrors bool + haltIfRunning bool // stop automatically if run is called + disabled bool + valueMutex *sync.Mutex // to ensure that read and write of values do not interfere + + stepFunc func() error + sleepFunc func() error + stepNum int + stopAsynchRunFunc func(bool) error } // NewStepperDriver returns a new StepperDriver given a @@ -67,193 +86,401 @@ type StepperDriver struct { // Phase - Defined by StepperModes {SinglePhaseStepping, DualPhaseStepping, HalfStepping} // Steps - No of steps per revolution of Stepper motor func NewStepperDriver(a DigitalWriter, pins [4]string, phase phase, stepsPerRev uint) *StepperDriver { - s := &StepperDriver{ - name: gobot.DefaultName("Stepper"), - connection: a, - pins: pins, - phase: phase, - stepsPerRev: stepsPerRev, - moving: false, - direction: "forward", - stepNum: 0, - speed: 1, - mutex: &sync.Mutex{}, - Commander: gobot.NewCommander(), + if stepsPerRev <= 0 { + panic("steps per revolution needs to be greater than zero") } - s.speed = s.GetMaxSpeed() - - s.AddCommand("Move", func(params map[string]interface{}) interface{} { + d := &StepperDriver{ + Driver: NewDriver(a.(gobot.Connection), "Stepper"), + pins: pins, + phase: phase, + stepsPerRev: float32(stepsPerRev), + stepperDebug: stepperDriverDebug, + skipStepErrors: false, + haltIfRunning: true, + direction: StepperDriverForward, + stepNum: 0, + speedRpm: 1, + valueMutex: &sync.Mutex{}, + } + d.speedRpm = d.MaxSpeed() + d.stepFunc = d.phasedStepping + d.sleepFunc = d.sleepOuputs + d.beforeHalt = d.shutdown + + d.AddCommand("MoveDeg", func(params map[string]interface{}) interface{} { + degs, _ := strconv.Atoi(params["degs"].(string)) + return d.MoveDeg(degs) + }) + d.AddCommand("Move", func(params map[string]interface{}) interface{} { steps, _ := strconv.Atoi(params["steps"].(string)) - return s.Move(steps) + return d.Move(steps) + }) + d.AddCommand("Step", func(params map[string]interface{}) interface{} { + return d.Move(1) + }) + d.AddCommand("Run", func(params map[string]interface{}) interface{} { + return d.Run() }) - s.AddCommand("Run", func(params map[string]interface{}) interface{} { - return s.Run() + d.AddCommand("Sleep", func(params map[string]interface{}) interface{} { + return d.Sleep() }) - s.AddCommand("Halt", func(params map[string]interface{}) interface{} { - return s.Halt() + d.AddCommand("Stop", func(params map[string]interface{}) interface{} { + return d.Stop() + }) + d.AddCommand("Halt", func(params map[string]interface{}) interface{} { + return d.Halt() }) - return s + return d } -// Name of StepperDriver -func (s *StepperDriver) Name() string { return s.name } +// Move moves the motor for given number of steps. +func (d *StepperDriver) Move(stepsToMove int) error { + d.mutex.Lock() + defer d.mutex.Unlock() + + if err := d.stepAsynch(float64(stepsToMove)); err != nil { + // something went wrong with preparation + return err + } -// SetName sets name for StepperDriver -func (s *StepperDriver) SetName(n string) { s.name = n } + err := d.stopAsynchRunFunc(false) // wait to finish with err or nil + d.stopAsynchRunFunc = nil -// Connection returns StepperDriver's connection -func (s *StepperDriver) Connection() gobot.Connection { return s.connection.(gobot.Connection) } + return err +} -// Start implements the Driver interface and keeps running the stepper till halt is called -func (s *StepperDriver) Start() error { return nil } +// MoveDeg moves the motor given number of degrees at current speed. Negative values cause to move in backward direction. +func (d *StepperDriver) MoveDeg(degs int) error { + d.mutex.Lock() + defer d.mutex.Unlock() -// Run continuously runs the stepper -func (s *StepperDriver) Run() error { - // halt if already moving - if s.moving { - if err := s.Halt(); err != nil { - return err - } + stepsToMove := float64(degs) * float64(d.stepsPerRev) / 360 + + if err := d.stepAsynch(stepsToMove); err != nil { + // something went wrong with preparation + return err } - s.mutex.Lock() - s.moving = true - s.mutex.Unlock() + err := d.stopAsynchRunFunc(false) // wait to finish with err or nil + d.stopAsynchRunFunc = nil - delay := s.getDelayPerStep() + return err +} - go func() { - for { - if !s.moving { - break - } - if err := s.step(); err != nil { - panic(err) - } - time.Sleep(delay) - } - }() +// Run runs the stepper continuously. Stop needs to be done with call Stop(). +func (d *StepperDriver) Run() error { + d.mutex.Lock() + defer d.mutex.Unlock() - return nil + return d.stepAsynch(float64(math.MaxInt) + 1) } -// Halt implements the Driver interface and halts the motion of the Stepper -func (s *StepperDriver) Halt() error { - s.mutex.Lock() - s.moving = false - s.mutex.Unlock() - return nil +// IsMoving returns a bool stating whether motor is currently in motion +func (d *StepperDriver) IsMoving() bool { + return d.stopAsynchRunFunc != nil +} + +// Stop running the stepper +func (d *StepperDriver) Stop() error { + if d.stopAsynchRunFunc == nil { + return fmt.Errorf("'%s' is not yet started", d.name) + } + + err := d.stopAsynchRunFunc(true) + d.stopAsynchRunFunc = nil + + return err } -// SetDirection sets the direction in which motor should be moving, Default is forward -func (s *StepperDriver) SetDirection(direction string) error { +// Sleep release all pins to the same output level, so no current is consumed anymore. +func (d *StepperDriver) Sleep() error { + return d.sleepFunc() +} + +// SetDirection sets the direction in which motor should be moving, default is forward. +// Changing the direction affects the next step, also for asynchronous running. +func (d *StepperDriver) SetDirection(direction string) error { direction = strings.ToLower(direction) - if direction != "forward" && direction != "backward" { - return errors.New("Invalid direction. Value should be forward or backward") + if direction != StepperDriverForward && direction != StepperDriverBackward { + return fmt.Errorf("Invalid direction '%s'. Value should be '%s' or '%s'", + direction, StepperDriverForward, StepperDriverBackward) } - s.mutex.Lock() - s.direction = direction - s.mutex.Unlock() + // ensure that write of variable can not interfere with read in step() + d.valueMutex.Lock() + defer d.valueMutex.Unlock() + d.direction = direction + return nil } -// IsMoving returns a bool stating whether motor is currently in motion -func (s *StepperDriver) IsMoving() bool { - return s.moving +// MaxSpeed gives the max RPM of motor +// max. speed is limited by: +// * motor friction, inertia and inductance, load inertia +// * full step rate is normally below 1000 per second (1kHz), typically not more than ~400 per second +// * mostly not more than 1000-2000rpm (20-40 revolutions per second) are possible +// * higher values can be achieved only by ramp-up the velocity +// * duration of GPIO write (PI1 can reach up to 70kHz, typically 20kHz, so this is most likely not the limiting factor) +// * the hardware driver, to force the high current transitions for the max. speed +// * there are CNC steppers with 1000..20.000 steps per revolution, which works with faster step rates (e.g. 200kHz) +func (d *StepperDriver) MaxSpeed() uint { + const maxStepsPerSecond = 700 // a typical value for a normal, lightly loaded motor + return uint(float32(60*maxStepsPerSecond) / d.stepsPerRev) } -// Step moves motor one step in giving direction -func (s *StepperDriver) step() error { - if s.direction == "forward" { - s.stepNum++ - } else { - s.stepNum-- +// SetSpeed sets the rpm for the next move or run. A valid value is between 1 and MaxSpeed(). +// The run needs to be stopped and called again after set this value. +func (d *StepperDriver) SetSpeed(rpm uint) error { + var err error + if rpm <= 0 { + rpm = 0 + err = fmt.Errorf("RPM (%d) cannot be a zero or negative value", rpm) } - if s.stepNum >= int(s.stepsPerRev) { - s.stepNum = 0 - } else if s.stepNum < 0 { - s.stepNum = int(s.stepsPerRev) - 1 + maxRpm := d.MaxSpeed() + if rpm > maxRpm { + rpm = maxRpm + err = fmt.Errorf("RPM (%d) cannot be greater then maximal value %d", rpm, maxRpm) } - r := int(math.Abs(float64(s.stepNum))) % len(s.phase) + d.valueMutex.Lock() + defer d.valueMutex.Unlock() + d.speedRpm = rpm - for i, v := range s.phase[r] { - if err := s.connection.DigitalWrite(s.pins[i], v); err != nil { - return err - } - } + return err +} - return nil +// CurrentStep gives the current step of motor +func (d *StepperDriver) CurrentStep() int { + // ensure that read can not interfere with write in step() + d.valueMutex.Lock() + defer d.valueMutex.Unlock() + + return d.stepNum } -// Move moves the motor for given number of steps -func (s *StepperDriver) Move(stepsToMove int) error { - if stepsToMove == 0 { - return s.Halt() +// SetHaltIfRunning with the given value. Normally a call of Run() returns an error if already running. If set this +// to true, the next call of Run() cause a automatic stop before. +func (d *StepperDriver) SetHaltIfRunning(val bool) { + d.haltIfRunning = val +} + +// shutdown the driver +func (d *StepperDriver) shutdown() error { + // stops the continuous motion of the stepper, if running + return d.stopIfRunning() +} + +func (d *StepperDriver) stepAsynch(stepsToMove float64) error { + if d.disabled { + return fmt.Errorf("'%s' is disabled and can not be running or moving", d.name) } - if s.moving { - // stop previous motion - if err := s.Halt(); err != nil { + // if running, return error or stop automatically + if d.stopAsynchRunFunc != nil { + if !d.haltIfRunning { + return fmt.Errorf("'%s' already running or moving", d.name) + } + d.debug("stop former run forcefully") + if err := d.stopAsynchRunFunc(true); err != nil { + d.stopAsynchRunFunc = nil return err } } - s.mutex.Lock() - s.moving = true - s.direction = "forward" + // prepare stepping behavior + stepsLeft := uint64(math.Abs(stepsToMove)) + if stepsLeft == 0 { + return fmt.Errorf("no steps to do for '%s'", d.name) + } + + // t [min] = steps [st] / (steps_per_revolution [st/u] * speed [u/min]) or + // t [min] = steps [st] * delay_per_step [min/st], use safety factor 2 and a small offset of 100 ms + // prepare this timeout outside of stop function to prevent data race with stepsLeft + stopTimeout := time.Duration(2*stepsLeft)*d.getDelayPerStep() + 100*time.Millisecond + endlessMovement := false - if stepsToMove < 0 { - s.direction = "backward" + if stepsLeft > math.MaxInt { + stopTimeout = 100 * time.Millisecond + endlessMovement = true + } else { + d.direction = "forward" + if stepsToMove < 0 { + d.direction = "backward" + } } - s.mutex.Unlock() - stepsLeft := int64(math.Abs(float64(stepsToMove))) - delay := s.getDelayPerStep() + // prepare new asynchronous stepping + onceDoneChan := make(chan struct{}) + runStopChan := make(chan struct{}) + runErrChan := make(chan error) + + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt) + + d.stopAsynchRunFunc = func(forceStop bool) error { + defer func() { + d.debug("RUN: cleanup stop channel") + if runStopChan != nil { + close(runStopChan) + } + runStopChan = nil + d.debug("STOP: cleanup err channel") + if runErrChan != nil { + close(runErrChan) + } + runErrChan = nil + d.debug("STOP: cleanup done") + }() + + d.debug("STOP: wait for once done") + <-onceDoneChan // wait for the first step was called - for stepsLeft > 0 { - if err := s.step(); err != nil { + // send stop for endless movement or a forceful stop happen + if endlessMovement || forceStop { + d.debug("STOP: send stop channel") + runStopChan <- struct{}{} + } + + if !endlessMovement && forceStop { + // do not wait if an normal movement was stopped forcefully + log.Printf("'%s' was forcefully stopped\n", d.name) + return nil + } + + // wait for go routine is finished and cleanup + d.debug(fmt.Sprintf("STOP: wait %s for err channel", stopTimeout)) + select { + case err := <-runErrChan: return err + case <-time.After(stopTimeout): + return fmt.Errorf("'%s' was not finished in %s", d.name, stopTimeout) } - stepsLeft-- - time.Sleep(delay) } - s.moving = false + d.debug(fmt.Sprintf("going to start go routine - endless=%t, steps=%d", endlessMovement, stepsLeft)) + go func(name string) { + var err error + var onceDone bool + defer func() { + // some cases here: + // * stop by stop channel: error should be send as nil + // * count of steps reached: error should be send as nil + // * write error occurred + // * for Run(): caller needs to send stop channel and read the error + // * for Move(): caller waits for the error, but don't send stop channel + // + d.debug(fmt.Sprintf("RUN: write '%v' to err channel", err)) + runErrChan <- err + }() + for stepsLeft > 0 { + select { + case <-sigChan: + d.debug("RUN: OS signal received") + err = fmt.Errorf("OS signal received") + return + case <-runStopChan: + d.debug("RUN: stop channel received") + return + default: + if err == nil { + err = d.stepFunc() + if err != nil { + if d.skipStepErrors { + fmt.Printf("step skipped for '%s': %v\n", name, err) + err = nil + } else { + d.debug("RUN: write error occurred") + } + } + if !onceDone { + close(onceDoneChan) // to inform that we are ready for stop now + onceDone = true + d.debug("RUN: once done") + } + if !endlessMovement { + if err != nil { + return + } + stepsLeft-- + } + } + } + } + }(d.name) + return nil } // getDelayPerStep gives the delay per step -func (s *StepperDriver) getDelayPerStep() time.Duration { - // Do not remove *1000 and change duration to time.Millisecond. It has been done for a reason - return time.Duration(60000*1000/(s.stepsPerRev*s.speed)) * time.Microsecond +// formula: delay_per_step [min] = 1/(steps_per_revolution * speed [rpm]) +func (d *StepperDriver) getDelayPerStep() time.Duration { + // considering a max. speed of 1000 rpm and max. 1000 steps per revolution, a microsecond resolution is needed + // if the motor or application needs bigger values, switch to nanosecond is needed + return time.Duration(60*1000*1000/(d.stepsPerRev*float32(d.speedRpm))) * time.Microsecond } -// GetCurrentStep gives the current step of motor -func (s *StepperDriver) GetCurrentStep() int { - return s.stepNum -} +// phasedStepping moves the motor one step with the configured speed and direction. The speed can be adjusted by SetSpeed() +// and the direction can be changed by SetDirection() asynchronously. +func (d *StepperDriver) phasedStepping() error { + // ensure that read and write of variables (direction, stepNum) can not interfere + d.valueMutex.Lock() + defer d.valueMutex.Unlock() -// GetMaxSpeed gives the max RPM of motor -func (s *StepperDriver) GetMaxSpeed() uint { - // considering time for 1 rev as no of steps per rev * 1.5 (min time req between each step) - return uint(60000 / (float64(s.stepsPerRev) * 1.5)) -} + oldStepNum := d.stepNum -// SetSpeed sets the rpm -func (s *StepperDriver) SetSpeed(rpm uint) error { - if rpm <= 0 { - return errors.New("RPM cannot be a zero or negative value") + if d.direction == StepperDriverForward { + d.stepNum++ + } else { + d.stepNum-- + } + + if d.stepNum >= int(d.stepsPerRev) { + d.stepNum = 0 + } else if d.stepNum < 0 { + d.stepNum = int(d.stepsPerRev) - 1 } - m := s.GetMaxSpeed() - if rpm > m { - rpm = m + r := int(math.Abs(float64(d.stepNum))) % len(d.phase) + + for i, v := range d.phase[r] { + if err := d.connection.(DigitalWriter).DigitalWrite(d.pins[i], v); err != nil { + d.stepNum = oldStepNum + return err + } } - s.speed = rpm + delay := d.getDelayPerStep() + time.Sleep(delay) + return nil } + +func (d *StepperDriver) sleepOuputs() error { + for _, pin := range d.pins { + if err := d.connection.(DigitalWriter).DigitalWrite(pin, 0); err != nil { + return err + } + } + return nil +} + +// stopIfRunning stop the stepper if moving or running +func (d *StepperDriver) stopIfRunning() error { + // stops the continuous motion of the stepper, if running + if d.stopAsynchRunFunc == nil { + return nil + } + + err := d.stopAsynchRunFunc(true) + d.stopAsynchRunFunc = nil + + return err +} + +func (d *StepperDriver) debug(text string) { + if d.stepperDebug { + fmt.Println(text) + } +} diff --git a/drivers/gpio/stepper_driver_test.go b/drivers/gpio/stepper_driver_test.go index 4c3271b6b..237b05901 100644 --- a/drivers/gpio/stepper_driver_test.go +++ b/drivers/gpio/stepper_driver_test.go @@ -1,104 +1,429 @@ package gpio import ( + "fmt" + "log" "strings" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -const ( - stepsInRev = 32 -) - -func initStepperMotorDriver() *StepperDriver { - return NewStepperDriver(newGpioTestAdaptor(), [4]string{"7", "11", "13", "15"}, StepperModes.DualPhaseStepping, stepsInRev) -} +func initTestStepperDriverWithStubbedAdaptor() (*StepperDriver, *gpioTestAdaptor) { + const stepsPerRev = 32 -func TestStepperDriverRun(t *testing.T) { - d := initStepperMotorDriver() - _ = d.Run() - assert.True(t, d.IsMoving()) + a := newGpioTestAdaptor() + d := NewStepperDriver(a, [4]string{"7", "11", "13", "15"}, StepperModes.DualPhaseStepping, stepsPerRev) + return d, a } -func TestStepperDriverHalt(t *testing.T) { - d := initStepperMotorDriver() - _ = d.Run() - time.Sleep(200 * time.Millisecond) - _ = d.Halt() - assert.False(t, d.IsMoving()) -} - -func TestStepperDriverDefaultName(t *testing.T) { - d := initStepperMotorDriver() - assert.True(t, strings.HasPrefix(d.Name(), "Stepper")) -} +func TestNewStepperDriver(t *testing.T) { + // arrange + const stepsPerRev = 32 -func TestStepperDriverSetName(t *testing.T) { - name := "SomeStepperSriver" - d := initStepperMotorDriver() - d.SetName(name) - assert.Equal(t, name, d.Name()) + a := newGpioTestAdaptor() + // act + d := NewStepperDriver(a, [4]string{"7", "11", "13", "15"}, StepperModes.DualPhaseStepping, stepsPerRev) + // assert + assert.IsType(t, &StepperDriver{}, d) + assert.True(t, strings.HasPrefix(d.name, "Stepper")) + assert.Equal(t, a, d.connection) + assert.NoError(t, d.afterStart()) + assert.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + assert.Equal(t, "forward", d.direction) + assert.Equal(t, StepperModes.DualPhaseStepping, d.phase) + assert.Equal(t, float32(stepsPerRev), d.stepsPerRev) + assert.Equal(t, 0, d.stepNum) + assert.Nil(t, d.stopAsynchRunFunc) } -func TestStepperDriverSetDirection(t *testing.T) { - dir := "backward" - d := initStepperMotorDriver() - _ = d.SetDirection(dir) - assert.Equal(t, dir, d.direction) -} +func TestStepperMove_IsMoving(t *testing.T) { + const stepsPerRev = 32 -func TestStepperDriverDefaultDirection(t *testing.T) { - d := initStepperMotorDriver() - assert.Equal(t, "forward", d.direction) + tests := map[string]struct { + inputSteps int + noAutoStopIfRunning bool + simulateAlreadyRunning bool + simulateWriteErr bool + wantWrites int + wantSteps int + wantMoving bool + wantErr string + }{ + "move_forward": { + inputSteps: 2, + wantWrites: 8, + wantSteps: 2, + wantMoving: false, + }, + "move_more_forward": { + inputSteps: 10, + wantWrites: 40, + wantSteps: 10, + wantMoving: false, + }, + "move_forward_full_revolution": { + inputSteps: stepsPerRev, + wantWrites: 128, + wantSteps: 0, // will be reset after each revision + wantMoving: false, + }, + "move_backward": { + inputSteps: -2, + wantWrites: 8, + wantSteps: stepsPerRev - 2, + wantMoving: false, + }, + "move_more_backward": { + inputSteps: -10, + wantWrites: 40, + wantSteps: stepsPerRev - 10, + wantMoving: false, + }, + "move_backward_full_revolution": { + inputSteps: -stepsPerRev, + wantWrites: 128, + wantSteps: 0, // will be reset after each revision + wantMoving: false, + }, + "already_running_autostop": { + inputSteps: 3, + simulateAlreadyRunning: true, + wantWrites: 12, + wantSteps: 3, + wantMoving: false, + }, + "error_already_running": { + noAutoStopIfRunning: true, + simulateAlreadyRunning: true, + wantMoving: true, + wantErr: "already running or moving", + }, + "error_no_steps": { + inputSteps: 0, + wantWrites: 0, + wantSteps: 0, + wantMoving: false, + wantErr: "no steps to do", + }, + "error_write": { + inputSteps: 1, + simulateWriteErr: true, + wantWrites: 0, + wantMoving: false, + wantErr: "write error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, a := initTestStepperDriverWithStubbedAdaptor() + defer func() { + // for cleanup dangling channels + if d.stopAsynchRunFunc != nil { + err := d.stopAsynchRunFunc(true) + assert.NoError(t, err) + } + }() + // arrange: different behavior + d.haltIfRunning = !tc.noAutoStopIfRunning + if tc.simulateAlreadyRunning { + d.stopAsynchRunFunc = func(bool) error { log.Println("former run stopped"); return nil } + } + // arrange: writes + a.written = nil // reset writes of Start() + a.simulateWriteError = tc.simulateWriteErr + // act + err := d.Move(tc.inputSteps) + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.wantSteps, d.stepNum) + assert.Equal(t, tc.wantWrites, len(a.written)) + assert.Equal(t, tc.wantMoving, d.IsMoving()) + }) + } } -func TestStepperDriverInvalidDirection(t *testing.T) { - d := initStepperMotorDriver() - err := d.SetDirection("reverse") - assert.ErrorContains(t, err, "Invalid direction. Value should be forward or backward") +func TestStepperRun_IsMoving(t *testing.T) { + tests := map[string]struct { + noAutoStopIfRunning bool + simulateAlreadyRunning bool + simulateWriteErr bool + wantMoving bool + wantErr string + }{ + "run": { + wantMoving: true, + }, + "error_write": { + simulateWriteErr: true, + wantMoving: true, + }, + "error_already_running": { + noAutoStopIfRunning: true, + simulateAlreadyRunning: true, + wantMoving: true, + wantErr: "already running or moving", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, a := initTestStepperDriverWithStubbedAdaptor() + defer func() { + // for cleanup dangling channels + if d.stopAsynchRunFunc != nil { + err := d.stopAsynchRunFunc(true) + assert.NoError(t, err) + } + }() + // arrange: different behavior + writeChan := make(chan struct{}) + if tc.noAutoStopIfRunning { + // in this case no write should be called + close(writeChan) + writeChan = nil + d.haltIfRunning = false + } else { + d.haltIfRunning = true + } + if tc.simulateAlreadyRunning { + d.stopAsynchRunFunc = func(bool) error { return nil } + } + // arrange: writes + simWriteErr := tc.simulateWriteErr // to prevent data race in write function (go-called) + var firstWriteDone bool + a.digitalWriteFunc = func(string, byte) error { + if firstWriteDone { + return nil // to prevent to much output and write to channel + } + writeChan <- struct{}{} + firstWriteDone = true + if simWriteErr { + return fmt.Errorf("write error") + } + return nil + } + // act + err := d.Run() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.wantMoving, d.IsMoving()) + if writeChan != nil { + // wait until the first write was called and a little bit longer + <-writeChan + time.Sleep(10 * time.Millisecond) + var asynchErr error + if d.stopAsynchRunFunc != nil { + asynchErr = d.stopAsynchRunFunc(false) + d.stopAsynchRunFunc = nil + } + if tc.simulateWriteErr { + assert.Error(t, asynchErr) + } else { + assert.NoError(t, asynchErr) + } + } + }) + } } -func TestStepperDriverMoveForward(t *testing.T) { - d := initStepperMotorDriver() - _ = d.Move(1) - assert.Equal(t, 1, d.GetCurrentStep()) - - _ = d.Move(10) - assert.Equal(t, 11, d.GetCurrentStep()) +func TestStepperStop_IsMoving(t *testing.T) { + tests := map[string]struct { + running bool + wantErr string + }{ + "stop_running": { + running: true, + }, + "errro_not_started": { + running: false, + wantErr: "is not yet started", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, _ := initTestStepperDriverWithStubbedAdaptor() + if tc.running { + require.NoError(t, d.Run()) + require.True(t, d.IsMoving()) + } + // act + err := d.Stop() + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.False(t, d.IsMoving()) + }) + } } -func TestStepperDriverMoveBackward(t *testing.T) { - d := initStepperMotorDriver() - _ = d.Move(-1) - assert.Equal(t, stepsInRev-1, d.GetCurrentStep()) - - _ = d.Move(-10) - assert.Equal(t, stepsInRev-11, d.GetCurrentStep()) +func TestStepperHalt_IsMoving(t *testing.T) { + tests := map[string]struct { + running bool + }{ + "halt_running": { + running: true, + }, + "halt_not_started": { + running: false, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, _ := initTestStepperDriverWithStubbedAdaptor() + if tc.running { + require.NoError(t, d.Run()) + require.True(t, d.IsMoving()) + } + // act + err := d.Halt() + // assert + assert.NoError(t, err) + assert.False(t, d.IsMoving()) + }) + } } -func TestStepperDriverMoveFullRotation(t *testing.T) { - d := initStepperMotorDriver() - _ = d.Move(stepsInRev) - assert.Equal(t, 0, d.GetCurrentStep()) +func TestStepperSetDirection(t *testing.T) { + tests := map[string]struct { + input string + wantVal string + wantErr string + }{ + "direction_forward": { + input: "forward", + wantVal: "forward", + }, + "direction_backward": { + input: "backward", + wantVal: "backward", + }, + "error_invalid_direction": { + input: "reverse", + wantVal: "forward", + wantErr: "Invalid direction 'reverse'", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, _ := initTestStepperDriverWithStubbedAdaptor() + require.Equal(t, "forward", d.direction) + // act + err := d.SetDirection(tc.input) + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.wantVal, d.direction) + }) + } } -func TestStepperDriverMotorSetSpeedMoreThanMax(t *testing.T) { - d := initStepperMotorDriver() - m := d.GetMaxSpeed() +func TestStepperMaxSpeed(t *testing.T) { + const delayForMaxSpeed = 1428 * time.Microsecond // 1/700Hz - _ = d.SetSpeed(m + 1) - assert.Equal(t, d.speed, m) + tests := map[string]struct { + stepsPerRev float32 + want uint + }{ + "maxspeed_for_20spr": { + stepsPerRev: 20, + want: 2100, + }, + "maxspeed_for_50spr": { + stepsPerRev: 50, + want: 840, + }, + "maxspeed_for_100spr": { + stepsPerRev: 100, + want: 420, + }, + "maxspeed_for_400spr": { + stepsPerRev: 400, + want: 105, + }, + "maxspeed_for_1000spr": { + stepsPerRev: 1000, + want: 42, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := StepperDriver{stepsPerRev: tc.stepsPerRev} + // act + got := d.MaxSpeed() + d.speedRpm = got + got2 := d.getDelayPerStep() + // assert + assert.Equal(t, tc.want, got) + assert.Equal(t, delayForMaxSpeed, got2) + }) + } } -func TestStepperDriverMotorSetSpeedLessOrEqualMax(t *testing.T) { - d := initStepperMotorDriver() - m := d.GetMaxSpeed() - - _ = d.SetSpeed(m - 1) - assert.Equal(t, d.speed, m-1) +func TestStepperSetSpeed(t *testing.T) { + const maxRpm = 1166 - _ = d.SetSpeed(m) - assert.Equal(t, d.speed, m) + tests := map[string]struct { + input uint + want uint + wantErr string + }{ + "below_minimum": { + input: 0, + want: 0, + wantErr: "RPM (0) cannot be a zero or negative value", + }, + "minimum": { + input: 1, + want: 1, + }, + "maximum": { + input: maxRpm, + want: maxRpm, + }, + "above_maximum": { + input: maxRpm + 1, + want: maxRpm, + wantErr: "cannot be greater then maximal value 1166", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d, _ := initTestStepperDriverWithStubbedAdaptor() + d.stepsPerRev = 36 + // act + err := d.SetSpeed(tc.input) + // assert + if tc.wantErr != "" { + assert.ErrorContains(t, err, tc.wantErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tc.want, d.speedRpm) + }) + } } diff --git a/examples/raspi_stepper_move.go b/examples/raspi_stepper_move.go index 61784039c..2dd62cd60 100644 --- a/examples/raspi_stepper_move.go +++ b/examples/raspi_stepper_move.go @@ -7,7 +7,9 @@ package main import ( - "fmt" + "log" + "os" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" @@ -15,22 +17,59 @@ import ( ) func main() { + const ( + coilA1 = "7" + coilA2 = "13" + coilB1 = "11" + coilB2 = "15" + + degPerStep = 1.875 + countRot = 10 + ) + stepPerRevision := int(360.0 / degPerStep) + r := raspi.NewAdaptor() - stepper := gpio.NewStepperDriver(r, [4]string{"7", "11", "13", "15"}, gpio.StepperModes.DualPhaseStepping, 2048) + stepper := gpio.NewStepperDriver(r, [4]string{coilA1, coilB1, coilA2, coilB2}, gpio.StepperModes.DualPhaseStepping, + uint(stepPerRevision)) work := func() { - // set spped - stepper.SetSpeed(15) + defer func() { + ec := 0 + // set current to zero to prevent overheating + if err := stepper.Sleep(); err != nil { + ec = 1 + log.Println("work done", err) + } else { + log.Println("work done") + } + + os.Exit(ec) + }() + + gobot.After(5*time.Second, func() { + // this stops only the current movement and the next will start immediately (if any) + // this means for the example, that the first rotation stops after ~5 rotations + log.Println("asynchron stop after 5 sec.") + if err := stepper.Stop(); err != nil { + log.Println(err) + } + }) + + // one rotation per second + if err := stepper.SetSpeed(60); err != nil { + log.Println("set speed", err) + } - // Move forward one revolution - if err := stepper.Move(2048); err != nil { - fmt.Println(err) + // Move forward N revolution + if err := stepper.Move(stepPerRevision * countRot); err != nil { + log.Println("move forward", err) } - // Move backward one revolution - if err := stepper.Move(-2048); err != nil { - fmt.Println(err) + // Move backward N revolution + if err := stepper.MoveDeg(-360 * countRot); err != nil { + log.Println("move backward", err) } + return } robot := gobot.NewRobot("stepperBot", From 04fa5793712fc4feea8c29107611b9b65cebbb61 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sat, 11 Nov 2023 19:31:25 +0100 Subject: [PATCH 25/57] i2c(core): fix problems with usage of uintptr (#1033) --- drivers/i2c/i2c_connection_test.go | 8 +++-- system/i2c_device.go | 26 ++++++++++------ system/i2c_device_test.go | 50 ++++++++++++++++++------------ system/syscall.go | 26 ++++++++++++++-- system/syscall_mock.go | 17 +++++++--- system/system.go | 9 +++++- 6 files changed, 96 insertions(+), 40 deletions(-) diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index e4a610e95..92d075a57 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -14,18 +14,20 @@ import ( const dev = "/dev/i2c-1" -func getSyscallFuncImpl(errorMask byte) func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err system.SyscallErrno) { +func getSyscallFuncImpl( + errorMask byte, +) func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err system.SyscallErrno) { // bit 0: error on function query // bit 1: error on set address // bit 2: error on command - return func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err system.SyscallErrno) { + return func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err system.SyscallErrno) { // function query if (trap == system.Syscall_SYS_IOCTL) && (a2 == system.I2C_FUNCS) { if errorMask&0x01 == 0x01 { return 0, 0, 1 } - var funcPtr *uint64 = (*uint64)(unsafe.Pointer(a3)) + var funcPtr *uint64 = (*uint64)(a3) *funcPtr = system.I2C_FUNC_SMBUS_READ_BYTE | system.I2C_FUNC_SMBUS_READ_BYTE_DATA | system.I2C_FUNC_SMBUS_READ_WORD_DATA | system.I2C_FUNC_SMBUS_WRITE_BYTE | system.I2C_FUNC_SMBUS_WRITE_BYTE_DATA | diff --git a/system/i2c_device.go b/system/i2c_device.go index 2c2e4cba1..3b635e03d 100644 --- a/system/i2c_device.go +++ b/system/i2c_device.go @@ -160,7 +160,8 @@ func (d *i2cDevice) ReadBlockData(address int, reg uint8, data []byte) error { buf := make([]byte, dataLen+1) buf[0] = byte(dataLen) copy(buf[1:], data) - if err := d.smbusAccess(address, I2C_SMBUS_READ, reg, I2C_SMBUS_I2C_BLOCK_DATA, unsafe.Pointer(&buf[0])); err != nil { + if err := d.smbusAccess(address, I2C_SMBUS_READ, reg, I2C_SMBUS_I2C_BLOCK_DATA, + unsafe.Pointer(&buf[0])); err != nil { return err } // get data from buffer without first size element @@ -322,7 +323,7 @@ func (d *i2cDevice) read(address int, b []byte) (n int, err error) { func (d *i2cDevice) queryFunctionality(requested uint64, sender string) error { // lazy initialization if d.funcs == 0 { - if err := d.syscallIoctl(I2C_FUNCS, unsafe.Pointer(&d.funcs), "Querying functionality"); err != nil { + if err := d.syscallIoctl(I2C_FUNCS, unsafe.Pointer(&d.funcs), 0, "Querying functionality"); err != nil { return err } } @@ -334,7 +335,13 @@ func (d *i2cDevice) queryFunctionality(requested uint64, sender string) error { return nil } -func (d *i2cDevice) smbusAccess(address int, readWrite byte, command byte, protocol uint32, dataStart unsafe.Pointer) error { +func (d *i2cDevice) smbusAccess( + address int, + readWrite byte, + command byte, + protocol uint32, + dataStart unsafe.Pointer, +) error { if err := d.setAddress(address); err != nil { return err } @@ -346,8 +353,9 @@ func (d *i2cDevice) smbusAccess(address int, readWrite byte, command byte, proto data: dataStart, // the reflected value of unsafePointer equals uintptr(dataStart), } - sender := fmt.Sprintf("SMBus access r/w: %d, command: %d, protocol: %d, address: %d", readWrite, command, protocol, d.lastAddress) - if err := d.syscallIoctl(I2C_SMBUS, unsafe.Pointer(&smbus), sender); err != nil { + sender := fmt.Sprintf("SMBus access r/w: %d, command: %d, protocol: %d, address: %d", + readWrite, command, protocol, d.lastAddress) + if err := d.syscallIoctl(I2C_SMBUS, unsafe.Pointer(&smbus), 0, sender); err != nil { return err } @@ -362,19 +370,19 @@ func (d *i2cDevice) setAddress(address int) error { } return nil } - // for go vet false positives, see: https://github.com/golang/go/issues/41205 - if err := d.syscallIoctl(I2C_SLAVE, unsafe.Pointer(uintptr(byte(address))), "Setting address"); err != nil { + + if err := d.syscallIoctl(I2C_SLAVE, nil, address, "Setting address"); err != nil { return err } d.lastAddress = address return nil } -func (d *i2cDevice) syscallIoctl(signal uintptr, payload unsafe.Pointer, sender string) (err error) { +func (d *i2cDevice) syscallIoctl(signal uintptr, payload unsafe.Pointer, address int, sender string) (err error) { if err := d.openFileLazy(sender); err != nil { return err } - if _, _, errno := d.sys.syscall(Syscall_SYS_IOCTL, d.file, signal, payload); errno != 0 { + if _, _, errno := d.sys.syscall(Syscall_SYS_IOCTL, d.file, signal, payload, uint16(address)); errno != 0 { return fmt.Errorf("%s failed with syscall.Errno %v", sender, errno) } diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index 061bf395f..31dc1d333 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -11,18 +11,20 @@ import ( const dev = "/dev/i2c-1" -func getSyscallFuncImpl(errorMask byte) func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) { +func getSyscallFuncImpl( + errorMask byte, +) func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) { // bit 0: error on function query // bit 1: error on set address // bit 2: error on command - return func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) { + return func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) { // function query if (trap == Syscall_SYS_IOCTL) && (a2 == I2C_FUNCS) { if errorMask&0x01 == 0x01 { return 0, 0, 1 } - var funcPtr *uint64 = (*uint64)(unsafe.Pointer(a3)) + var funcPtr *uint64 = (*uint64)(a3) *funcPtr = I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA | @@ -115,7 +117,7 @@ func TestWriteRead(t *testing.T) { func TestReadByte(t *testing.T) { tests := map[string]struct { funcs uint64 - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string }{ "read_byte_ok": { @@ -124,7 +126,8 @@ func TestReadByte(t *testing.T) { "error_syscall": { funcs: I2C_FUNC_SMBUS_READ_BYTE, syscallImpl: getSyscallFuncImpl(0x04), - wantErr: "SMBus access r/w: 1, command: 0, protocol: 1, address: 2 failed with syscall.Errno operation not permitted", + wantErr: "SMBus access r/w: 1, command: 0, protocol: 1, address: 2 " + + "failed with syscall.Errno operation not permitted", }, "error_not_supported": { wantErr: "SMBus read byte not supported", @@ -159,7 +162,7 @@ func TestReadByte(t *testing.T) { func TestReadByteData(t *testing.T) { tests := map[string]struct { funcs uint64 - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string }{ "read_byte_data_ok": { @@ -168,7 +171,8 @@ func TestReadByteData(t *testing.T) { "error_syscall": { funcs: I2C_FUNC_SMBUS_READ_BYTE_DATA, syscallImpl: getSyscallFuncImpl(0x04), - wantErr: "SMBus access r/w: 1, command: 1, protocol: 2, address: 3 failed with syscall.Errno operation not permitted", + wantErr: "SMBus access r/w: 1, command: 1, protocol: 2, address: 3 " + + "failed with syscall.Errno operation not permitted", }, "error_not_supported": { wantErr: "SMBus read byte data not supported", @@ -206,7 +210,7 @@ func TestReadByteData(t *testing.T) { func TestReadWordData(t *testing.T) { tests := map[string]struct { funcs uint64 - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string }{ "read_word_data_ok": { @@ -215,7 +219,8 @@ func TestReadWordData(t *testing.T) { "error_syscall": { funcs: I2C_FUNC_SMBUS_READ_WORD_DATA, syscallImpl: getSyscallFuncImpl(0x04), - wantErr: "SMBus access r/w: 1, command: 2, protocol: 3, address: 4 failed with syscall.Errno operation not permitted", + wantErr: "SMBus access r/w: 1, command: 2, protocol: 3, address: 4 " + + "failed with syscall.Errno operation not permitted", }, "error_not_supported": { wantErr: "SMBus read word data not supported", @@ -270,7 +275,7 @@ func TestReadBlockData(t *testing.T) { ) tests := map[string]struct { funcs uint64 - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string }{ "read_block_data_ok": { @@ -279,7 +284,8 @@ func TestReadBlockData(t *testing.T) { "error_syscall": { funcs: I2C_FUNC_SMBUS_READ_I2C_BLOCK, syscallImpl: getSyscallFuncImpl(0x04), - wantErr: "SMBus access r/w: 1, command: 3, protocol: 8, address: 5 failed with syscall.Errno operation not permitted", + wantErr: "SMBus access r/w: 1, command: 3, protocol: 8, address: 5 " + + "failed with syscall.Errno operation not permitted", }, "error_from_used_fallback_if_not_supported": { wantErr: "Read 1 bytes from device by sysfs, expected 10", @@ -315,7 +321,7 @@ func TestReadBlockData(t *testing.T) { func TestWriteByte(t *testing.T) { tests := map[string]struct { funcs uint64 - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string }{ "write_byte_ok": { @@ -324,7 +330,8 @@ func TestWriteByte(t *testing.T) { "error_syscall": { funcs: I2C_FUNC_SMBUS_WRITE_BYTE, syscallImpl: getSyscallFuncImpl(0x04), - wantErr: "SMBus access r/w: 0, command: 68, protocol: 1, address: 6 failed with syscall.Errno operation not permitted", + wantErr: "SMBus access r/w: 0, command: 68, protocol: 1, address: 6 " + + "failed with syscall.Errno operation not permitted", }, "error_not_supported": { wantErr: "SMBus write byte not supported", @@ -357,7 +364,7 @@ func TestWriteByte(t *testing.T) { func TestWriteByteData(t *testing.T) { tests := map[string]struct { funcs uint64 - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string }{ "write_byte_data_ok": { @@ -366,7 +373,8 @@ func TestWriteByteData(t *testing.T) { "error_syscall": { funcs: I2C_FUNC_SMBUS_WRITE_BYTE_DATA, syscallImpl: getSyscallFuncImpl(0x04), - wantErr: "SMBus access r/w: 0, command: 4, protocol: 2, address: 7 failed with syscall.Errno operation not permitted", + wantErr: "SMBus access r/w: 0, command: 4, protocol: 2, address: 7 " + + "failed with syscall.Errno operation not permitted", }, "error_not_supported": { wantErr: "SMBus write byte data not supported", @@ -404,7 +412,7 @@ func TestWriteByteData(t *testing.T) { func TestWriteWordData(t *testing.T) { tests := map[string]struct { funcs uint64 - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string }{ "write_word_data_ok": { @@ -413,7 +421,8 @@ func TestWriteWordData(t *testing.T) { "error_syscall": { funcs: I2C_FUNC_SMBUS_WRITE_WORD_DATA, syscallImpl: getSyscallFuncImpl(0x04), - wantErr: "SMBus access r/w: 0, command: 5, protocol: 3, address: 8 failed with syscall.Errno operation not permitted", + wantErr: "SMBus access r/w: 0, command: 5, protocol: 3, address: 8 " + + "failed with syscall.Errno operation not permitted", }, "error_not_supported": { wantErr: "SMBus write word data not supported", @@ -469,7 +478,7 @@ func TestWriteBlockData(t *testing.T) { ) tests := map[string]struct { funcs uint64 - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string }{ "write_block_data_ok": { @@ -478,7 +487,8 @@ func TestWriteBlockData(t *testing.T) { "error_syscall": { funcs: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK, syscallImpl: getSyscallFuncImpl(0x04), - wantErr: "SMBus access r/w: 0, command: 6, protocol: 8, address: 9 failed with syscall.Errno operation not permitted", + wantErr: "SMBus access r/w: 0, command: 6, protocol: 8, address: 9 " + + "failed with syscall.Errno operation not permitted", }, } for name, tc := range tests { @@ -531,7 +541,7 @@ func Test_queryFunctionality(t *testing.T) { tests := map[string]struct { requested uint64 dev string - syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + syscallImpl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) wantErr string wantFile bool wantFuncs uint64 diff --git a/system/syscall.go b/system/syscall.go index 633bd9ba9..b90b1e976 100644 --- a/system/syscall.go +++ b/system/syscall.go @@ -21,8 +21,30 @@ const ( type nativeSyscall struct{} // Syscall calls the native unix.Syscall, implements the SystemCaller interface -func (sys *nativeSyscall) syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) { - r1, r2, errNo := unix.Syscall(trap, f.Fd(), signal, uintptr(payload)) +// Note: It would be possible to transfer the address as an unsafe.Pointer to e.g. a byte, uint16 or integer variable. +// The unpack process here would be as follows: +// * convert the payload back to the pointer: addrPtr := (*byte)(payload) +// * call with the content converted to uintptr: r1, r2, errNo = unix.Syscall(trap, f.Fd(), signal, uintptr(*addrPtr)) +// This has the main disadvantage, that if someone change the type of the address at caller side, the compiler will not +// detect this problem and this unpack procedure would cause unpredictable results. +// So the decision was taken to give the address here as a separate parameter, although it is not used in every call. +// Note also, that the size of the address variable at Kernel side is u16, therefore uint16 is used here. +func (sys *nativeSyscall) syscall( + trap uintptr, + f File, + signal uintptr, + payload unsafe.Pointer, + address uint16, +) (r1, r2 uintptr, err SyscallErrno) { + var errNo unix.Errno + if signal == I2C_SLAVE { + // this is the setup for the address, it just needs to be converted to an uintptr, + // the given payload is not used in this case, see the comment on the function + r1, r2, errNo = unix.Syscall(trap, f.Fd(), signal, uintptr(address)) + } else { + r1, r2, errNo = unix.Syscall(trap, f.Fd(), signal, uintptr(payload)) + } + return r1, r2, SyscallErrno(errNo) } diff --git a/system/syscall_mock.go b/system/syscall_mock.go index 45317c97d..1be3ffeba 100644 --- a/system/syscall_mock.go +++ b/system/syscall_mock.go @@ -13,18 +13,25 @@ type mockSyscall struct { smbus *i2cSmbusIoctlData sliceSize uint8 dataSlice []byte - Impl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) + Impl func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) } // Syscall calls the user defined implementation, used for tests, implements the SystemCaller interface -func (sys *mockSyscall) syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) { +func (sys *mockSyscall) syscall( + trap uintptr, + f File, + signal uintptr, + payload unsafe.Pointer, + address uint16, +) (r1, r2 uintptr, err SyscallErrno) { sys.lastTrap = trap // points to the used syscall (e.g. "SYS_IOCTL") sys.lastFile = f // a character device file (e.g. file to path "/dev/i2c-1") sys.lastSignal = signal // points to used function type (e.g. I2C_SMBUS, I2C_RDWR) if signal == I2C_SLAVE { - // in this case the uintptr corresponds the address - sys.devAddress = uintptr(payload) + // this is the setup for the address, it needs to be converted to an uintptr, + // the given payload is not used in this case, see the comment on the function used for production + sys.devAddress = uintptr(address) } if signal == I2C_SMBUS { @@ -54,7 +61,7 @@ func (sys *mockSyscall) syscall(trap uintptr, f File, signal uintptr, payload un // call mock implementation if sys.Impl != nil { - return sys.Impl(trap, f.Fd(), signal, uintptr(payload)) + return sys.Impl(trap, f.Fd(), signal, payload) } return 0, 0, 0 } diff --git a/system/system.go b/system/system.go index 708885265..30ae3f39e 100644 --- a/system/system.go +++ b/system/system.go @@ -31,8 +31,15 @@ type filesystem interface { // systemCaller represents unexposed Syscall interface to allow the switch between native and mocked implementation // Prevent unsafe call, since go 1.15, see "Pattern 4" in: https://go101.org/article/unsafe.html +// For go vet false positives, see: https://github.com/golang/go/issues/41205 type systemCaller interface { - syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) + syscall( + trap uintptr, + f File, + signal uintptr, + payload unsafe.Pointer, + address uint16, + ) (r1, r2 uintptr, err SyscallErrno) } // digitalPinAccesser represents unexposed interface to allow the switch between different implementations and From 88a0c7af2b2dcf5b109f4bb41168d989fb65b92d Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sat, 11 Nov 2023 19:55:47 +0100 Subject: [PATCH 26/57] ollie(test): fix data race in test (#1034) --- platforms/sphero/ollie/ollie_driver_test.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/platforms/sphero/ollie/ollie_driver_test.go b/platforms/sphero/ollie/ollie_driver_test.go index 3116d5849..4da63a2e4 100644 --- a/platforms/sphero/ollie/ollie_driver_test.go +++ b/platforms/sphero/ollie/ollie_driver_test.go @@ -50,7 +50,9 @@ func TestLocatorData(t *testing.T) { for _, point := range tables { // 0x0B is the locator ID - packet := []byte{0xFF, 0xFF, 0x00, 0x00, 0x0B, point.x1, point.x2, point.y1, point.y2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + packet := []byte{ + 0xFF, 0xFF, 0x00, 0x00, 0x0B, point.x1, point.x2, point.y1, point.y2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + } d.GetLocatorData(func(p Point2D) { assert.Equal(t, point.y, p.Y) @@ -64,12 +66,12 @@ func TestDataStreaming(t *testing.T) { _ = d.SetDataStreamingConfig(sphero.DefaultDataStreamingConfig()) - response := false + responseChan := make(chan bool) _ = d.On("sensordata", func(data interface{}) { cont := data.(DataStreamingPacket) fmt.Printf("got streaming packet: %+v \n", cont) assert.Equal(t, int16(10), cont.RawAccX) - response = true + responseChan <- true }) // example data packet @@ -95,8 +97,9 @@ func TestDataStreaming(t *testing.T) { // send empty packet to indicate start of next message d.HandleResponses([]byte{0xFF}, nil) - time.Sleep(10 * time.Millisecond) - if response == false { + select { + case <-responseChan: + case <-time.After(10 * time.Millisecond): t.Error("no response received") } } From 030de93a9d41d065a457dff9107f14a1fff730cd Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sat, 11 Nov 2023 20:18:44 +0100 Subject: [PATCH 27/57] doc(test): use -race for tests by default (#1035) --- .circleci/config.yml | 4 ++-- .github/pull_request_template.md | 2 +- CONTRIBUTING.md | 10 +++------- Makefile | 10 +++++----- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c3b40f46b..681dcbfa9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -23,7 +23,7 @@ jobs: - run: name: Core and drivers tests command: | - go test -v -coverprofile=coverage.txt -covermode=atomic . ./drivers/... + go test -race -v -coverprofile=coverage.txt -covermode=atomic . ./drivers/... - run: name: Code coverage command: | @@ -41,7 +41,7 @@ jobs: # digispark needs libusb, opencv needs opencv name: Platform tests (except digispark and opencv) command: | - go test -v $(go list ./platforms/... | grep -v platforms/digispark | grep -v platforms/opencv) + go test -race -v $(go list ./platforms/... | grep -v platforms/digispark | grep -v platforms/opencv) "check_examples": docker: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1b04c6552..8588899ad 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,7 +12,7 @@ - [ ] The PR's target branch is 'hybridgroup:dev' - [ ] I have added tests that prove my fix is effective or that my feature works -- [ ] New and existing unit tests pass locally with my changes (e.g. by run `make test`) +- [ ] New and existing unit tests pass locally with my changes (e.g. by run `make test_race`) - [ ] No linter errors exist locally (e.g. by run `make fmt_check`) - [ ] I have performed a self-review of my own code diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea1f095ed..a86a9ff4d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,7 +42,7 @@ Descriptions for each of these will eventually be provided below. * Take care to maintain the existing coding style. * `golangci-lint` your code, see [instruction for local installation](https://golangci-lint.run/usage/install/#local-installation) * `gofumpt` your code (the go version will be automatically obtained from go.mod), see [instructions](https://github.com/mvdan/gofumpt/blob/master/README.md) -* Add unit tests for any new or changed functionality. +* Add unit tests for any new or changed functionality and run tests with `-race` flag activated. * All pull requests should be "fast forward" * If there are commits after yours use “git rebase -i ” * If you have local changes you may need to use “git stash” @@ -69,14 +69,10 @@ The basics are as follows: All import paths should now work fine assuming that you've got the proper branch checked out. -3. Get all the needed gobot's dependencies each of them at their needed version. Gobot uses - [dep (Dependency management for Go)](https://golang.github.io/dep/) to manage the project's dependencies. To get all - the correct dependencies: +3. Get all dependencies: - * Install dep tool. Follow the dep [installation](https://golang.github.io/dep/docs/installation.html) instructions in - case you don't have it already installed. * `cd $GOPATH/src/gobot.io/x/gobot` - * `dep ensure` will fetch all the dependencies at their needed version. + * `go mod tidy` will fetch all the dependencies at their needed version. ## Landing Pull Requests diff --git a/Makefile b/Makefile index 85cfec583..e3c7883f0 100644 --- a/Makefile +++ b/Makefile @@ -10,13 +10,13 @@ EXAMPLES := $(EXAMPLES_NO_GOCV) # opencv platform currently skipped to prevent install of preconditions including_except := $(shell go list ./... | grep -v platforms/opencv) +# Run tests on nearly all directories without test cache, with race detection +test_race: + go test -failfast -count=1 -v -race $(including_except) + # Run tests on nearly all directories without test cache test: - go test -failfast -count=1 -v $(including_except) - -# Run tests with race detection -test_race: - go test -race $(including_except) + go test -failfast -count=1 $(including_except) # Test, generate and show coverage in browser test_cover: From aee81436c990f2bef30e5d232ff3fef4776ef1f9 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 12 Nov 2023 14:17:02 +0100 Subject: [PATCH 28/57] lint(all): switch to 1.55.2 and adjust linter issues (#1036) --- .github/workflows/golangci-lint.yml | 2 +- .golangci.yml | 11 ++- adaptor.go | 14 +-- api/api_test.go | 12 +-- commander.go | 2 +- commander_test.go | 2 +- drivers/aio/analog_actuator_driver_test.go | 23 ++--- drivers/aio/analog_sensor_driver_test.go | 21 ++-- drivers/aio/grove_drivers_test.go | 3 +- .../grove_temperature_sensor_driver_test.go | 9 +- drivers/aio/temperature_sensor_driver_test.go | 17 ++-- drivers/common/mfrc522/mfrc522_pcd_test.go | 17 ++-- drivers/gpio/aip1640_driver_test.go | 19 ++-- drivers/gpio/button_driver_test.go | 8 +- drivers/gpio/buzzer_driver_test.go | 13 +-- drivers/gpio/direct_pin_driver_test.go | 45 ++++----- drivers/gpio/easy_driver_test.go | 52 +++++----- drivers/gpio/gpio_driver.go | 8 +- drivers/gpio/gpio_driver_test.go | 13 +-- drivers/gpio/grove_drivers_test.go | 3 +- drivers/gpio/hcsr04_driver_test.go | 16 +-- drivers/gpio/hd44780_driver_test.go | 59 +++++------ drivers/gpio/led_driver_test.go | 15 +-- drivers/gpio/max7219_driver_test.go | 5 +- drivers/gpio/motor_driver_test.go | 5 +- drivers/gpio/pir_motion_driver_test.go | 7 +- drivers/gpio/relay_driver_test.go | 5 +- drivers/gpio/rgb_led_driver_test.go | 17 ++-- drivers/gpio/servo_driver_test.go | 13 +-- drivers/gpio/stepper_driver_test.go | 38 ++++---- drivers/gpio/tm1638_driver_test.go | 11 ++- drivers/i2c/adafruit1109_driver_test.go | 27 +++--- drivers/i2c/adafruit2327_driver_test.go | 13 +-- drivers/i2c/adafruit2348_driver_test.go | 31 +++--- drivers/i2c/ads1x15_driver_1015_test.go | 41 ++++---- drivers/i2c/ads1x15_driver_1115_test.go | 41 ++++---- drivers/i2c/ads1x15_driver_test.go | 3 +- drivers/i2c/adxl345_driver_test.go | 39 ++++---- drivers/i2c/bh1750_driver_test.go | 9 +- drivers/i2c/blinkm_driver_test.go | 13 +-- drivers/i2c/bme280_driver_test.go | 23 ++--- drivers/i2c/bmp180_driver_test.go | 19 ++-- drivers/i2c/bmp280_driver_test.go | 37 +++---- drivers/i2c/bmp388_driver_test.go | 57 +++++------ drivers/i2c/ccs811_driver_test.go | 7 +- drivers/i2c/drv2605l_driver_test.go | 21 ++-- drivers/i2c/grovepi_driver_test.go | 22 +++-- drivers/i2c/hmc5883l_driver_test.go | 21 ++-- drivers/i2c/hmc6352_driver_test.go | 9 +- drivers/i2c/i2c_connection_test.go | 41 ++++---- drivers/i2c/i2c_driver_test.go | 17 ++-- drivers/i2c/ina3221_driver_test.go | 29 +++--- drivers/i2c/jhd1313m1_driver_test.go | 41 ++++---- drivers/i2c/l3gd20h_driver_test.go | 21 ++-- drivers/i2c/lidarlite_driver_test.go | 15 +-- drivers/i2c/mcp23017_driver_test.go | 85 ++++++++-------- drivers/i2c/mma7660_driver_test.go | 25 ++--- drivers/i2c/mpl115a2_driver_test.go | 25 ++--- drivers/i2c/mpu6050_driver_test.go | 15 +-- drivers/i2c/pca9501_driver_test.go | 17 ++-- drivers/i2c/pca953x_driver_test.go | 27 +++--- drivers/i2c/pca9685_driver_test.go | 37 +++---- drivers/i2c/pcf8583_driver_test.go | 57 +++++------ drivers/i2c/pcf8591_driver_test.go | 21 ++-- drivers/i2c/sht2x_driver_test.go | 29 +++--- drivers/i2c/sht3x_driver_test.go | 23 ++--- drivers/i2c/ssd1306_driver_test.go | 29 +++--- drivers/i2c/th02_driver_test.go | 25 ++--- drivers/i2c/tsl2561_driver_test.go | 21 ++-- drivers/i2c/wiichuck_driver_test.go | 91 ++++++++--------- drivers/i2c/yl40_driver_test.go | 49 +++++----- drivers/spi/apa102_test.go | 3 +- drivers/spi/mcp3002_test.go | 3 +- drivers/spi/mcp3004_test.go | 3 +- drivers/spi/mcp3008_test.go | 3 +- drivers/spi/mcp3202_test.go | 3 +- drivers/spi/mcp3204_test.go | 3 +- drivers/spi/mcp3208_test.go | 3 +- drivers/spi/mcp3304_test.go | 3 +- drivers/spi/mfrc522_driver_test.go | 3 +- drivers/spi/spi_connection_test.go | 15 +-- drivers/spi/spi_driver.go | 10 +- drivers/spi/spi_driver_test.go | 5 +- drivers/spi/ssd1306_driver_test.go | 12 +-- master_test.go | 17 ++-- platforms/adaptors/digitalpinsadaptor.go | 2 +- platforms/adaptors/digitalpinsadaptor_test.go | 63 ++++++------ platforms/adaptors/i2cbusadaptor_test.go | 51 +++++----- platforms/adaptors/pwmpinsadaptor.go | 6 +- platforms/adaptors/pwmpinsadaptor_test.go | 73 +++++++------- platforms/adaptors/spibusadaptor_test.go | 37 +++---- platforms/audio/audio_adaptor_test.go | 9 +- platforms/audio/audio_driver_test.go | 7 +- .../beaglebone/beaglebone_adaptor_test.go | 33 ++++--- platforms/ble/battery_driver_test.go | 5 +- platforms/ble/ble_client_adaptor.go | 15 ++- .../ble/device_information_driver_test.go | 5 +- platforms/ble/generic_access_driver_test.go | 5 +- platforms/chip/chip_adaptor_test.go | 31 +++--- platforms/dexter/gopigo3/driver_test.go | 6 +- platforms/digispark/digispark_adaptor_test.go | 21 ++-- platforms/digispark/digispark_i2c_test.go | 29 +++--- platforms/digispark/littleWire.go | 10 +- .../dragonboard/dragonboard_adaptor_test.go | 15 +-- platforms/firmata/client/client_test.go | 33 ++++--- platforms/firmata/firmata_adaptor.go | 20 ++-- platforms/firmata/firmata_adaptor_test.go | 43 ++++---- platforms/firmata/firmata_i2c_test.go | 45 ++++----- platforms/intel-iot/curie/imu_driver_test.go | 63 ++++++------ .../intel-iot/edison/edison_adaptor_test.go | 55 +++++------ .../intel-iot/joule/joule_adaptor_test.go | 23 ++--- platforms/jetson/jetson_adaptor_test.go | 37 +++---- platforms/jetson/pwm_pin.go | 5 +- platforms/jetson/pwm_pin_test.go | 20 ++-- platforms/joystick/bin/scanner.go | 2 - platforms/joystick/joystick_adaptor_test.go | 7 +- platforms/joystick/joystick_driver_test.go | 7 +- platforms/keyboard/keyboard_driver_test.go | 5 +- platforms/leap/leap_motion_adaptor_test.go | 7 +- platforms/leap/leap_motion_driver_test.go | 25 ++--- platforms/mavlink/common/mavlink.go | 2 +- platforms/mavlink/mavlink_adaptor_test.go | 9 +- platforms/mavlink/mavlink_driver_test.go | 7 +- platforms/mavlink/mavlink_udp_adaptor.go | 4 +- platforms/mavlink/mavlink_udp_adaptor_test.go | 9 +- .../microbit/accelerometer_driver_test.go | 11 ++- platforms/microbit/button_driver_test.go | 5 +- platforms/microbit/io_pin_driver_test.go | 25 ++--- platforms/microbit/led_driver_test.go | 27 +++--- .../microbit/magnetometer_driver_test.go | 11 ++- platforms/microbit/temperature_driver_test.go | 5 +- platforms/mqtt/mqtt_adaptor_test.go | 7 +- platforms/mqtt/mqtt_driver_test.go | 5 +- platforms/nanopi/nanopi_adaptor_test.go | 50 +++++----- platforms/nats/nats_adaptor_test.go | 11 ++- platforms/nats/nats_driver_test.go | 5 +- platforms/neurosky/neurosky_adaptor_test.go | 9 +- platforms/neurosky/neurosky_driver_test.go | 5 +- platforms/opencv/camera_driver_test.go | 7 +- platforms/opencv/window_driver_test.go | 5 +- .../parrot/ardrone/ardrone_adaptor_test.go | 7 +- .../parrot/ardrone/ardrone_driver_test.go | 5 +- platforms/parrot/ardrone/pitch_test.go | 6 +- platforms/parrot/bebop/bebop_adaptor_test.go | 7 +- .../parrot/minidrone/minidrone_driver_test.go | 97 ++++++++++--------- platforms/particle/adaptor.go | 2 +- platforms/particle/adaptor_test.go | 15 +-- platforms/pebble/pebble_adaptor_test.go | 5 +- platforms/pebble/pebble_driver_test.go | 5 +- platforms/raspi/pwm_pin_test.go | 21 ++-- platforms/raspi/raspi_adaptor_test.go | 59 +++++------ platforms/sphero/bb8/bb8_driver_test.go | 5 +- platforms/sphero/ollie/ollie_driver_test.go | 5 +- platforms/sphero/sphero_adaptor_test.go | 9 +- platforms/sphero/sphero_driver_test.go | 5 +- .../sphero/sprkplus/sprkplus_driver_test.go | 5 +- platforms/tinkerboard/adaptor_test.go | 50 +++++----- platforms/upboard/up2/adaptor_test.go | 23 ++--- robot_test.go | 17 ++-- system/digitalpin_gpiod_test.go | 5 +- system/digitalpin_poll_test.go | 7 +- system/digitalpin_sysfs_test.go | 26 ++--- system/fs_mock_test.go | 27 +++--- system/fs_test.go | 5 +- system/i2c_device_test.go | 59 +++++------ system/pwmpin_sysfs.go | 4 +- system/pwmpin_sysfs_test.go | 29 +++--- system/system_test.go | 3 +- utils_test.go | 12 +-- 169 files changed, 1727 insertions(+), 1581 deletions(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 8b9028ee6..dd454656b 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -24,7 +24,7 @@ jobs: uses: golangci/golangci-lint-action@v3 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.54.2 + version: v1.55.2 # Optional: working directory, useful for monorepos # working-directory: v2 diff --git a/.golangci.yml b/.golangci.yml index 9b907888c..465ecde60 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,8 @@ # note: GolangCI-Lint also searches for config files in all directories from the directory of the first analyzed path up to the root. run: + build-tags: + - utils + # Timeout for analysis, e.g. 30s, 5m. # gobot is very expensive, on a machine with heavy load it takes some minutes # for first run or after empty the cache by 'golangci-lint cache clean' @@ -31,10 +34,10 @@ run: linters: # currently active linters: # - #INFO [lintersdb] Active 42 linters: [asasalint asciicheck bidichk contextcheck decorder depguard dupword durationcheck errcheck exportloopref - # gocheckcompilerdirectives gofmt gofumpt goimports gomoddirectives gomodguard goprintffuncname gosec gosimple govet grouper ineffassign makezero mirror - # misspell musttag nilerr nilnil nolintlint nosprintfhostport prealloc reassign revive staticcheck tagalign tenv testableexamples tparallel unconvert unparam - # unused wastedassign] + #INFO [lintersdb] Active 49 linters: [asasalint asciicheck bidichk contextcheck decorder depguard dupword durationcheck errcheck exportloopref + # gocheckcompilerdirectives gochecknoinits gochecksumtype gofmt gofumpt goimports gomoddirectives gomodguard goprintffuncname gosec gosimple govet grouper + # inamedparam ineffassign makezero mirror misspell musttag nilerr nilnil nolintlint nosprintfhostport perfsprint prealloc protogetter reassign revive + # sloglint staticcheck tagalign tenv testableexamples testifylint tparallel unconvert unparam unused wastedassign] enable-all: true diff --git a/adaptor.go b/adaptor.go index 81c6919a4..ef4730bda 100644 --- a/adaptor.go +++ b/adaptor.go @@ -8,7 +8,7 @@ import ( // DigitalPinOptioner is the interface to provide the possibility to change pin behavior for the next usage type DigitalPinOptioner interface { // SetLabel change the pins label - SetLabel(string) (changed bool) + SetLabel(label string) (changed bool) // SetDirectionOutput sets the pins direction to output with the given initial value SetDirectionOutput(initialState int) (changed bool) // SetDirectionInput sets the pins direction to input @@ -38,7 +38,7 @@ type DigitalPinOptioner interface { // DigitalPinOptionApplier is the interface to apply options to change pin behavior immediately type DigitalPinOptionApplier interface { // ApplyOptions apply all given options to the pin immediately - ApplyOptions(...func(DigitalPinOptioner) bool) error + ApplyOptions(options ...func(DigitalPinOptioner) bool) error } // DigitalPinner is the interface for system gpio interactions @@ -50,7 +50,7 @@ type DigitalPinner interface { // Read reads the current value of the pin Read() (int, error) // Write writes to the pin - Write(int) error + Write(val int) error // DigitalPinOptionApplier is the interface to change pin behavior immediately DigitalPinOptionApplier } @@ -78,7 +78,7 @@ type PWMPinner interface { // Enabled returns the enabled state of the PWM pin Enabled() (bool, error) // SetEnabled enables/disables the PWM pin - SetEnabled(bool) error + SetEnabled(val bool) error // Polarity returns true if the polarity of the PWM pin is normal, otherwise false Polarity() (bool, error) // SetPolarity sets the polarity of the PWM pin to normal if called with true and to inverted if called with false @@ -86,11 +86,11 @@ type PWMPinner interface { // Period returns the current PWM period in nanoseconds for pin Period() (uint32, error) // SetPeriod sets the current PWM period in nanoseconds for pin - SetPeriod(uint32) error + SetPeriod(period uint32) error // DutyCycle returns the duty cycle in nanoseconds for the PWM pin DutyCycle() (uint32, error) // SetDutyCycle writes the duty cycle in nanoseconds to the PWM pin - SetDutyCycle(uint32) error + SetDutyCycle(dutyCyle uint32) error } // PWMPinnerProvider is the interface that an Adaptor should implement to allow @@ -210,7 +210,7 @@ type Adaptor interface { // Name returns the label for the Adaptor Name() string // SetName sets the label for the Adaptor - SetName(string) + SetName(name string) // Connect initiates the Adaptor Connect() error // Finalize terminates the Adaptor diff --git a/api/api_test.go b/api/api_test.go index 477bb298c..267b11cc4 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -80,8 +80,8 @@ func TestIndex(t *testing.T) { a.ServeHTTP(response, request) - assert.Equal(t, response.Code, http.StatusMovedPermanently) - assert.Equal(t, response.Header()["Location"][0], "/index.html") + assert.Equal(t, http.StatusMovedPermanently, response.Code) + assert.Equal(t, "/index.html", response.Header()["Location"][0]) } func TestMcp(t *testing.T) { @@ -144,7 +144,7 @@ func TestRobots(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - assert.Equal(t, 3, len(body["robots"].([]interface{}))) + assert.Len(t, body["robots"].([]interface{}), 3) } func TestRobot(t *testing.T) { @@ -177,7 +177,7 @@ func TestRobotDevices(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - assert.Equal(t, 3, len(body["devices"].([]interface{}))) + assert.Len(t, body["devices"].([]interface{}), 3) // unknown robot request, _ = http.NewRequest("GET", "/api/robots/UnknownRobot1/devices", nil) @@ -283,7 +283,7 @@ func TestRobotDeviceCommands(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - assert.Equal(t, 2, len(body["commands"].([]interface{}))) + assert.Len(t, body["commands"].([]interface{}), 2) // unknown device request, _ = http.NewRequest("GET", @@ -345,7 +345,7 @@ func TestRobotConnections(t *testing.T) { var body map[string]interface{} _ = json.NewDecoder(response.Body).Decode(&body) - assert.Equal(t, 3, len(body["connections"].([]interface{}))) + assert.Len(t, body["connections"].([]interface{}), 3) // unknown robot request, _ = http.NewRequest("GET", "/api/robots/UnknownRobot1/connections", nil) diff --git a/commander.go b/commander.go index 4b1f4a57b..b2c5608d4 100644 --- a/commander.go +++ b/commander.go @@ -8,7 +8,7 @@ type commander struct { // which exposes API commands. type Commander interface { // Command returns a command given a name. Returns nil if the command is not found. - Command(string) (command func(map[string]interface{}) interface{}) + Command(name string) (command func(map[string]interface{}) interface{}) // Commands returns a map of commands. Commands() (commands map[string]func(map[string]interface{}) interface{}) // AddCommand adds a command given a name. diff --git a/commander_test.go b/commander_test.go index e73021984..85dda9159 100644 --- a/commander_test.go +++ b/commander_test.go @@ -14,7 +14,7 @@ func TestCommander(t *testing.T) { }) // act && assert - assert.Equal(t, 1, len(c.Commands())) + assert.Len(t, c.Commands(), 1) assert.NotNil(t, c.Command("test")) assert.Nil(t, c.Command("booyeah")) } diff --git a/drivers/aio/analog_actuator_driver_test.go b/drivers/aio/analog_actuator_driver_test.go index 9124777b0..88e3d22ce 100644 --- a/drivers/aio/analog_actuator_driver_test.go +++ b/drivers/aio/analog_actuator_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestAnalogActuatorDriver(t *testing.T) { @@ -15,16 +16,16 @@ func TestAnalogActuatorDriver(t *testing.T) { assert.Equal(t, "47", d.Pin()) err := d.RawWrite(100) - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, 100, a.written[0]) err = d.Write(247.0) - assert.NoError(t, err) - assert.Equal(t, 2, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 2) assert.Equal(t, 247, a.written[1]) assert.Equal(t, 247, d.RawValue()) - assert.Equal(t, 247.0, d.Value()) + assert.InDelta(t, 247.0, d.Value(), 0.0) } func TestAnalogActuatorDriverWithScaler(t *testing.T) { @@ -35,12 +36,12 @@ func TestAnalogActuatorDriverWithScaler(t *testing.T) { err := d.Command("RawWrite")(map[string]interface{}{"val": "100"}) assert.Nil(t, err) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, 100, a.written[0]) err = d.Command("Write")(map[string]interface{}{"val": "247.0"}) assert.Nil(t, err) - assert.Equal(t, 2, len(a.written)) + assert.Len(t, a.written, 2) assert.Equal(t, 100, a.written[1]) } @@ -76,8 +77,8 @@ func TestAnalogActuatorDriverLinearScaler(t *testing.T) { // act err := d.Write(tt.input) // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, tt.want, a.written[0]) }) } @@ -85,12 +86,12 @@ func TestAnalogActuatorDriverLinearScaler(t *testing.T) { func TestAnalogActuatorDriverStart(t *testing.T) { d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestAnalogActuatorDriverHalt(t *testing.T) { d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestAnalogActuatorDriverDefaultName(t *testing.T) { diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index 3b60eb209..3e4bff255 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -37,7 +38,7 @@ func TestAnalogSensorDriver(t *testing.T) { assert.Nil(t, ret["err"]) ret = d.Command("Read")(nil).(map[string]interface{}) - assert.Equal(t, 247.0, ret["val"].(float64)) + assert.InDelta(t, 247.0, ret["val"].(float64), 0.0) assert.Nil(t, ret["err"]) // refresh value on read @@ -47,11 +48,11 @@ func TestAnalogSensorDriver(t *testing.T) { val = 150 return } - assert.Equal(t, 0.0, d.Value()) + assert.InDelta(t, 0.0, d.Value(), 0.0) val, err := d.Read() - assert.NoError(t, err) - assert.Equal(t, 150.0, val) - assert.Equal(t, 150.0, d.Value()) + require.NoError(t, err) + assert.InDelta(t, 150.0, val, 0.0) + assert.InDelta(t, 150.0, d.Value(), 0.0) assert.Equal(t, 150, d.RawValue()) } @@ -85,8 +86,8 @@ func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { // act got, err := d.Read() // assert - assert.NoError(t, err) - assert.Equal(t, tt.want, got) + require.NoError(t, err) + assert.InDelta(t, tt.want, got, 0.0) }) } } @@ -104,7 +105,7 @@ func TestAnalogSensorDriverStart(t *testing.T) { }) _ = d.Once(d.Event(Value), func(data interface{}) { - assert.Equal(t, 10000.0, data.(float64)) + assert.InDelta(t, 10000.0, data.(float64), 0.0) sem <- true }) @@ -114,7 +115,7 @@ func TestAnalogSensorDriverStart(t *testing.T) { return } - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) select { case <-sem: @@ -170,7 +171,7 @@ func TestAnalogSensorDriverHalt(t *testing.T) { <-d.halt close(done) }() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) select { case <-done: case <-time.After(100 * time.Millisecond): diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go index e9ea6d408..df88e2cb7 100644 --- a/drivers/aio/grove_drivers_test.go +++ b/drivers/aio/grove_drivers_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -89,7 +90,7 @@ func TestDriverPublishesError(t *testing.T) { return } - assert.NoError(t, driver.Start()) + require.NoError(t, driver.Start()) // expect error _ = driver.Once(driver.Event(Error), func(data interface{}) { diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index 602ad26c9..a7b303e58 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -47,8 +48,8 @@ func TestGroveTemperatureSensorDriverScaling(t *testing.T) { // act got, err := d.Read() // assert - assert.NoError(t, err) - assert.Equal(t, tt.want, got) + require.NoError(t, err) + assert.InDelta(t, tt.want, got, 0.0) }) } } @@ -66,7 +67,7 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) select { case <-sem: @@ -74,7 +75,7 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { t.Errorf("Grove Temperature Sensor Event \"Data\" was not published") } - assert.Equal(t, 31.61532462352477, d.Temperature()) + assert.InDelta(t, 31.61532462352477, d.Temperature(), 0.0) } func TestGroveTempDriverDefaultName(t *testing.T) { diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index 7519ec46d..21c16711b 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestTemperatureSensorDriver(t *testing.T) { @@ -48,8 +49,8 @@ func TestTemperatureSensorDriverNtcScaling(t *testing.T) { // act got, err := d.Read() // assert - assert.NoError(t, err) - assert.Equal(t, tt.want, got) + require.NoError(t, err) + assert.InDelta(t, tt.want, got, 0.0) }) } } @@ -83,8 +84,8 @@ func TestTemperatureSensorDriverLinearScaling(t *testing.T) { // act got, err := d.Read() // assert - assert.NoError(t, err) - assert.Equal(t, tt.want, got) + require.NoError(t, err) + assert.InDelta(t, tt.want, got, 0.0) }) } } @@ -104,7 +105,7 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.T) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) select { case <-sem: @@ -112,7 +113,7 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.T) { t.Errorf(" Temperature Sensor Event \"Data\" was not published") } - assert.Equal(t, 31.61532462352477, d.Value()) + assert.InDelta(t, 31.61532462352477, d.Value(), 0.0) } func TestTempSensorPublishesError(t *testing.T) { @@ -126,7 +127,7 @@ func TestTempSensorPublishesError(t *testing.T) { return } - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) // expect error _ = d.Once(d.Event(Error), func(data interface{}) { @@ -148,7 +149,7 @@ func TestTempSensorHalt(t *testing.T) { <-d.halt close(done) }() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) select { case <-done: case <-time.After(100 * time.Millisecond): diff --git a/drivers/common/mfrc522/mfrc522_pcd_test.go b/drivers/common/mfrc522/mfrc522_pcd_test.go index 891d60ea6..435a2ee81 100644 --- a/drivers/common/mfrc522/mfrc522_pcd_test.go +++ b/drivers/common/mfrc522/mfrc522_pcd_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type busConnMock struct { @@ -63,7 +64,7 @@ func TestInitialize(t *testing.T) { // act err := d.Initialize(c) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, c, d.connection) assert.Equal(t, wantSoftReset, c.written[:3]) assert.Equal(t, wantInit, c.written[3:21]) @@ -80,7 +81,7 @@ func Test_getVersion(t *testing.T) { // act got, err := d.getVersion() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, wantWritten, c.written) } @@ -120,7 +121,7 @@ func Test_switchAntenna(t *testing.T) { // act err := d.switchAntenna(tc.target) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.wantWritten, c.written) }) } @@ -134,7 +135,7 @@ func Test_stopCrypto1(t *testing.T) { // act err := d.stopCrypto1() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, wantWritten, c.written) } @@ -158,7 +159,7 @@ func Test_communicateWithPICC(t *testing.T) { // transceive, all 8 bits, no CRC err := d.communicateWithPICC(0x0C, dataToFifo, backData, 0x00, false) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, writtenPrepare, c.written[:8]) assert.Equal(t, writtenWriteFifo, c.written[8:12]) assert.Equal(t, writtenTransceive, c.written[12:16]) @@ -181,7 +182,7 @@ func Test_calculateCRC(t *testing.T) { // act err := d.calculateCRC(dataToFifo, gotCrcBack) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, writtenPrepare, c.written[:6]) assert.Equal(t, writtenFifo, c.written[6:10]) assert.Equal(t, writtenCalc, c.written[10:15]) @@ -197,7 +198,7 @@ func Test_writeFifo(t *testing.T) { // act err := d.writeFifo(dataToFifo) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, wantWritten, c.written) } @@ -210,7 +211,7 @@ func Test_readFifo(t *testing.T) { // act _, err := d.readFifo(backData) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, wantWritten, c.written) assert.Equal(t, c.simFifo, backData) } diff --git a/drivers/gpio/aip1640_driver_test.go b/drivers/gpio/aip1640_driver_test.go index d7d8e256b..b4870e18c 100644 --- a/drivers/gpio/aip1640_driver_test.go +++ b/drivers/gpio/aip1640_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -32,12 +33,12 @@ func TestAIP1640Driver(t *testing.T) { func TestAIP1640DriverStart(t *testing.T) { d := initTestAIP1640Driver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestAIP1640DriverHalt(t *testing.T) { d := initTestAIP1640Driver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestAIP1640DriverDefaultName(t *testing.T) { @@ -55,39 +56,39 @@ func TestAIP1640DriveDrawPixel(t *testing.T) { d := initTestAIP1640Driver() d.DrawPixel(2, 3, true) d.DrawPixel(0, 3, true) - assert.Equal(t, d.buffer[7-3], uint8(5)) + assert.Equal(t, uint8(5), d.buffer[7-3]) } func TestAIP1640DriverDrawRow(t *testing.T) { d := initTestAIP1640Driver() d.DrawRow(4, 0x3C) - assert.Equal(t, d.buffer[7-4], uint8(0x3C)) + assert.Equal(t, uint8(0x3C), d.buffer[7-4]) } func TestAIP1640DriverDrawMatrix(t *testing.T) { d := initTestAIP1640Driver() drawing := [8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} d.DrawMatrix(drawing) - assert.Equal(t, d.buffer, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}) + assert.Equal(t, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}, d.buffer) } func TestAIP1640DriverClear(t *testing.T) { d := initTestAIP1640Driver() drawing := [8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} d.DrawMatrix(drawing) - assert.Equal(t, d.buffer, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}) + assert.Equal(t, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}, d.buffer) d.Clear() - assert.Equal(t, d.buffer, [8]byte{}) + assert.Equal(t, [8]byte{}, d.buffer) } func TestAIP1640DriverSetIntensity(t *testing.T) { d := initTestAIP1640Driver() d.SetIntensity(3) - assert.Equal(t, d.intensity, uint8(3)) + assert.Equal(t, uint8(3), d.intensity) } func TestAIP1640DriverSetIntensityHigherThan7(t *testing.T) { d := initTestAIP1640Driver() d.SetIntensity(19) - assert.Equal(t, d.intensity, uint8(7)) + assert.Equal(t, uint8(7), d.intensity) } diff --git a/drivers/gpio/button_driver_test.go b/drivers/gpio/button_driver_test.go index c9112e42a..a71dcd371 100644 --- a/drivers/gpio/button_driver_test.go +++ b/drivers/gpio/button_driver_test.go @@ -37,7 +37,7 @@ func TestNewButtonDriver(t *testing.T) { assert.NotNil(t, d.mutex) assert.NotNil(t, d.Eventer) assert.Equal(t, "1", d.pin) - assert.Equal(t, false, d.active) + assert.False(t, d.active) assert.Equal(t, 0, d.defaultState) assert.Equal(t, 10*time.Millisecond, d.interval) assert.NotNil(t, d.halt) @@ -76,7 +76,7 @@ func TestButtonStart(t *testing.T) { err := d.Start() // assert & rearrange - assert.NoError(t, err) + require.NoError(t, err) select { case <-sem: @@ -146,7 +146,7 @@ func TestButtonSetDefaultState(t *testing.T) { // assert & rearrange require.Equal(t, 1, d.defaultState) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) select { case <-sem: @@ -182,7 +182,7 @@ func TestButtonHalt(t *testing.T) { } }() // act & assert - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) wg.Wait() // wait until the go function was really finished } diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index b845813aa..7f3d34040 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -28,12 +29,12 @@ func TestBuzzerDriverSetName(t *testing.T) { func TestBuzzerDriverStart(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestBuzzerDriverHalt(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestBuzzerDriverToggle(t *testing.T) { @@ -47,7 +48,7 @@ func TestBuzzerDriverToggle(t *testing.T) { func TestBuzzerDriverTone(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - assert.NoError(t, d.Tone(100, 0.01)) + require.NoError(t, d.Tone(100, 0.01)) } func TestBuzzerDriverOnError(t *testing.T) { @@ -57,7 +58,7 @@ func TestBuzzerDriverOnError(t *testing.T) { return errors.New("write error") } - assert.ErrorContains(t, d.On(), "write error") + require.ErrorContains(t, d.On(), "write error") } func TestBuzzerDriverOffError(t *testing.T) { @@ -67,7 +68,7 @@ func TestBuzzerDriverOffError(t *testing.T) { return errors.New("write error") } - assert.ErrorContains(t, d.Off(), "write error") + require.ErrorContains(t, d.Off(), "write error") } func TestBuzzerDriverToneError(t *testing.T) { @@ -77,5 +78,5 @@ func TestBuzzerDriverToneError(t *testing.T) { return errors.New("write error") } - assert.ErrorContains(t, d.Tone(100, 0.01), "write error") + require.ErrorContains(t, d.Tone(100, 0.01), "write error") } diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index 7996eee28..f9eaa96e6 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -43,120 +44,120 @@ func TestDirectPinDriver(t *testing.T) { assert.Nil(t, ret["err"]) err = d.Command("DigitalWrite")(map[string]interface{}{"level": "1"}) - assert.ErrorContains(t, err.(error), "write error") + require.ErrorContains(t, err.(error), "write error") err = d.Command("PwmWrite")(map[string]interface{}{"level": "1"}) - assert.ErrorContains(t, err.(error), "write error") + require.ErrorContains(t, err.(error), "write error") err = d.Command("ServoWrite")(map[string]interface{}{"level": "1"}) - assert.ErrorContains(t, err.(error), "write error") + require.ErrorContains(t, err.(error), "write error") } func TestDirectPinDriverStart(t *testing.T) { d := initTestDirectPinDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestDirectPinDriverHalt(t *testing.T) { d := initTestDirectPinDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestDirectPinDriverOff(t *testing.T) { d := initTestDirectPinDriver() - assert.NotNil(t, d.Off()) + require.Error(t, d.Off()) a := newGpioTestAdaptor() d = NewDirectPinDriver(a, "1") - assert.NoError(t, d.Off()) + require.NoError(t, d.Off()) } func TestDirectPinDriverOffNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.ErrorContains(t, d.Off(), "DigitalWrite is not supported by this platform") + require.ErrorContains(t, d.Off(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverOn(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - assert.NoError(t, d.On()) + require.NoError(t, d.On()) } func TestDirectPinDriverOnError(t *testing.T) { d := initTestDirectPinDriver() - assert.NotNil(t, d.On()) + require.Error(t, d.On()) } func TestDirectPinDriverOnNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.ErrorContains(t, d.On(), "DigitalWrite is not supported by this platform") + require.ErrorContains(t, d.On(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWrite(t *testing.T) { adaptor := newGpioTestAdaptor() d := NewDirectPinDriver(adaptor, "1") - assert.NoError(t, d.DigitalWrite(1)) + require.NoError(t, d.DigitalWrite(1)) } func TestDirectPinDriverDigitalWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.ErrorContains(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") + require.ErrorContains(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWriteError(t *testing.T) { d := initTestDirectPinDriver() - assert.NotNil(t, d.DigitalWrite(1)) + require.Error(t, d.DigitalWrite(1)) } func TestDirectPinDriverDigitalRead(t *testing.T) { d := initTestDirectPinDriver() ret, err := d.DigitalRead() assert.Equal(t, 1, ret) - assert.NoError(t, err) + require.NoError(t, err) } func TestDirectPinDriverDigitalReadNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") _, e := d.DigitalRead() - assert.ErrorContains(t, e, "DigitalRead is not supported by this platform") + require.ErrorContains(t, e, "DigitalRead is not supported by this platform") } func TestDirectPinDriverPwmWrite(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - assert.NoError(t, d.PwmWrite(1)) + require.NoError(t, d.PwmWrite(1)) } func TestDirectPinDriverPwmWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.ErrorContains(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") + require.ErrorContains(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") } func TestDirectPinDriverPwmWriteError(t *testing.T) { d := initTestDirectPinDriver() - assert.NotNil(t, d.PwmWrite(1)) + require.Error(t, d.PwmWrite(1)) } func TestDirectPinDriverServoWrite(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") - assert.NoError(t, d.ServoWrite(1)) + require.NoError(t, d.ServoWrite(1)) } func TestDirectPinDriverServoWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - assert.ErrorContains(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") + require.ErrorContains(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") } func TestDirectPinDriverServoWriteError(t *testing.T) { d := initTestDirectPinDriver() - assert.NotNil(t, d.ServoWrite(1)) + require.Error(t, d.ServoWrite(1)) } func TestDirectPinDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/easy_driver_test.go b/drivers/gpio/easy_driver_test.go index 5e978ed68..11c5cd6f6 100644 --- a/drivers/gpio/easy_driver_test.go +++ b/drivers/gpio/easy_driver_test.go @@ -29,20 +29,20 @@ func TestNewEasyDriver(t *testing.T) { assert.IsType(t, &EasyDriver{}, d) assert.True(t, strings.HasPrefix(d.name, "EasyDriver")) assert.Equal(t, a, d.connection) - assert.NoError(t, d.afterStart()) - assert.NoError(t, d.beforeHalt()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) assert.Equal(t, "1", d.stepPin) assert.Equal(t, "2", d.dirPin) assert.Equal(t, "3", d.enPin) assert.Equal(t, "4", d.sleepPin) - assert.Equal(t, float32(anglePerStep), d.anglePerStep) + assert.InDelta(t, float32(anglePerStep), d.anglePerStep, 0.0) assert.Equal(t, uint(14), d.speedRpm) assert.Equal(t, "forward", d.direction) assert.Equal(t, 0, d.stepNum) - assert.Equal(t, false, d.disabled) - assert.Equal(t, false, d.sleeping) + assert.False(t, d.disabled) + assert.False(t, d.sleeping) assert.Nil(t, d.stopAsynchRunFunc) } @@ -95,7 +95,7 @@ func TestEasyDriverMoveDeg_IsMoving(t *testing.T) { // for cleanup dangling channels if d.stopAsynchRunFunc != nil { err := d.stopAsynchRunFunc(true) - assert.NoError(t, err) + require.NoError(t, err) } }() // arrange: different behavior @@ -110,12 +110,12 @@ func TestEasyDriverMoveDeg_IsMoving(t *testing.T) { err := d.MoveDeg(tc.inputDeg) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tc.wantSteps, d.stepNum) - assert.Equal(t, tc.wantWrites, len(a.written)) + assert.Len(t, a.written, tc.wantWrites) assert.Equal(t, tc.wantMoving, d.IsMoving()) }) } @@ -168,9 +168,9 @@ func TestEasyDriverRun_IsMoving(t *testing.T) { err := d.Run() // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tc.wantMoving, d.IsMoving()) }) @@ -185,7 +185,7 @@ func TestEasyDriverStop_IsMoving(t *testing.T) { // act err := d.Stop() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, d.IsMoving()) } @@ -197,7 +197,7 @@ func TestEasyDriverHalt_IsMoving(t *testing.T) { // act err := d.Halt() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, d.IsMoving()) } @@ -259,9 +259,9 @@ func TestEasyDriverSetDirection(t *testing.T) { err := d.SetDirection(tc.input) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.dirPin, a.written[0].pin) assert.Equal(t, tc.wantWritten, a.written[0].val) } @@ -356,9 +356,9 @@ func TestEasyDriverSetSpeed(t *testing.T) { err := d.SetSpeed(tc.input) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tc.want, d.speedRpm) }) @@ -515,11 +515,11 @@ func TestEasyDriverEnable_IsEnabled(t *testing.T) { // act err := d.Enable() // assert - assert.Equal(t, tc.wantWrites, len(a.written)) + assert.Len(t, a.written, tc.wantWrites) if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.enPin, a.written[0].pin) assert.Equal(t, byte(0), a.written[0].val) // enable pin is active low } @@ -596,9 +596,9 @@ func TestEasyDriverDisable_IsEnabled(t *testing.T) { err := d.Disable() // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, byte(1), writtenValue) // enable pin is active low } assert.Equal(t, tc.wantEnabled, d.IsEnabled()) @@ -676,9 +676,9 @@ func TestEasyDriverSleep_IsSleeping(t *testing.T) { err := d.Sleep() // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, byte(0), writtenValue) // sleep pin is active low } assert.Equal(t, tc.wantSleep, d.IsSleeping()) @@ -745,9 +745,9 @@ func TestEasyDriverWake_IsSleeping(t *testing.T) { err := d.Wake() // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, byte(1), writtenValue) // sleep pin is active low } assert.Equal(t, tc.wantSleep, d.IsSleeping()) diff --git a/drivers/gpio/gpio_driver.go b/drivers/gpio/gpio_driver.go index bc09ae0a7..896897dcc 100644 --- a/drivers/gpio/gpio_driver.go +++ b/drivers/gpio/gpio_driver.go @@ -47,22 +47,22 @@ const ( // PwmWriter interface represents an Adaptor which has Pwm capabilities type PwmWriter interface { - PwmWrite(string, byte) (err error) + PwmWrite(pin string, val byte) (err error) } // ServoWriter interface represents an Adaptor which has Servo capabilities type ServoWriter interface { - ServoWrite(string, byte) (err error) + ServoWrite(pin string, val byte) (err error) } // DigitalWriter interface represents an Adaptor which has DigitalWrite capabilities type DigitalWriter interface { - DigitalWrite(string, byte) (err error) + DigitalWrite(pin string, val byte) (err error) } // DigitalReader interface represents an Adaptor which has DigitalRead capabilities type DigitalReader interface { - DigitalRead(string) (val int, err error) + DigitalRead(pin string) (val int, err error) } // Driver implements the interface gobot.Driver. diff --git a/drivers/gpio/gpio_driver_test.go b/drivers/gpio/gpio_driver_test.go index da26d6b14..0ea6021ca 100644 --- a/drivers/gpio/gpio_driver_test.go +++ b/drivers/gpio/gpio_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -30,8 +31,8 @@ func TestNewDriver(t *testing.T) { assert.IsType(t, &Driver{}, d) assert.Contains(t, d.name, "GPIO_BASIC") assert.Equal(t, a, d.connection) - assert.NoError(t, d.afterStart()) - assert.NoError(t, d.beforeHalt()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) } @@ -56,20 +57,20 @@ func TestStart(t *testing.T) { // arrange d := initTestDriver() // act, assert - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) // arrange after start function d.afterStart = func() error { return fmt.Errorf("after start error") } // act, assert - assert.ErrorContains(t, d.Start(), "after start error") + require.ErrorContains(t, d.Start(), "after start error") } func TestHalt(t *testing.T) { // arrange d := initTestDriver() // act, assert - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) // arrange after start function d.beforeHalt = func() error { return fmt.Errorf("before halt error") } // act, assert - assert.ErrorContains(t, d.Halt(), "before halt error") + require.ErrorContains(t, d.Halt(), "before halt error") } diff --git a/drivers/gpio/grove_drivers_test.go b/drivers/gpio/grove_drivers_test.go index d580fc51f..e614432f8 100644 --- a/drivers/gpio/grove_drivers_test.go +++ b/drivers/gpio/grove_drivers_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -91,7 +92,7 @@ func TestDriverPublishesError(t *testing.T) { } testAdaptor.digitalReadFunc = returnErr - assert.NoError(t, driver.Start()) + require.NoError(t, driver.Start()) // expect error _ = driver.Once(driver.Event(Error), func(data interface{}) { diff --git a/drivers/gpio/hcsr04_driver_test.go b/drivers/gpio/hcsr04_driver_test.go index 994600a55..da65fc901 100644 --- a/drivers/gpio/hcsr04_driver_test.go +++ b/drivers/gpio/hcsr04_driver_test.go @@ -39,13 +39,13 @@ func TestNewHCSR04Driver(t *testing.T) { assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.name, "HCSR04")) assert.Equal(t, a, d.connection) - assert.NoError(t, d.afterStart()) - assert.NoError(t, d.beforeHalt()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) assert.Equal(t, triggerPinID, d.triggerPinID) assert.Equal(t, echoPinID, d.echoPinID) - assert.Equal(t, false, d.useEdgePolling) + assert.False(t, d.useEdgePolling) assert.Equal(t, tpin, d.triggerPin) assert.Equal(t, epin, d.echoPin) } @@ -115,11 +115,11 @@ func TestHCSR04MeasureDistance(t *testing.T) { // assert assert.Equal(t, tc.wantCallsWrite, numCallsWrite) if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { require.NoError(t, err) } - assert.Equal(t, tc.wantVal, got) + assert.InDelta(t, tc.wantVal, got, 0.0) }) } } @@ -151,7 +151,7 @@ func TestHCSR04Distance(t *testing.T) { // act got := d.Distance() // assert - assert.Equal(t, tc.wantVal, got) + assert.InDelta(t, tc.wantVal, got, 0.0) }) } } @@ -197,7 +197,7 @@ func TestHCSR04StartDistanceMonitor(t *testing.T) { time.Sleep(1 * time.Millisecond) // < 160 ms // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { require.NoError(t, err) assert.NotNil(t, d.distanceMonitorStopChan) @@ -240,7 +240,7 @@ func TestHCSR04StopDistanceMonitor(t *testing.T) { time.Sleep(1 * time.Millisecond) // < 160 ms // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { require.NoError(t, err) assert.Nil(t, d.distanceMonitorStopChan) diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index 81985d98f..a69f9f775 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -61,7 +62,7 @@ func TestHD44780Driver(t *testing.T) { func TestHD44780DriverHalt(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestHD44780DriverDefaultName(t *testing.T) { @@ -77,7 +78,7 @@ func TestHD44780DriverSetName(t *testing.T) { func TestHD44780DriverStart(t *testing.T) { d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestHD44780DriverStartError(t *testing.T) { @@ -93,7 +94,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_4BITMODE, "13", "15", pins) - assert.ErrorContains(t, d.Start(), "Initialization error") + require.ErrorContains(t, d.Start(), "Initialization error") pins = HD44780DataPin{ D0: "31", @@ -106,7 +107,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_8BITMODE, "13", "15", pins) - assert.ErrorContains(t, d.Start(), "Initialization error") + require.ErrorContains(t, d.Start(), "Initialization error") } func TestHD44780DriverWrite(t *testing.T) { @@ -114,11 +115,11 @@ func TestHD44780DriverWrite(t *testing.T) { d, _ = initTestHD44780Driver4BitModeWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Write("hello gobot")) + require.NoError(t, d.Write("hello gobot")) d, _ = initTestHD44780Driver8BitModeWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Write("hello gobot")) + require.NoError(t, d.Write("hello gobot")) } func TestHD44780DriverWriteError(t *testing.T) { @@ -130,108 +131,108 @@ func TestHD44780DriverWriteError(t *testing.T) { return errors.New("write error") } _ = d.Start() - assert.ErrorContains(t, d.Write("hello gobot"), "write error") + require.ErrorContains(t, d.Write("hello gobot"), "write error") d, a = initTestHD44780Driver8BitModeWithStubbedAdaptor() a.digitalWriteFunc = func(string, byte) (err error) { return errors.New("write error") } _ = d.Start() - assert.ErrorContains(t, d.Write("hello gobot"), "write error") + require.ErrorContains(t, d.Write("hello gobot"), "write error") } func TestHD44780DriverClear(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Clear()) + require.NoError(t, d.Clear()) } func TestHD44780DriverHome(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Home()) + require.NoError(t, d.Home()) } func TestHD44780DriverSetCursor(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.SetCursor(0, 3)) + require.NoError(t, d.SetCursor(0, 3)) } func TestHD44780DriverSetCursorInvalid(t *testing.T) { d := initTestHD44780Driver() - assert.ErrorContains(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") - assert.ErrorContains(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") - assert.ErrorContains(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") - assert.ErrorContains(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") + require.ErrorContains(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") + require.ErrorContains(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") + require.ErrorContains(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") + require.ErrorContains(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") } func TestHD44780DriverDisplayOn(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Display(true)) + require.NoError(t, d.Display(true)) } func TestHD44780DriverDisplayOff(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Display(false)) + require.NoError(t, d.Display(false)) } func TestHD44780DriverCursorOn(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Cursor(true)) + require.NoError(t, d.Cursor(true)) } func TestHD44780DriverCursorOff(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Cursor(false)) + require.NoError(t, d.Cursor(false)) } func TestHD44780DriverBlinkOn(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Blink(true)) + require.NoError(t, d.Blink(true)) } func TestHD44780DriverBlinkOff(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.Blink(false)) + require.NoError(t, d.Blink(false)) } func TestHD44780DriverScrollLeft(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.ScrollLeft()) + require.NoError(t, d.ScrollLeft()) } func TestHD44780DriverScrollRight(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.ScrollRight()) + require.NoError(t, d.ScrollRight()) } func TestHD44780DriverLeftToRight(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.LeftToRight()) + require.NoError(t, d.LeftToRight()) } func TestHD44780DriverRightToLeft(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.RightToLeft()) + require.NoError(t, d.RightToLeft()) } func TestHD44780DriverSendCommand(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.SendCommand(0x33)) + require.NoError(t, d.SendCommand(0x33)) } func TestHD44780DriverWriteChar(t *testing.T) { d := initTestHD44780Driver() - assert.NoError(t, d.WriteChar(0x41)) + require.NoError(t, d.WriteChar(0x41)) } func TestHD44780DriverCreateChar(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - assert.NoError(t, d.CreateChar(0, charMap)) + require.NoError(t, d.CreateChar(0, charMap)) } func TestHD44780DriverCreateCharError(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - assert.ErrorContains(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") + require.ErrorContains(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") } diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index 38d40bc76..b5c74f629 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -38,26 +39,26 @@ func TestLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - assert.ErrorContains(t, err.(error), "write error") + require.ErrorContains(t, err.(error), "write error") err = d.Command("On")(nil) - assert.ErrorContains(t, err.(error), "write error") + require.ErrorContains(t, err.(error), "write error") err = d.Command("Off")(nil) - assert.ErrorContains(t, err.(error), "write error") + require.ErrorContains(t, err.(error), "write error") err = d.Command("Brightness")(map[string]interface{}{"level": 100.0}) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") } func TestLedDriverStart(t *testing.T) { d := initTestLedDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestLedDriverHalt(t *testing.T) { d := initTestLedDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestLedDriverToggle(t *testing.T) { @@ -76,7 +77,7 @@ func TestLedDriverBrightness(t *testing.T) { err = errors.New("pwm error") return } - assert.ErrorContains(t, d.Brightness(150), "pwm error") + require.ErrorContains(t, d.Brightness(150), "pwm error") } func TestLEDDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/max7219_driver_test.go b/drivers/gpio/max7219_driver_test.go index 9fab6bd22..8515b6bab 100644 --- a/drivers/gpio/max7219_driver_test.go +++ b/drivers/gpio/max7219_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -32,12 +33,12 @@ func TestMAX7219Driver(t *testing.T) { func TestMAX7219DriverStart(t *testing.T) { d := initTestMAX7219Driver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestMAX7219DriverHalt(t *testing.T) { d := initTestMAX7219Driver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestMAX7219DriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/motor_driver_test.go b/drivers/gpio/motor_driver_test.go index 6ec1c9142..5864b791c 100644 --- a/drivers/gpio/motor_driver_test.go +++ b/drivers/gpio/motor_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -21,12 +22,12 @@ func TestMotorDriver(t *testing.T) { func TestMotorDriverStart(t *testing.T) { d := initTestMotorDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestMotorDriverHalt(t *testing.T) { d := initTestMotorDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestMotorDriverIsOn(t *testing.T) { diff --git a/drivers/gpio/pir_motion_driver_test.go b/drivers/gpio/pir_motion_driver_test.go index b1ad17cd3..709f07b61 100644 --- a/drivers/gpio/pir_motion_driver_test.go +++ b/drivers/gpio/pir_motion_driver_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -36,7 +37,7 @@ func TestNewPIRMotionDriver(t *testing.T) { assert.NotNil(t, d.mutex) assert.NotNil(t, d.Eventer) assert.Equal(t, "1", d.pin) - assert.Equal(t, false, d.active) + assert.False(t, d.active) assert.Equal(t, 10*time.Millisecond, d.interval) assert.NotNil(t, d.halt) // act & assert other interval @@ -75,7 +76,7 @@ func TestPIRMotionStart(t *testing.T) { err := d.Start() // assert & rearrange - assert.NoError(t, err) + require.NoError(t, err) select { case <-sem: @@ -134,7 +135,7 @@ func TestPIRMotionHalt(t *testing.T) { } }() // act & assert - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) wg.Wait() // wait until the go function was really finished } diff --git a/drivers/gpio/relay_driver_test.go b/drivers/gpio/relay_driver_test.go index 340965d72..320034403 100644 --- a/drivers/gpio/relay_driver_test.go +++ b/drivers/gpio/relay_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -38,12 +39,12 @@ func TestRelayDriverSetName(t *testing.T) { func TestRelayDriverStart(t *testing.T) { d, _ := initTestRelayDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestRelayDriverHalt(t *testing.T) { d, _ := initTestRelayDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestRelayDriverToggle(t *testing.T) { diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index 818e2490a..46121ca33 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -42,26 +43,26 @@ func TestRgbLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") err = d.Command("On")(nil) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") err = d.Command("Off")(nil) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") err = d.Command("SetRGB")(map[string]interface{}{"r": 0xff, "g": 0xff, "b": 0xff}) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") } func TestRgbLedDriverStart(t *testing.T) { d := initTestRgbLedDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestRgbLedDriverHalt(t *testing.T) { d := initTestRgbLedDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestRgbLedDriverToggle(t *testing.T) { @@ -76,14 +77,14 @@ func TestRgbLedDriverToggle(t *testing.T) { func TestRgbLedDriverSetLevel(t *testing.T) { a := newGpioTestAdaptor() d := NewRgbLedDriver(a, "1", "2", "3") - assert.NoError(t, d.SetLevel("1", 150)) + require.NoError(t, d.SetLevel("1", 150)) d = NewRgbLedDriver(a, "1", "2", "3") a.pwmWriteFunc = func(string, byte) (err error) { err = errors.New("pwm error") return } - assert.ErrorContains(t, d.SetLevel("1", 150), "pwm error") + require.ErrorContains(t, d.SetLevel("1", 150), "pwm error") } func TestRgbLedDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index 5aad8c953..a0db6d242 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -29,26 +30,26 @@ func TestServoDriver(t *testing.T) { } err = d.Command("Min")(nil) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") err = d.Command("Center")(nil) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") err = d.Command("Max")(nil) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") err = d.Command("Move")(map[string]interface{}{"angle": 100.0}) - assert.ErrorContains(t, err.(error), "pwm error") + require.ErrorContains(t, err.(error), "pwm error") } func TestServoDriverStart(t *testing.T) { d := initTestServoDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestServoDriverHalt(t *testing.T) { d := initTestServoDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestServoDriverMove(t *testing.T) { diff --git a/drivers/gpio/stepper_driver_test.go b/drivers/gpio/stepper_driver_test.go index 237b05901..b00c31ef5 100644 --- a/drivers/gpio/stepper_driver_test.go +++ b/drivers/gpio/stepper_driver_test.go @@ -30,13 +30,13 @@ func TestNewStepperDriver(t *testing.T) { assert.IsType(t, &StepperDriver{}, d) assert.True(t, strings.HasPrefix(d.name, "Stepper")) assert.Equal(t, a, d.connection) - assert.NoError(t, d.afterStart()) - assert.NoError(t, d.beforeHalt()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) assert.Equal(t, "forward", d.direction) assert.Equal(t, StepperModes.DualPhaseStepping, d.phase) - assert.Equal(t, float32(stepsPerRev), d.stepsPerRev) + assert.InDelta(t, float32(stepsPerRev), d.stepsPerRev, 0.0) assert.Equal(t, 0, d.stepNum) assert.Nil(t, d.stopAsynchRunFunc) } @@ -126,7 +126,7 @@ func TestStepperMove_IsMoving(t *testing.T) { // for cleanup dangling channels if d.stopAsynchRunFunc != nil { err := d.stopAsynchRunFunc(true) - assert.NoError(t, err) + require.NoError(t, err) } }() // arrange: different behavior @@ -141,12 +141,12 @@ func TestStepperMove_IsMoving(t *testing.T) { err := d.Move(tc.inputSteps) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tc.wantSteps, d.stepNum) - assert.Equal(t, tc.wantWrites, len(a.written)) + assert.Len(t, a.written, tc.wantWrites) assert.Equal(t, tc.wantMoving, d.IsMoving()) }) } @@ -182,7 +182,7 @@ func TestStepperRun_IsMoving(t *testing.T) { // for cleanup dangling channels if d.stopAsynchRunFunc != nil { err := d.stopAsynchRunFunc(true) - assert.NoError(t, err) + require.NoError(t, err) } }() // arrange: different behavior @@ -216,9 +216,9 @@ func TestStepperRun_IsMoving(t *testing.T) { err := d.Run() // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tc.wantMoving, d.IsMoving()) if writeChan != nil { @@ -231,9 +231,9 @@ func TestStepperRun_IsMoving(t *testing.T) { d.stopAsynchRunFunc = nil } if tc.simulateWriteErr { - assert.Error(t, asynchErr) + require.Error(t, asynchErr) } else { - assert.NoError(t, asynchErr) + require.NoError(t, asynchErr) } } }) @@ -265,9 +265,9 @@ func TestStepperStop_IsMoving(t *testing.T) { err := d.Stop() // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.False(t, d.IsMoving()) }) @@ -296,7 +296,7 @@ func TestStepperHalt_IsMoving(t *testing.T) { // act err := d.Halt() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, d.IsMoving()) }) } @@ -331,9 +331,9 @@ func TestStepperSetDirection(t *testing.T) { err := d.SetDirection(tc.input) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tc.wantVal, d.direction) }) @@ -419,9 +419,9 @@ func TestStepperSetSpeed(t *testing.T) { err := d.SetSpeed(tc.input) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tc.want, d.speedRpm) }) diff --git a/drivers/gpio/tm1638_driver_test.go b/drivers/gpio/tm1638_driver_test.go index dc5ce2718..dc916d9ba 100644 --- a/drivers/gpio/tm1638_driver_test.go +++ b/drivers/gpio/tm1638_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -32,12 +33,12 @@ func TestTM1638Driver(t *testing.T) { func TestTM1638DriverStart(t *testing.T) { d := initTestTM1638Driver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestTM1638DriverHalt(t *testing.T) { d := initTestTM1638Driver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestTM1638DriverDefaultName(t *testing.T) { @@ -54,19 +55,19 @@ func TestTM1638DriverSetName(t *testing.T) { func TestTM1638DriverFromStringToByteArray(t *testing.T) { d := initTestTM1638Driver() data := d.fromStringToByteArray("Hello World") - assert.Equal(t, data, []byte{0x76, 0x7B, 0x30, 0x30, 0x5C, 0x00, 0x1D, 0x5C, 0x50, 0x30, 0x5E}) + assert.Equal(t, []byte{0x76, 0x7B, 0x30, 0x30, 0x5C, 0x00, 0x1D, 0x5C, 0x50, 0x30, 0x5E}, data) } func TestTM1638DriverAddFonts(t *testing.T) { d := initTestTM1638Driver() d.AddFonts(map[string]byte{"µ": 0x1C, "ß": 0x7F}) data := d.fromStringToByteArray("µß") - assert.Equal(t, data, []byte{0x1C, 0x7F}) + assert.Equal(t, []byte{0x1C, 0x7F}, data) } func TestTM1638DriverClearFonts(t *testing.T) { d := initTestTM1638Driver() d.ClearFonts() data := d.fromStringToByteArray("Hello World") - assert.Equal(t, data, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, data) } diff --git a/drivers/i2c/adafruit1109_driver_test.go b/drivers/i2c/adafruit1109_driver_test.go index bea0e179f..838f57592 100644 --- a/drivers/i2c/adafruit1109_driver_test.go +++ b/drivers/i2c/adafruit1109_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -49,12 +50,12 @@ func TestNewAdafruit1109Driver(t *testing.T) { func TestAdafruit1109Connect(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - assert.NoError(t, d.Connect()) + require.NoError(t, d.Connect()) } func TestAdafruit1109Finalize(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - assert.NoError(t, d.Finalize()) + require.NoError(t, d.Finalize()) } func TestAdafruit1109SetName(t *testing.T) { @@ -65,7 +66,7 @@ func TestAdafruit1109SetName(t *testing.T) { func TestAdafruit1109Start(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestAdafruit1109StartWriteErr(t *testing.T) { @@ -73,7 +74,7 @@ func TestAdafruit1109StartWriteErr(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.Start(), "write error") + require.ErrorContains(t, d.Start(), "write error") } func TestAdafruit1109StartReadErr(t *testing.T) { @@ -81,13 +82,13 @@ func TestAdafruit1109StartReadErr(t *testing.T) { adaptor.i2cReadImpl = func([]byte) (int, error) { return 0, errors.New("read error") } - assert.ErrorContains(t, d.Start(), "MCP write-read: MCP write-ReadByteData(reg=0): read error") + require.ErrorContains(t, d.Start(), "MCP write-read: MCP write-ReadByteData(reg=0): read error") } func TestAdafruit1109Halt(t *testing.T) { d, _ := initTestAdafruit1109WithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestAdafruit1109DigitalRead(t *testing.T) { @@ -128,9 +129,9 @@ func TestAdafruit1109DigitalRead(t *testing.T) { // act got, err := d.DigitalRead(name) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, tc.wantReg, a.written[0]) assert.Equal(t, 1, got) }) @@ -160,7 +161,7 @@ func TestAdafruit1109SelectButton(t *testing.T) { // act got, err := d.SelectButton() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) @@ -190,7 +191,7 @@ func TestAdafruit1109UpButton(t *testing.T) { // act got, err := d.UpButton() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) @@ -220,7 +221,7 @@ func TestAdafruit1109DownButton(t *testing.T) { // act got, err := d.DownButton() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) @@ -250,7 +251,7 @@ func TestAdafruit1109LeftButton(t *testing.T) { // act got, err := d.LeftButton() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) @@ -280,7 +281,7 @@ func TestAdafruit1109RightButton(t *testing.T) { // act got, err := d.RightButton() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, tc.want, got) }) diff --git a/drivers/i2c/adafruit2327_driver_test.go b/drivers/i2c/adafruit2327_driver_test.go index 9690be1fa..b070c3f4b 100644 --- a/drivers/i2c/adafruit2327_driver_test.go +++ b/drivers/i2c/adafruit2327_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -47,8 +48,8 @@ func TestAdafruit2327SetServoMotorFreq(t *testing.T) { // act err := d.SetServoMotorFreq(freq) // assert - assert.NoError(t, err) - assert.Equal(t, 9, len(a.written)) // detailed test, see "TestPCA9685SetPWMFreq" + require.NoError(t, err) + assert.Len(t, a.written, 9) // detailed test, see "TestPCA9685SetPWMFreq" } func TestAdafruit2327SetServoMotorFreqError(t *testing.T) { @@ -59,7 +60,7 @@ func TestAdafruit2327SetServoMotorFreqError(t *testing.T) { } const freq = 60.0 // act & assert - assert.ErrorContains(t, d.SetServoMotorFreq(freq), "write error") + require.ErrorContains(t, d.SetServoMotorFreq(freq), "write error") } func TestAdafruit2327SetServoMotorPulse(t *testing.T) { @@ -74,8 +75,8 @@ func TestAdafruit2327SetServoMotorPulse(t *testing.T) { // act err := d.SetServoMotorPulse(channel, on, off) // assert - assert.NoError(t, err) - assert.Equal(t, 8, len(a.written)) // detailed test, see "TestPCA9685SetPWM" + require.NoError(t, err) + assert.Len(t, a.written, 8) // detailed test, see "TestPCA9685SetPWM" } func TestAdafruit2327SetServoMotorPulseError(t *testing.T) { @@ -90,5 +91,5 @@ func TestAdafruit2327SetServoMotorPulseError(t *testing.T) { off int32 = 4321 ) // act & assert - assert.ErrorContains(t, d.SetServoMotorPulse(channel, on, off), "write error") + require.ErrorContains(t, d.SetServoMotorPulse(channel, on, off), "write error") } diff --git a/drivers/i2c/adafruit2348_driver_test.go b/drivers/i2c/adafruit2348_driver_test.go index d668034cf..a791f646f 100644 --- a/drivers/i2c/adafruit2348_driver_test.go +++ b/drivers/i2c/adafruit2348_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -52,8 +53,8 @@ func TestAdafruit2348SetDCMotorSpeed(t *testing.T) { // act err := d.SetDCMotorSpeed(dcMotor, speed) // assert - assert.NoError(t, err) - assert.Equal(t, 8, len(a.written)) // detailed test, see "TestPCA9685SetPWM" + require.NoError(t, err) + assert.Len(t, a.written, 8) // detailed test, see "TestPCA9685SetPWM" } func TestAdafruit2348SetDCMotorSpeedError(t *testing.T) { @@ -63,7 +64,7 @@ func TestAdafruit2348SetDCMotorSpeedError(t *testing.T) { return 0, errors.New("write error") } // act & assert - assert.ErrorContains(t, d.SetDCMotorSpeed(1, 255), "write error") + require.ErrorContains(t, d.SetDCMotorSpeed(1, 255), "write error") } func TestAdafruit2348RunDCMotor(t *testing.T) { @@ -71,9 +72,9 @@ func TestAdafruit2348RunDCMotor(t *testing.T) { d, _ := initTestAdafruit2348WithStubbedAdaptor() const dcMotor = 1 // act & assert - assert.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Forward)) - assert.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Backward)) - assert.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Release)) + require.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Forward)) + require.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Backward)) + require.NoError(t, d.RunDCMotor(dcMotor, Adafruit2348Release)) } func TestAdafruit2348RunDCMotorError(t *testing.T) { @@ -84,9 +85,9 @@ func TestAdafruit2348RunDCMotorError(t *testing.T) { } const dcMotor = 1 // act & assert - assert.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Forward), "write error") - assert.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Backward), "write error") - assert.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Release), "write error") + require.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Forward), "write error") + require.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Backward), "write error") + require.ErrorContains(t, d.RunDCMotor(dcMotor, Adafruit2348Release), "write error") } func TestAdafruit2348SetStepperMotorSpeed(t *testing.T) { @@ -97,8 +98,8 @@ func TestAdafruit2348SetStepperMotorSpeed(t *testing.T) { rpm = 30 ) // act & assert - assert.NoError(t, d.SetStepperMotorSpeed(stepperMotor, rpm)) - assert.Equal(t, 0.01, d.stepperMotors[stepperMotor].secPerStep) // 60/(revSteps*rpm), revSteps=200 + require.NoError(t, d.SetStepperMotorSpeed(stepperMotor, rpm)) + assert.InDelta(t, 0.01, d.stepperMotors[stepperMotor].secPerStep, 0.0) // 60/(revSteps*rpm), revSteps=200 } func TestAdafruit2348StepperSingleStep(t *testing.T) { @@ -113,7 +114,7 @@ func TestAdafruit2348StepperSingleStep(t *testing.T) { // act err := d.Step(stepperMotor, steps, back, single) // assert - assert.NoError(t, err) + require.NoError(t, err) } func TestAdafruit2348StepperDoubleStep(t *testing.T) { @@ -128,7 +129,7 @@ func TestAdafruit2348StepperDoubleStep(t *testing.T) { // act err := d.Step(stepperMotor, steps, back, double) // assert - assert.NoError(t, err) + require.NoError(t, err) } func TestAdafruit2348StepperInterleaveStep(t *testing.T) { @@ -143,7 +144,7 @@ func TestAdafruit2348StepperInterleaveStep(t *testing.T) { // act err := d.Step(stepperMotor, steps, back, interleave) // assert - assert.NoError(t, err) + require.NoError(t, err) } func TestAdafruit2348StepperMicroStep(t *testing.T) { @@ -158,5 +159,5 @@ func TestAdafruit2348StepperMicroStep(t *testing.T) { // act err := d.Step(stepperMotor, steps, back, micro) // assert - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/drivers/i2c/ads1x15_driver_1015_test.go b/drivers/i2c/ads1x15_driver_1015_test.go index be88c09ee..5640a27aa 100644 --- a/drivers/i2c/ads1x15_driver_1015_test.go +++ b/drivers/i2c/ads1x15_driver_1015_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func initTestADS1015DriverWithStubbedAdaptor() (*ADS1x15Driver, *i2cTestAdaptor) { @@ -73,38 +74,38 @@ func TestADS1015AnalogRead(t *testing.T) { val, err := d.AnalogRead("0") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("1") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("2") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("3") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("0-1") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("0-3") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("1-3") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("2-3") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) _, err = d.AnalogRead("3-2") - assert.NotNil(t, err.Error()) + require.Error(t, err) } func TestADS1x15AnalogReadError(t *testing.T) { @@ -115,14 +116,14 @@ func TestADS1x15AnalogReadError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestADS1x15AnalogReadInvalidPin(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.AnalogRead("99") - assert.ErrorContains(t, err, "Invalid channel (99), must be between 0 and 3") + require.ErrorContains(t, err, "Invalid channel (99), must be between 0 and 3") } func TestADS1x15AnalogReadWriteError(t *testing.T) { @@ -133,41 +134,41 @@ func TestADS1x15AnalogReadWriteError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") _, err = d.AnalogRead("0-1") - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") _, err = d.AnalogRead("2-3") - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestADS1x15ReadInvalidChannel(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(9, 1, 1600) - assert.ErrorContains(t, err, "Invalid channel (9), must be between 0 and 3") + require.ErrorContains(t, err, "Invalid channel (9), must be between 0 and 3") } func TestADS1x15ReadInvalidGain(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(0, 8, 1600) - assert.ErrorContains(t, err, "Gain (8) must be one of: [0 1 2 3 4 5 6 7]") + require.ErrorContains(t, err, "Gain (8) must be one of: [0 1 2 3 4 5 6 7]") } func TestADS1x15ReadInvalidDataRate(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.Read(0, 1, 321) - assert.ErrorContains(t, err, "Invalid data rate (321). Accepted values: [128 250 490 920 1600 2400 3300]") + require.ErrorContains(t, err, "Invalid data rate (321). Accepted values: [128 250 490 920 1600 2400 3300]") } func TestADS1x15ReadDifferenceInvalidChannel(t *testing.T) { d, _ := initTestADS1015DriverWithStubbedAdaptor() _, err := d.ReadDifference(9, 1, 1600) - assert.ErrorContains(t, err, "Invalid channel (9), must be between 0 and 3") + require.ErrorContains(t, err, "Invalid channel (9), must be between 0 and 3") } func TestADS1015_rawRead(t *testing.T) { @@ -269,10 +270,10 @@ func TestADS1015_rawRead(t *testing.T) { // act got, err := d.rawRead(channel, channelOffset, tt.gain, tt.dataRate) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tt.want, got) assert.Equal(t, 3, numCallsRead) - assert.Equal(t, 6, len(a.written)) + assert.Len(t, a.written, 6) assert.Equal(t, uint8(ads1x15PointerConfig), a.written[0]) assert.Equal(t, tt.wantConfig[0], a.written[1]) // MSByte: OS, MUX, PGA, MODE assert.Equal(t, tt.wantConfig[1], a.written[2]) // LSByte: DR, COMP_* diff --git a/drivers/i2c/ads1x15_driver_1115_test.go b/drivers/i2c/ads1x15_driver_1115_test.go index 03c7e4b81..bae7ced2e 100644 --- a/drivers/i2c/ads1x15_driver_1115_test.go +++ b/drivers/i2c/ads1x15_driver_1115_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func initTestADS1115DriverWithStubbedAdaptor() (*ADS1x15Driver, *i2cTestAdaptor) { @@ -73,38 +74,38 @@ func TestADS1115AnalogRead(t *testing.T) { val, err := d.AnalogRead("0") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("1") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("2") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("3") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("0-1") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("0-3") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("1-3") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = d.AnalogRead("2-3") assert.Equal(t, 32767, val) - assert.NoError(t, err) + require.NoError(t, err) _, err = d.AnalogRead("3-2") - assert.NotNil(t, err.Error()) + require.Error(t, err) } func TestADS1115AnalogReadError(t *testing.T) { @@ -115,14 +116,14 @@ func TestADS1115AnalogReadError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestADS1115AnalogReadInvalidPin(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.AnalogRead("98") - assert.ErrorContains(t, err, "Invalid channel (98), must be between 0 and 3") + require.ErrorContains(t, err, "Invalid channel (98), must be between 0 and 3") } func TestADS1115AnalogReadWriteError(t *testing.T) { @@ -133,41 +134,41 @@ func TestADS1115AnalogReadWriteError(t *testing.T) { } _, err := d.AnalogRead("0") - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") _, err = d.AnalogRead("0-1") - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") _, err = d.AnalogRead("2-3") - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestADS1115ReadInvalidChannel(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(7, 1, 1600) - assert.ErrorContains(t, err, "Invalid channel (7), must be between 0 and 3") + require.ErrorContains(t, err, "Invalid channel (7), must be between 0 and 3") } func TestADS1115ReadInvalidGain(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(0, 21, 1600) - assert.ErrorContains(t, err, "Gain (21) must be one of: [0 1 2 3 4 5 6 7]") + require.ErrorContains(t, err, "Gain (21) must be one of: [0 1 2 3 4 5 6 7]") } func TestADS1115ReadInvalidDataRate(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.Read(0, 1, 678) - assert.ErrorContains(t, err, "Invalid data rate (678). Accepted values: [8 16 32 64 128 250 475 860]") + require.ErrorContains(t, err, "Invalid data rate (678). Accepted values: [8 16 32 64 128 250 475 860]") } func TestADS1115ReadDifferenceInvalidChannel(t *testing.T) { d, _ := initTestADS1115DriverWithStubbedAdaptor() _, err := d.ReadDifference(5, 1, 1600) - assert.ErrorContains(t, err, "Invalid channel (5), must be between 0 and 3") + require.ErrorContains(t, err, "Invalid channel (5), must be between 0 and 3") } func TestADS1115_rawRead(t *testing.T) { @@ -269,10 +270,10 @@ func TestADS1115_rawRead(t *testing.T) { // act got, err := d.rawRead(channel, channelOffset, tt.gain, tt.dataRate) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tt.want, got) assert.Equal(t, 3, numCallsRead) - assert.Equal(t, 6, len(a.written)) + assert.Len(t, a.written, 6) assert.Equal(t, uint8(ads1x15PointerConfig), a.written[0]) assert.Equal(t, tt.wantConfig[0], a.written[1]) // MSByte: OS, MUX, PGA, MODE assert.Equal(t, tt.wantConfig[1], a.written[2]) // LSByte: DR, COMP_* diff --git a/drivers/i2c/ads1x15_driver_test.go b/drivers/i2c/ads1x15_driver_test.go index d88f46cab..3bbe77688 100644 --- a/drivers/i2c/ads1x15_driver_test.go +++ b/drivers/i2c/ads1x15_driver_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) @@ -99,5 +100,5 @@ func TestADS1x15_ads1x15BestGainForVoltage(t *testing.T) { assert.Equal(t, 2, g) _, err := ads1x15BestGainForVoltage(20.0) - assert.ErrorContains(t, err, "The maximum voltage which can be read is 6.144000") + require.ErrorContains(t, err, "The maximum voltage which can be read is 6.144000") } diff --git a/drivers/i2c/adxl345_driver_test.go b/drivers/i2c/adxl345_driver_test.go index 51e4b287e..2888160dd 100644 --- a/drivers/i2c/adxl345_driver_test.go +++ b/drivers/i2c/adxl345_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -53,7 +54,7 @@ func TestADXL345WithADXL345DataOutputRate(t *testing.T) { WithADXL345DataOutputRate(setVal)(d) // assert assert.Equal(t, setVal, d.bwRate.rate) - assert.Equal(t, 0, len(a.written)) + assert.Empty(t, a.written) } func TestADXL345WithADXL345FullScaleRange(t *testing.T) { @@ -67,7 +68,7 @@ func TestADXL345WithADXL345FullScaleRange(t *testing.T) { WithADXL345FullScaleRange(setVal)(d) // assert assert.Equal(t, setVal, d.dataFormat.fullScaleRange) - assert.Equal(t, 0, len(a.written)) + assert.Empty(t, a.written) } func TestADXL345UseLowPower(t *testing.T) { @@ -85,9 +86,9 @@ func TestADXL345UseLowPower(t *testing.T) { // act err := d.UseLowPower(setVal) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, setVal, d.bwRate.lowPower) - assert.Equal(t, 2, len(a.written)) + assert.Len(t, a.written, 2) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantVal, a.written[1]) } @@ -107,9 +108,9 @@ func TestADXL345SetRate(t *testing.T) { // act err := d.SetRate(setVal) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, setVal, d.bwRate.rate) - assert.Equal(t, 2, len(a.written)) + assert.Len(t, a.written, 2) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantVal, a.written[1]) } @@ -129,9 +130,9 @@ func TestADXL345SetRange(t *testing.T) { // act err := d.SetRange(setVal) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, setVal, d.dataFormat.fullScaleRange) - assert.Equal(t, 2, len(a.written)) + assert.Len(t, a.written, 2) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantVal, a.written[1]) } @@ -184,12 +185,12 @@ func TestADXL345RawXYZ(t *testing.T) { // act gotX, gotY, gotZ, err := d.RawXYZ() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.wantX, gotX) assert.Equal(t, tc.wantY, gotY) assert.Equal(t, tc.wantZ, gotZ) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(0x32), a.written[0]) }) } @@ -205,7 +206,7 @@ func TestADXL345RawXYZError(t *testing.T) { // act _, _, _, err := d.RawXYZ() // assert - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestADXL345XYZ(t *testing.T) { @@ -252,9 +253,9 @@ func TestADXL345XYZ(t *testing.T) { // act x, y, z, _ := d.XYZ() // assert - assert.Equal(t, tc.wantX, x) - assert.Equal(t, tc.wantY, y) - assert.Equal(t, tc.wantZ, z) + assert.InDelta(t, tc.wantX, x, 0.0) + assert.InDelta(t, tc.wantY, y, 0.0) + assert.InDelta(t, tc.wantZ, z, 0.0) }) } } @@ -269,7 +270,7 @@ func TestADXL345XYZError(t *testing.T) { // act _, _, _, err := d.XYZ() // assert - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestADXL345_initialize(t *testing.T) { @@ -292,8 +293,8 @@ func TestADXL345_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) - assert.Equal(t, 6, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 6) assert.Equal(t, wantRateReg, a.written[0]) assert.Equal(t, wantRateRegVal, a.written[1]) assert.Equal(t, wantPwrReg, a.written[2]) @@ -316,8 +317,8 @@ func TestADXL345_shutdown(t *testing.T) { // act, assert - shutdown() must be called on Halt() err := d.Halt() // assert - assert.NoError(t, err) - assert.Equal(t, 2, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 2) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantVal, a.written[1]) } diff --git a/drivers/i2c/bh1750_driver_test.go b/drivers/i2c/bh1750_driver_test.go index c75f59bd3..ffa75ee6a 100644 --- a/drivers/i2c/bh1750_driver_test.go +++ b/drivers/i2c/bh1750_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -43,12 +44,12 @@ func TestBH1750Options(t *testing.T) { func TestBH1750Start(t *testing.T) { d := NewBH1750Driver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestBH1750Halt(t *testing.T) { d, _ := initTestBH1750DriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestBH1750NullLux(t *testing.T) { @@ -96,7 +97,7 @@ func TestBH1750LuxError(t *testing.T) { } _, err := d.Lux() - assert.ErrorContains(t, err, "wrong number of bytes read") + require.ErrorContains(t, err, "wrong number of bytes read") } func TestBH1750RawSensorDataError(t *testing.T) { @@ -106,5 +107,5 @@ func TestBH1750RawSensorDataError(t *testing.T) { } _, err := d.RawSensorData() - assert.ErrorContains(t, err, "wrong number of bytes read") + require.ErrorContains(t, err, "wrong number of bytes read") } diff --git a/drivers/i2c/blinkm_driver_test.go b/drivers/i2c/blinkm_driver_test.go index 3e0811cc3..1818fbbbb 100644 --- a/drivers/i2c/blinkm_driver_test.go +++ b/drivers/i2c/blinkm_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -42,12 +43,12 @@ func TestBlinkMOptions(t *testing.T) { func TestBlinkMStart(t *testing.T) { d := NewBlinkMDriver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestBlinkMHalt(t *testing.T) { d, _ := initTestBlinkMDriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } // Commands @@ -125,7 +126,7 @@ func TestBlinkMFirmwareVersion(t *testing.T) { } _, err := d.FirmwareVersion() - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestBlinkMColor(t *testing.T) { @@ -153,7 +154,7 @@ func TestBlinkMColor(t *testing.T) { } _, err := d.Color() - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestBlinkMFade(t *testing.T) { @@ -163,7 +164,7 @@ func TestBlinkMFade(t *testing.T) { } err := d.Fade(100, 100, 100) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestBlinkMRGB(t *testing.T) { @@ -173,5 +174,5 @@ func TestBlinkMRGB(t *testing.T) { } err := d.Rgb(100, 100, 100) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } diff --git a/drivers/i2c/bme280_driver_test.go b/drivers/i2c/bme280_driver_test.go index 49e049e6c..daf393528 100644 --- a/drivers/i2c/bme280_driver_test.go +++ b/drivers/i2c/bme280_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -72,8 +73,8 @@ func TestBME280Measurements(t *testing.T) { } _ = bme280.Start() hum, err := bme280.Humidity() - assert.NoError(t, err) - assert.Equal(t, float32(51.20179), hum) + require.NoError(t, err) + assert.InDelta(t, float32(51.20179), hum, 0.0) } func TestBME280InitH1Error(t *testing.T) { @@ -92,7 +93,7 @@ func TestBME280InitH1Error(t *testing.T) { return buf.Len(), nil } - assert.ErrorContains(t, bme280.Start(), "h1 read error") + require.ErrorContains(t, bme280.Start(), "h1 read error") } func TestBME280InitH2Error(t *testing.T) { @@ -111,7 +112,7 @@ func TestBME280InitH2Error(t *testing.T) { return buf.Len(), nil } - assert.ErrorContains(t, bme280.Start(), "h2 read error") + require.ErrorContains(t, bme280.Start(), "h2 read error") } func TestBME280HumidityWriteError(t *testing.T) { @@ -122,8 +123,8 @@ func TestBME280HumidityWriteError(t *testing.T) { return 0, errors.New("write error") } hum, err := bme280.Humidity() - assert.ErrorContains(t, err, "write error") - assert.Equal(t, float32(0.0), hum) + require.ErrorContains(t, err, "write error") + assert.InDelta(t, float32(0.0), hum, 0.0) } func TestBME280HumidityReadError(t *testing.T) { @@ -134,8 +135,8 @@ func TestBME280HumidityReadError(t *testing.T) { return 0, errors.New("read error") } hum, err := bme280.Humidity() - assert.ErrorContains(t, err, "read error") - assert.Equal(t, float32(0.0), hum) + require.ErrorContains(t, err, "read error") + assert.InDelta(t, float32(0.0), hum, 0.0) } func TestBME280HumidityNotEnabled(t *testing.T) { @@ -159,8 +160,8 @@ func TestBME280HumidityNotEnabled(t *testing.T) { } _ = bme280.Start() hum, err := bme280.Humidity() - assert.ErrorContains(t, err, "Humidity disabled") - assert.Equal(t, float32(0.0), hum) + require.ErrorContains(t, err, "Humidity disabled") + assert.InDelta(t, float32(0.0), hum, 0.0) } func TestBME280_initializationBME280(t *testing.T) { @@ -186,5 +187,5 @@ func TestBME280_initializationBME280(t *testing.T) { } return 0, nil } - assert.NoError(t, bme280.Start()) + require.NoError(t, bme280.Start()) } diff --git a/drivers/i2c/bmp180_driver_test.go b/drivers/i2c/bmp180_driver_test.go index 39033d9df..e70393718 100644 --- a/drivers/i2c/bmp180_driver_test.go +++ b/drivers/i2c/bmp180_driver_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -72,11 +73,11 @@ func TestBMP180Measurements(t *testing.T) { } _ = bmp180.Start() temp, err := bmp180.Temperature() - assert.NoError(t, err) - assert.Equal(t, float32(15.0), temp) + require.NoError(t, err) + assert.InDelta(t, float32(15.0), temp, 0.0) pressure, err := bmp180.Pressure() - assert.NoError(t, err) - assert.Equal(t, float32(69964), pressure) + require.NoError(t, err) + assert.InDelta(t, float32(69964), pressure, 0.0) } func TestBMP180TemperatureError(t *testing.T) { @@ -108,7 +109,7 @@ func TestBMP180TemperatureError(t *testing.T) { } _ = bmp180.Start() _, err := bmp180.Temperature() - assert.ErrorContains(t, err, "temp error") + require.ErrorContains(t, err, "temp error") } func TestBMP180PressureError(t *testing.T) { @@ -138,7 +139,7 @@ func TestBMP180PressureError(t *testing.T) { } _ = bmp180.Start() _, err := bmp180.Pressure() - assert.ErrorContains(t, err, "press error") + require.ErrorContains(t, err, "press error") } func TestBMP180PressureWriteError(t *testing.T) { @@ -150,7 +151,7 @@ func TestBMP180PressureWriteError(t *testing.T) { } _, err := bmp180.Pressure() - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestBMP180_initialization(t *testing.T) { @@ -183,9 +184,9 @@ func TestBMP180_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(0xAA), a.written[0]) assert.Equal(t, int16(408), d.calCoeffs.ac1) assert.Equal(t, int16(-72), d.calCoeffs.ac2) diff --git a/drivers/i2c/bmp280_driver_test.go b/drivers/i2c/bmp280_driver_test.go index 354e8bae1..04ae5e4d2 100644 --- a/drivers/i2c/bmp280_driver_test.go +++ b/drivers/i2c/bmp280_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -54,7 +55,7 @@ func TestWithBMP280TemperatureOversampling(t *testing.T) { WithBMP280TemperatureOversampling(setVal)(d) // assert assert.Equal(t, setVal, d.ctrlTempOversamp) - assert.Equal(t, 0, len(a.written)) + assert.Empty(t, a.written) } func TestWithBMP280IIRFilter(t *testing.T) { @@ -68,7 +69,7 @@ func TestWithBMP280IIRFilter(t *testing.T) { WithBMP280IIRFilter(setVal)(d) // assert assert.Equal(t, setVal, d.confFilter) - assert.Equal(t, 0, len(a.written)) + assert.Empty(t, a.written) } func TestBMP280Measurements(t *testing.T) { @@ -88,14 +89,14 @@ func TestBMP280Measurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature() - assert.NoError(t, err) - assert.Equal(t, float32(25.014637), temp) + require.NoError(t, err) + assert.InDelta(t, float32(25.014637), temp, 0.0) pressure, err := d.Pressure() - assert.NoError(t, err) - assert.Equal(t, float32(99545.414), pressure) + require.NoError(t, err) + assert.InDelta(t, float32(99545.414), pressure, 0.0) alt, err := d.Altitude() - assert.NoError(t, err) - assert.Equal(t, float32(149.22713), alt) + require.NoError(t, err) + assert.InDelta(t, float32(149.22713), alt, 0.0) } func TestBMP280TemperatureWriteError(t *testing.T) { @@ -106,8 +107,8 @@ func TestBMP280TemperatureWriteError(t *testing.T) { return 0, errors.New("write error") } temp, err := d.Temperature() - assert.ErrorContains(t, err, "write error") - assert.Equal(t, float32(0.0), temp) + require.ErrorContains(t, err, "write error") + assert.InDelta(t, float32(0.0), temp, 0.0) } func TestBMP280TemperatureReadError(t *testing.T) { @@ -118,8 +119,8 @@ func TestBMP280TemperatureReadError(t *testing.T) { return 0, errors.New("read error") } temp, err := d.Temperature() - assert.ErrorContains(t, err, "read error") - assert.Equal(t, float32(0.0), temp) + require.ErrorContains(t, err, "read error") + assert.InDelta(t, float32(0.0), temp, 0.0) } func TestBMP280PressureWriteError(t *testing.T) { @@ -130,8 +131,8 @@ func TestBMP280PressureWriteError(t *testing.T) { return 0, errors.New("write error") } press, err := d.Pressure() - assert.ErrorContains(t, err, "write error") - assert.Equal(t, float32(0.0), press) + require.ErrorContains(t, err, "write error") + assert.InDelta(t, float32(0.0), press, 0.0) } func TestBMP280PressureReadError(t *testing.T) { @@ -142,8 +143,8 @@ func TestBMP280PressureReadError(t *testing.T) { return 0, errors.New("read error") } press, err := d.Pressure() - assert.ErrorContains(t, err, "read error") - assert.Equal(t, float32(0.0), press) + require.ErrorContains(t, err, "read error") + assert.InDelta(t, float32(0.0), press, 0.0) } func TestBMP280_initialization(t *testing.T) { @@ -188,9 +189,9 @@ func TestBMP280_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 5, len(a.written)) + assert.Len(t, a.written, 5) assert.Equal(t, wantCalibReg, a.written[0]) assert.Equal(t, wantCtrlReg, a.written[1]) assert.Equal(t, wantCtrlRegVal, a.written[2]) diff --git a/drivers/i2c/bmp388_driver_test.go b/drivers/i2c/bmp388_driver_test.go index 59d3f224b..ea2b25a14 100644 --- a/drivers/i2c/bmp388_driver_test.go +++ b/drivers/i2c/bmp388_driver_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -84,14 +85,14 @@ func TestBMP388Measurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature(2) - assert.NoError(t, err) - assert.Equal(t, float32(22.906143), temp) + require.NoError(t, err) + assert.InDelta(t, float32(22.906143), temp, 0.0) pressure, err := d.Pressure(2) - assert.NoError(t, err) - assert.Equal(t, float32(98874.85), pressure) + require.NoError(t, err) + assert.InDelta(t, float32(98874.85), pressure, 0.0) alt, err := d.Altitude(2) - assert.NoError(t, err) - assert.Equal(t, float32(205.89395), alt) + require.NoError(t, err) + assert.InDelta(t, float32(205.89395), alt, 0.0) } func TestBMP388TemperatureWriteError(t *testing.T) { @@ -102,8 +103,8 @@ func TestBMP388TemperatureWriteError(t *testing.T) { return 0, errors.New("write error") } temp, err := d.Temperature(2) - assert.ErrorContains(t, err, "write error") - assert.Equal(t, float32(0.0), temp) + require.ErrorContains(t, err, "write error") + assert.InDelta(t, float32(0.0), temp, 0.0) } func TestBMP388TemperatureReadError(t *testing.T) { @@ -114,8 +115,8 @@ func TestBMP388TemperatureReadError(t *testing.T) { return 0, errors.New("read error") } temp, err := d.Temperature(2) - assert.ErrorContains(t, err, "read error") - assert.Equal(t, float32(0.0), temp) + require.ErrorContains(t, err, "read error") + assert.InDelta(t, float32(0.0), temp, 0.0) } func TestBMP388PressureWriteError(t *testing.T) { @@ -126,8 +127,8 @@ func TestBMP388PressureWriteError(t *testing.T) { return 0, errors.New("write error") } press, err := d.Pressure(2) - assert.ErrorContains(t, err, "write error") - assert.Equal(t, float32(0.0), press) + require.ErrorContains(t, err, "write error") + assert.InDelta(t, float32(0.0), press, 0.0) } func TestBMP388PressureReadError(t *testing.T) { @@ -138,8 +139,8 @@ func TestBMP388PressureReadError(t *testing.T) { return 0, errors.New("read error") } press, err := d.Pressure(2) - assert.ErrorContains(t, err, "read error") - assert.Equal(t, float32(0.0), press) + require.ErrorContains(t, err, "read error") + assert.InDelta(t, float32(0.0), press, 0.0) } func TestBMP388_initialization(t *testing.T) { @@ -176,25 +177,25 @@ func TestBMP388_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, 6, len(a.written)) + assert.Len(t, a.written, 6) assert.Equal(t, wantChipIDReg, a.written[0]) assert.Equal(t, wantCalibReg, a.written[1]) assert.Equal(t, wantCommandReg, a.written[2]) assert.Equal(t, wantCommandRegVal, a.written[3]) assert.Equal(t, wantConfReg, a.written[4]) assert.Equal(t, wantConfRegVal, a.written[5]) - assert.Equal(t, float32(7.021568e+06), d.calCoeffs.t1) - assert.Equal(t, float32(1.7549843e-05), d.calCoeffs.t2) - assert.Equal(t, float32(-3.5527137e-14), d.calCoeffs.t3) - assert.Equal(t, float32(-0.015769958), d.calCoeffs.p1) - assert.Equal(t, float32(-3.5410747e-05), d.calCoeffs.p2) - assert.Equal(t, float32(8.1490725e-09), d.calCoeffs.p3) - assert.Equal(t, float32(0), d.calCoeffs.p4) - assert.Equal(t, float32(208056), d.calCoeffs.p5) - assert.Equal(t, float32(490.875), d.calCoeffs.p6) - assert.Equal(t, float32(-0.05078125), d.calCoeffs.p7) - assert.Equal(t, float32(-0.00030517578), d.calCoeffs.p8) - assert.Equal(t, float32(5.8957283e-11), d.calCoeffs.p9) + assert.InDelta(t, float32(7.021568e+06), d.calCoeffs.t1, 0.0) + assert.InDelta(t, float32(1.7549843e-05), d.calCoeffs.t2, 0.0) + assert.InDelta(t, float32(-3.5527137e-14), d.calCoeffs.t3, 0.0) + assert.InDelta(t, float32(-0.015769958), d.calCoeffs.p1, 0.0) + assert.InDelta(t, float32(-3.5410747e-05), d.calCoeffs.p2, 0.0) + assert.InDelta(t, float32(8.1490725e-09), d.calCoeffs.p3, 0.0) + assert.InDelta(t, float32(0), d.calCoeffs.p4, 0.0) + assert.InDelta(t, float32(208056), d.calCoeffs.p5, 0.0) + assert.InDelta(t, float32(490.875), d.calCoeffs.p6, 0.0) + assert.InDelta(t, float32(-0.05078125), d.calCoeffs.p7, 0.0) + assert.InDelta(t, float32(-0.00030517578), d.calCoeffs.p8, 0.0) + assert.InDelta(t, float32(5.8957283e-11), d.calCoeffs.p9, 0.0) } diff --git a/drivers/i2c/ccs811_driver_test.go b/drivers/i2c/ccs811_driver_test.go index b28a554d5..f8abcb746 100644 --- a/drivers/i2c/ccs811_driver_test.go +++ b/drivers/i2c/ccs811_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -148,7 +149,7 @@ func TestCCS811GetTemperature(t *testing.T) { // act temp, err := d.GetTemperature() // assert - assert.Equal(t, tc.temp, temp) + assert.InDelta(t, tc.temp, temp, 0.0) assert.Equal(t, tc.err, err) }) } @@ -255,9 +256,9 @@ func TestCCS811_initialize(t *testing.T) { // arrange, act - initialize() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 9, len(a.written)) + assert.Len(t, a.written, 9) assert.Equal(t, wantChipIDReg, a.written[0]) assert.Equal(t, wantResetReg, a.written[1]) assert.Equal(t, wantResetRegSequence, a.written[2:6]) diff --git a/drivers/i2c/drv2605l_driver_test.go b/drivers/i2c/drv2605l_driver_test.go index 6ec3bda11..e8295db7b 100644 --- a/drivers/i2c/drv2605l_driver_test.go +++ b/drivers/i2c/drv2605l_driver_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -51,7 +52,7 @@ func TestDRV2605LOptions(t *testing.T) { func TestDRV2605LStart(t *testing.T) { d := NewDRV2605LDriver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestDRV2605LHalt(t *testing.T) { @@ -62,7 +63,7 @@ func TestDRV2605LHalt(t *testing.T) { writeNewStandbyModeData := []byte{drv2605RegMode, 42 | drv2605Standby} d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) assert.Equal(t, append(append(writeStopPlaybackData, readCurrentStandbyModeData), writeNewStandbyModeData...), a.written) } @@ -76,7 +77,7 @@ func TestDRV2605LGetPause(t *testing.T) { func TestDRV2605LSequenceTermination(t *testing.T) { d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - assert.NoError(t, d.SetSequence([]byte{1, 2})) + require.NoError(t, d.SetSequence([]byte{1, 2})) assert.Equal(t, []byte{ drv2605RegWaveSeq1, 1, drv2605RegWaveSeq2, 2, @@ -87,7 +88,7 @@ func TestDRV2605LSequenceTermination(t *testing.T) { func TestDRV2605LSequenceTruncation(t *testing.T) { d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} - assert.NoError(t, d.SetSequence([]byte{1, 2, 3, 4, 5, 6, 7, 8, 99, 100})) + require.NoError(t, d.SetSequence([]byte{1, 2, 3, 4, 5, 6, 7, 8, 99, 100})) assert.Equal(t, []byte{ drv2605RegWaveSeq1, 1, drv2605RegWaveSeq2, 2, @@ -102,7 +103,7 @@ func TestDRV2605LSequenceTruncation(t *testing.T) { func TestDRV2605LSetMode(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - assert.NoError(t, d.SetMode(DRV2605ModeIntTrig)) + require.NoError(t, d.SetMode(DRV2605ModeIntTrig)) } func TestDRV2605LSetModeReadError(t *testing.T) { @@ -110,12 +111,12 @@ func TestDRV2605LSetModeReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - assert.ErrorContains(t, d.SetMode(DRV2605ModeIntTrig), "read error") + require.ErrorContains(t, d.SetMode(DRV2605ModeIntTrig), "read error") } func TestDRV2605LSetStandbyMode(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - assert.NoError(t, d.SetStandbyMode(true)) + require.NoError(t, d.SetStandbyMode(true)) } func TestDRV2605LSetStandbyModeReadError(t *testing.T) { @@ -123,15 +124,15 @@ func TestDRV2605LSetStandbyModeReadError(t *testing.T) { a.i2cReadImpl = func(b []byte) (int, error) { return 0, errors.New("read error") } - assert.ErrorContains(t, d.SetStandbyMode(true), "read error") + require.ErrorContains(t, d.SetStandbyMode(true), "read error") } func TestDRV2605LSelectLibrary(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - assert.NoError(t, d.SelectLibrary(1)) + require.NoError(t, d.SelectLibrary(1)) } func TestDRV2605LGo(t *testing.T) { d, _ := initTestDRV2605LDriverWithStubbedAdaptor() - assert.NoError(t, d.Go()) + require.NoError(t, d.Go()) } diff --git a/drivers/i2c/grovepi_driver_test.go b/drivers/i2c/grovepi_driver_test.go index d50abc707..cd6ed5682 100644 --- a/drivers/i2c/grovepi_driver_test.go +++ b/drivers/i2c/grovepi_driver_test.go @@ -2,10 +2,12 @@ package i2c import ( "fmt" + "strconv" "strings" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" @@ -152,15 +154,15 @@ func TestGrovePiSomeRead(t *testing.T) { // act switch { case strings.Contains(name, "DigitalRead"): - got, err = g.DigitalRead(fmt.Sprintf("%d", tc.usedPin)) + got, err = g.DigitalRead(strconv.Itoa(tc.usedPin)) case strings.Contains(name, "AnalogRead"): - got, err = g.AnalogRead(fmt.Sprintf("%d", tc.usedPin)) + got, err = g.AnalogRead(strconv.Itoa(tc.usedPin)) case strings.Contains(name, "UltrasonicRead"): - got, err = g.UltrasonicRead(fmt.Sprintf("%d", tc.usedPin), 2) + got, err = g.UltrasonicRead(strconv.Itoa(tc.usedPin), 2) case strings.Contains(name, "FirmwareVersionRead"): gotString, err = g.FirmwareVersionRead() case strings.Contains(name, "DHTRead"): - gotF1, gotF2, err = g.DHTRead(fmt.Sprintf("%d", tc.usedPin), 1, 2) + gotF1, gotF2, err = g.DHTRead(strconv.Itoa(tc.usedPin), 1, 2) default: t.Errorf("unknown command %s", name) return @@ -168,10 +170,10 @@ func TestGrovePiSomeRead(t *testing.T) { // assert assert.Equal(t, tc.wantErr, err) assert.Equal(t, tc.wantWritten, a.written) - assert.Equal(t, len(tc.simResponse), numCallsRead) + assert.Len(t, tc.simResponse, numCallsRead) assert.Equal(t, tc.wantResult, got) - assert.Equal(t, tc.wantResultF1, gotF1) - assert.Equal(t, tc.wantResultF2, gotF2) + assert.InDelta(t, tc.wantResultF1, gotF1, 0.0) + assert.InDelta(t, tc.wantResultF2, gotF2, 0.0) assert.Equal(t, tc.wantResultString, gotString) }) } @@ -211,15 +213,15 @@ func TestGrovePiSomeWrite(t *testing.T) { // act switch name { case "DigitalWrite": - err = g.DigitalWrite(fmt.Sprintf("%d", tc.usedPin), byte(tc.usedValue)) + err = g.DigitalWrite(strconv.Itoa(tc.usedPin), byte(tc.usedValue)) case "AnalogWrite": - err = g.AnalogWrite(fmt.Sprintf("%d", tc.usedPin), tc.usedValue) + err = g.AnalogWrite(strconv.Itoa(tc.usedPin), tc.usedValue) default: t.Errorf("unknown command %s", name) return } // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.wantWritten, a.written) }) } diff --git a/drivers/i2c/hmc5883l_driver_test.go b/drivers/i2c/hmc5883l_driver_test.go index 9af18c1c7..b62ce07d8 100644 --- a/drivers/i2c/hmc5883l_driver_test.go +++ b/drivers/i2c/hmc5883l_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -30,7 +31,7 @@ func TestNewHMC5883LDriver(t *testing.T) { assert.Equal(t, uint32(15000), d.outputRate) assert.Equal(t, int8(0), d.applyBias) assert.Equal(t, 0, d.measurementMode) - assert.Equal(t, 390.0, d.gain) + assert.InDelta(t, 390.0, d.gain, 0.0) } func TestHMC5883LOptions(t *testing.T) { @@ -56,7 +57,7 @@ func TestHMC5883LWithHMC5883LApplyBias(t *testing.T) { func TestHMC5883LWithHMC5883LGain(t *testing.T) { d := NewHMC5883LDriver(newI2cTestAdaptor()) WithHMC5883LGain(230)(d) - assert.Equal(t, 230.0, d.gain) + assert.InDelta(t, 230.0, d.gain, 0.0) } func TestHMC5883LRead(t *testing.T) { @@ -121,10 +122,10 @@ func TestHMC5883LRead(t *testing.T) { // act gotX, gotY, gotZ, err := d.Read() // assert - assert.NoError(t, err) - assert.Equal(t, tc.wantX, gotX) - assert.Equal(t, tc.wantY, gotY) - assert.Equal(t, tc.wantZ, gotZ) + require.NoError(t, err) + assert.InDelta(t, tc.wantX, gotX, 0.0) + assert.InDelta(t, tc.wantY, gotY, 0.0) + assert.InDelta(t, tc.wantZ, gotZ, 0.0) }) } } @@ -177,12 +178,12 @@ func TestHMC5883L_readRawData(t *testing.T) { // act gotX, gotY, gotZ, err := d.readRawData() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.wantX, gotX) assert.Equal(t, tc.wantY, gotY) assert.Equal(t, tc.wantZ, gotZ) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(hmc5883lAxisX), a.written[0]) }) } @@ -203,8 +204,8 @@ func TestHMC5883L_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) - assert.Equal(t, 6, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 6) assert.Equal(t, uint8(hmc5883lRegA), a.written[0]) assert.Equal(t, wantRegA, a.written[1]) assert.Equal(t, uint8(hmc5883lRegB), a.written[2]) diff --git a/drivers/i2c/hmc6352_driver_test.go b/drivers/i2c/hmc6352_driver_test.go index 7061a905a..908fb422b 100644 --- a/drivers/i2c/hmc6352_driver_test.go +++ b/drivers/i2c/hmc6352_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -42,12 +43,12 @@ func TestHMC6352Options(t *testing.T) { func TestHMC6352Start(t *testing.T) { d := NewHMC6352Driver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestHMC6352Halt(t *testing.T) { d, _ := initTestHMC6352DriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestHMC6352Heading(t *testing.T) { @@ -80,7 +81,7 @@ func TestHMC6352Heading(t *testing.T) { heading, err = d.Heading() assert.Equal(t, uint16(0), heading) - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") // when write error d, a = initTestHMC6352DriverWithStubbedAdaptor() @@ -90,5 +91,5 @@ func TestHMC6352Heading(t *testing.T) { heading, err = d.Heading() assert.Equal(t, uint16(0), heading) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index 92d075a57..d4ee56cc6 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -8,6 +8,7 @@ import ( "unsafe" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) @@ -77,7 +78,7 @@ func TestI2CAddress(t *testing.T) { func TestI2CClose(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) - assert.NoError(t, c.Close()) + require.NoError(t, c.Close()) } func TestI2CRead(t *testing.T) { @@ -89,7 +90,7 @@ func TestI2CRead(t *testing.T) { func TestI2CReadAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.Read([]byte{}) - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWrite(t *testing.T) { @@ -101,7 +102,7 @@ func TestI2CWrite(t *testing.T) { func TestI2CWriteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.Write([]byte{0x01}) - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadByte(t *testing.T) { @@ -113,7 +114,7 @@ func TestI2CReadByte(t *testing.T) { func TestI2CReadByteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadByte() - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadByteData(t *testing.T) { @@ -125,7 +126,7 @@ func TestI2CReadByteData(t *testing.T) { func TestI2CReadByteDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadByteData(0x01) - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CReadWordData(t *testing.T) { @@ -137,65 +138,65 @@ func TestI2CReadWordData(t *testing.T) { func TestI2CReadWordDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) _, err := c.ReadWordData(0x01) - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteByte(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteByte(0x01) - assert.NoError(t, err) + require.NoError(t, err) } func TestI2CWriteByteAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteByte(0x01) - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteByteData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteByteData(0x01, 0x01) - assert.NoError(t, err) + require.NoError(t, err) } func TestI2CWriteByteDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteByteData(0x01, 0x01) - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteWordData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteWordData(0x01, 0x01) - assert.NoError(t, err) + require.NoError(t, err) } func TestI2CWriteWordDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteWordData(0x01, 0x01) - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func TestI2CWriteBlockData(t *testing.T) { c := NewConnection(initI2CDevice(), 0x06) err := c.WriteBlockData(0x01, []byte{0x01, 0x02}) - assert.NoError(t, err) + require.NoError(t, err) } func TestI2CWriteBlockDataAddressError(t *testing.T) { c := NewConnection(initI2CDeviceAddressError(), 0x06) err := c.WriteBlockData(0x01, []byte{0x01, 0x02}) - assert.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") + require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } func Test_setBit(t *testing.T) { - var expectedVal uint8 = 129 - actualVal := setBit(1, 7) - assert.Equal(t, actualVal, expectedVal) + var wantVal uint8 = 129 + gotVal := setBit(1, 7) + assert.Equal(t, wantVal, gotVal) } func Test_clearBit(t *testing.T) { - var expectedVal uint8 - actualVal := clearBit(128, 7) - assert.Equal(t, actualVal, expectedVal) + var wantVal uint8 + gotVal := clearBit(128, 7) + assert.Equal(t, wantVal, gotVal) } diff --git a/drivers/i2c/i2c_driver_test.go b/drivers/i2c/i2c_driver_test.go index dd1addc2f..9dec4cecd 100644 --- a/drivers/i2c/i2c_driver_test.go +++ b/drivers/i2c/i2c_driver_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -34,8 +35,8 @@ func TestNewDriver(t *testing.T) { assert.Equal(t, 0x15, d.defaultAddress) assert.Equal(t, a, d.connector) assert.Nil(t, d.connection) - assert.NoError(t, d.afterStart()) - assert.NoError(t, d.beforeHalt()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Config) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) @@ -61,8 +62,8 @@ func TestStart(t *testing.T) { // arrange d, a := initDriverWithStubbedAdaptor() // act, assert - assert.NoError(t, d.Start()) - assert.Equal(t, a.address, 0x15) + require.NoError(t, d.Start()) + assert.Equal(t, 0x15, a.address) } func TestStartConnectError(t *testing.T) { @@ -70,14 +71,14 @@ func TestStartConnectError(t *testing.T) { d, a := initDriverWithStubbedAdaptor() a.Testi2cConnectErr(true) // act, assert - assert.ErrorContains(t, d.Start(), "Invalid i2c connection") + require.ErrorContains(t, d.Start(), "Invalid i2c connection") } func TestHalt(t *testing.T) { // arrange d := initTestDriver() // act, assert - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestWrite(t *testing.T) { @@ -98,7 +99,7 @@ func TestWrite(t *testing.T) { // act err := d.Write(address, value) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, wantAddress, a.written[0]) assert.Equal(t, uint8(value), a.written[1]) @@ -129,7 +130,7 @@ func TestRead(t *testing.T) { // act val, err := d.Read(address) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int(want), val) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, wantAddress, a.written[0]) diff --git a/drivers/i2c/ina3221_driver_test.go b/drivers/i2c/ina3221_driver_test.go index ae044fc9d..51cee46e9 100644 --- a/drivers/i2c/ina3221_driver_test.go +++ b/drivers/i2c/ina3221_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -42,12 +43,12 @@ func TestINA3221Options(t *testing.T) { func TestINA3221Start(t *testing.T) { d := NewINA3221Driver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestINA3221Halt(t *testing.T) { d, _ := initTestINA3221DriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestINA3221GetBusVoltage(t *testing.T) { @@ -59,8 +60,8 @@ func TestINA3221GetBusVoltage(t *testing.T) { } v, err := d.GetBusVoltage(INA3221Channel1) - assert.Equal(t, float64(13.928), v) - assert.NoError(t, err) + assert.InDelta(t, float64(13.928), v, 0.0) + require.NoError(t, err) } func TestINA3221GetBusVoltageReadError(t *testing.T) { @@ -70,7 +71,7 @@ func TestINA3221GetBusVoltageReadError(t *testing.T) { } _, err := d.GetBusVoltage(INA3221Channel1) - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestINA3221GetShuntVoltage(t *testing.T) { @@ -82,8 +83,8 @@ func TestINA3221GetShuntVoltage(t *testing.T) { } v, err := d.GetShuntVoltage(INA3221Channel1) - assert.Equal(t, float64(7.48), v) - assert.NoError(t, err) + assert.InDelta(t, float64(7.48), v, 0.0) + require.NoError(t, err) } func TestINA3221GetShuntVoltageReadError(t *testing.T) { @@ -93,7 +94,7 @@ func TestINA3221GetShuntVoltageReadError(t *testing.T) { } _, err := d.GetShuntVoltage(INA3221Channel1) - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestINA3221GetCurrent(t *testing.T) { @@ -105,8 +106,8 @@ func TestINA3221GetCurrent(t *testing.T) { } v, err := d.GetCurrent(INA3221Channel1) - assert.Equal(t, float64(74.8), v) - assert.NoError(t, err) + assert.InDelta(t, float64(74.8), v, 0.0) + require.NoError(t, err) } func TestINA3221CurrentReadError(t *testing.T) { @@ -116,7 +117,7 @@ func TestINA3221CurrentReadError(t *testing.T) { } _, err := d.GetCurrent(INA3221Channel1) - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestINA3221GetLoadVoltage(t *testing.T) { @@ -130,8 +131,8 @@ func TestINA3221GetLoadVoltage(t *testing.T) { } v, err := d.GetLoadVoltage(INA3221Channel2) - assert.Equal(t, float64(13.935480), v) - assert.NoError(t, err) + assert.InDelta(t, float64(13.935480), v, 0.0) + require.NoError(t, err) } func TestINA3221GetLoadVoltageReadError(t *testing.T) { @@ -141,5 +142,5 @@ func TestINA3221GetLoadVoltageReadError(t *testing.T) { } _, err := d.GetLoadVoltage(INA3221Channel2) - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } diff --git a/drivers/i2c/jhd1313m1_driver_test.go b/drivers/i2c/jhd1313m1_driver_test.go index f89efadbc..94ec4fbab 100644 --- a/drivers/i2c/jhd1313m1_driver_test.go +++ b/drivers/i2c/jhd1313m1_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -54,13 +55,13 @@ func TestJHD1313MDriverOptions(t *testing.T) { func TestJHD1313MDriverStart(t *testing.T) { d := initTestJHD1313M1Driver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestJHD1313MStartConnectError(t *testing.T) { d, adaptor := initTestJHD1313M1DriverWithStubbedAdaptor() adaptor.Testi2cConnectErr(true) - assert.ErrorContains(t, d.Start(), "Invalid i2c connection") + require.ErrorContains(t, d.Start(), "Invalid i2c connection") } func TestJHD1313MDriverStartWriteError(t *testing.T) { @@ -68,19 +69,19 @@ func TestJHD1313MDriverStartWriteError(t *testing.T) { adaptor.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.Start(), "write error") + require.ErrorContains(t, d.Start(), "write error") } func TestJHD1313MDriverHalt(t *testing.T) { d := initTestJHD1313M1Driver() _ = d.Start() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestJHD1313MDriverSetRgb(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.SetRGB(0x00, 0x00, 0x00)) + require.NoError(t, d.SetRGB(0x00, 0x00, 0x00)) } func TestJHD1313MDriverSetRgbError(t *testing.T) { @@ -90,13 +91,13 @@ func TestJHD1313MDriverSetRgbError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.SetRGB(0x00, 0x00, 0x00), "write error") + require.ErrorContains(t, d.SetRGB(0x00, 0x00, 0x00), "write error") } func TestJHD1313MDriverClear(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Clear()) + require.NoError(t, d.Clear()) } func TestJHD1313MDriverClearError(t *testing.T) { @@ -106,19 +107,19 @@ func TestJHD1313MDriverClearError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.Clear(), "write error") + require.ErrorContains(t, d.Clear(), "write error") } func TestJHD1313MDriverHome(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Home()) + require.NoError(t, d.Home()) } func TestJHD1313MDriverWrite(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Write("Hello")) + require.NoError(t, d.Write("Hello")) } func TestJHD1313MDriverWriteError(t *testing.T) { @@ -128,13 +129,13 @@ func TestJHD1313MDriverWriteError(t *testing.T) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.Write("Hello"), "write error") + require.ErrorContains(t, d.Write("Hello"), "write error") } func TestJHD1313MDriverWriteTwoLines(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Write("Hello\nthere")) + require.NoError(t, d.Write("Hello\nthere")) } func TestJHD1313MDriverWriteTwoLinesError(t *testing.T) { @@ -144,19 +145,19 @@ func TestJHD1313MDriverWriteTwoLinesError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.Write("Hello\nthere"), "write error") + require.ErrorContains(t, d.Write("Hello\nthere"), "write error") } func TestJHD1313MDriverSetPosition(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.SetPosition(2)) + require.NoError(t, d.SetPosition(2)) } func TestJHD1313MDriverSetSecondLinePosition(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.SetPosition(18)) + require.NoError(t, d.SetPosition(18)) } func TestJHD1313MDriverSetPositionInvalid(t *testing.T) { @@ -169,27 +170,27 @@ func TestJHD1313MDriverSetPositionInvalid(t *testing.T) { func TestJHD1313MDriverScroll(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Scroll(true)) + require.NoError(t, d.Scroll(true)) } func TestJHD1313MDriverReverseScroll(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() _ = d.Start() - assert.NoError(t, d.Scroll(false)) + require.NoError(t, d.Scroll(false)) } func TestJHD1313MDriverSetCustomChar(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} _ = d.Start() - assert.NoError(t, d.SetCustomChar(0, data)) + require.NoError(t, d.SetCustomChar(0, data)) } func TestJHD1313MDriverSetCustomCharError(t *testing.T) { d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} _ = d.Start() - assert.ErrorContains(t, d.SetCustomChar(10, data), "can't set a custom character at a position greater than 7") + require.ErrorContains(t, d.SetCustomChar(10, data), "can't set a custom character at a position greater than 7") } func TestJHD1313MDriverSetCustomCharWriteError(t *testing.T) { @@ -200,7 +201,7 @@ func TestJHD1313MDriverSetCustomCharWriteError(t *testing.T) { return 0, errors.New("write error") } data := [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - assert.ErrorContains(t, d.SetCustomChar(0, data), "write error") + require.ErrorContains(t, d.SetCustomChar(0, data), "write error") } func TestJHD1313MDriverCommands(t *testing.T) { diff --git a/drivers/i2c/l3gd20h_driver_test.go b/drivers/i2c/l3gd20h_driver_test.go index 9e1bf43f8..caeccf94f 100644 --- a/drivers/i2c/l3gd20h_driver_test.go +++ b/drivers/i2c/l3gd20h_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -130,8 +131,8 @@ func TestL3GD20HFullScaleRange(t *testing.T) { // act got, err := d.FullScaleRange() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(0x23), a.written[0]) assert.Equal(t, readValue, got) } @@ -196,12 +197,12 @@ func TestL3GD20HMeasurement(t *testing.T) { // act x, y, z, err := d.XYZ() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(0xA8), a.written[0]) - assert.Equal(t, tc.wantX, x) - assert.Equal(t, tc.wantY, y) - assert.Equal(t, tc.wantZ, z) + assert.InDelta(t, tc.wantX, x, 0.0) + assert.InDelta(t, tc.wantY, y, 0.0) + assert.InDelta(t, tc.wantZ, z, 0.0) }) } } @@ -214,7 +215,7 @@ func TestL3GD20HMeasurementError(t *testing.T) { _ = d.Start() _, _, _, err := d.XYZ() - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestL3GD20HMeasurementWriteError(t *testing.T) { @@ -223,7 +224,7 @@ func TestL3GD20HMeasurementWriteError(t *testing.T) { return 0, errors.New("write error") } _, _, _, err := d.XYZ() - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestL3GD20H_initialize(t *testing.T) { @@ -250,7 +251,7 @@ func TestL3GD20H_initialize(t *testing.T) { // arrange, act - initialize() must be called on Start() _, a := initL3GD20HWithStubbedAdaptor() // assert - assert.Equal(t, 6, len(a.written)) + assert.Len(t, a.written, 6) assert.Equal(t, uint8(0x20), a.written[0]) assert.Equal(t, uint8(0x00), a.written[1]) assert.Equal(t, uint8(0x20), a.written[2]) diff --git a/drivers/i2c/lidarlite_driver_test.go b/drivers/i2c/lidarlite_driver_test.go index ecae4a6ab..6b9a12376 100644 --- a/drivers/i2c/lidarlite_driver_test.go +++ b/drivers/i2c/lidarlite_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -48,12 +49,12 @@ func TestLIDARLiteDriverOptions(t *testing.T) { func TestLIDARLiteDriverStart(t *testing.T) { d := NewLIDARLiteDriver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestLIDARLiteDriverHalt(t *testing.T) { d := initTestLIDARLiteDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestLIDARLiteDriverDistance(t *testing.T) { @@ -72,7 +73,7 @@ func TestLIDARLiteDriverDistance(t *testing.T) { distance, err := d.Distance() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int(25345), distance) // when insufficient bytes have been read @@ -93,7 +94,7 @@ func TestLIDARLiteDriverDistance(t *testing.T) { distance, err = d.Distance() assert.Equal(t, int(0), distance) - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestLIDARLiteDriverDistanceError1(t *testing.T) { @@ -104,7 +105,7 @@ func TestLIDARLiteDriverDistanceError1(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestLIDARLiteDriverDistanceError2(t *testing.T) { @@ -118,7 +119,7 @@ func TestLIDARLiteDriverDistanceError2(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestLIDARLiteDriverDistanceError3(t *testing.T) { @@ -138,5 +139,5 @@ func TestLIDARLiteDriverDistanceError3(t *testing.T) { distance, err := d.Distance() assert.Equal(t, int(0), distance) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index f05139c6a..544d2f897 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -147,8 +148,8 @@ func TestMCP23017WriteGPIO(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - assert.NoError(t, err) - assert.Equal(t, 6, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 6) assert.Equal(t, wantReg1, a.written[0]) assert.Equal(t, wantReg1, a.written[1]) assert.Equal(t, wantReg1Val, a.written[2]) @@ -186,8 +187,8 @@ func TestMCP23017WriteGPIONoRefresh(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - assert.NoError(t, err) - assert.Equal(t, 2, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 2) assert.Equal(t, wantReg1, a.written[0]) assert.Equal(t, wantReg2, a.written[1]) assert.Equal(t, 2, numCallsRead) @@ -223,8 +224,8 @@ func TestMCP23017WriteGPIONoAutoDir(t *testing.T) { // act err := d.WriteGPIO(testPin, testPort, uint8(bitState)) // assert - assert.NoError(t, err) - assert.Equal(t, 3, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 3) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantReg, a.written[1]) assert.Equal(t, wantRegVal, a.written[2]) @@ -241,7 +242,7 @@ func TestMCP23017CommandsWriteGPIOErrIODIR(t *testing.T) { // act err := d.WriteGPIO(7, "A", 0) // assert - assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") + require.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") } func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { @@ -258,7 +259,7 @@ func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { // act err := d.WriteGPIO(7, "A", 0) // assert - assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=20): write error") + require.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=20): write error") } func TestMCP23017ReadGPIO(t *testing.T) { @@ -290,9 +291,9 @@ func TestMCP23017ReadGPIO(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, 4, len(a.written)) + assert.Len(t, a.written, 4) assert.Equal(t, wantReg1, a.written[0]) assert.Equal(t, wantReg1, a.written[1]) assert.Equal(t, wantReg1Val, a.written[2]) @@ -328,9 +329,9 @@ func TestMCP23017ReadGPIONoRefresh(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, 2, len(a.written)) + assert.Len(t, a.written, 2) assert.Equal(t, wantReg1, a.written[0]) assert.Equal(t, wantReg2, a.written[1]) assert.Equal(t, uint8(bitState), val) @@ -363,9 +364,9 @@ func TestMCP23017ReadGPIONoAutoDir(t *testing.T) { // act val, err := d.ReadGPIO(testPin, testPort) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, wantReg2, a.written[0]) assert.Equal(t, uint8(bitState), val) } @@ -381,7 +382,7 @@ func TestMCP23017ReadGPIOErr(t *testing.T) { // act _, err := d.ReadGPIO(7, "A") // assert - assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): read error") + require.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): read error") } func TestMCP23017SetPinMode(t *testing.T) { @@ -413,8 +414,8 @@ func TestMCP23017SetPinMode(t *testing.T) { // act err := d.SetPinMode(testPin, testPort, uint8(bitState)) // assert - assert.NoError(t, err) - assert.Equal(t, 3, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 3) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantReg, a.written[1]) assert.Equal(t, wantRegVal, a.written[2]) @@ -431,7 +432,7 @@ func TestMCP23017SetPinModeErr(t *testing.T) { // act err := d.SetPinMode(7, "A", 0) // assert - assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") + require.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=0): write error") } func TestMCP23017SetPullUp(t *testing.T) { @@ -463,8 +464,8 @@ func TestMCP23017SetPullUp(t *testing.T) { // act err := d.SetPullUp(testPin, testPort, uint8(bitState)) // assert - assert.NoError(t, err) - assert.Equal(t, 3, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 3) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantReg, a.written[1]) assert.Equal(t, wantSetVal, a.written[2]) @@ -481,7 +482,7 @@ func TestMCP23017SetPullUpErr(t *testing.T) { // act err := d.SetPullUp(7, "A", 0) // assert - assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=12): write error") + require.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=12): write error") } func TestMCP23017SetGPIOPolarity(t *testing.T) { @@ -513,8 +514,8 @@ func TestMCP23017SetGPIOPolarity(t *testing.T) { // act err := d.SetGPIOPolarity(testPin, testPort, uint8(bitState)) // assert - assert.NoError(t, err) - assert.Equal(t, 3, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 3) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, wantReg, a.written[1]) assert.Equal(t, wantSetVal, a.written[2]) @@ -531,7 +532,7 @@ func TestMCP23017SetGPIOPolarityErr(t *testing.T) { // act err := d.SetGPIOPolarity(7, "A", 0) // assert - assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=2): write error") + require.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=2): write error") } func TestMCP23017_write(t *testing.T) { @@ -539,13 +540,13 @@ func TestMCP23017_write(t *testing.T) { d, _ := initTestMCP23017WithStubbedAdaptor(0) port := d.getPort("A") err := d.write(port.IODIR, uint8(7), 0) - assert.NoError(t, err) + require.NoError(t, err) // set bit d, _ = initTestMCP23017WithStubbedAdaptor(0) port = d.getPort("B") err = d.write(port.IODIR, uint8(7), 1) - assert.NoError(t, err) + require.NoError(t, err) // write error d, a := initTestMCP23017WithStubbedAdaptor(0) @@ -553,7 +554,7 @@ func TestMCP23017_write(t *testing.T) { return 0, errors.New("write error") } err = d.write(port.IODIR, uint8(7), 0) - assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): write error") + require.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): write error") // read error d, a = initTestMCP23017WithStubbedAdaptor(0) @@ -561,12 +562,12 @@ func TestMCP23017_write(t *testing.T) { return len(b), errors.New("read error") } err = d.write(port.IODIR, uint8(7), 0) - assert.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): read error") + require.ErrorContains(t, err, "MCP write-read: MCP write-ReadByteData(reg=1): read error") a.i2cReadImpl = func(b []byte) (int, error) { return len(b), nil } err = d.write(port.IODIR, uint8(7), 1) - assert.NoError(t, err) + require.NoError(t, err) } func TestMCP23017_read(t *testing.T) { @@ -588,7 +589,7 @@ func TestMCP23017_read(t *testing.T) { val, err := d.read(port.IODIR) assert.Equal(t, uint8(0), val) - assert.ErrorContains(t, err, "MCP write-ReadByteData(reg=0): read error") + require.ErrorContains(t, err, "MCP write-ReadByteData(reg=0): read error") // read d, a = initTestMCP23017WithStubbedAdaptor(0) @@ -604,25 +605,25 @@ func TestMCP23017_read(t *testing.T) { func TestMCP23017_getPort(t *testing.T) { // port A d := initTestMCP23017(0) - expectedPort := mcp23017GetBank(0).portA - actualPort := d.getPort("A") - assert.Equal(t, actualPort, expectedPort) + wantPort := mcp23017GetBank(0).portA + gotPort := d.getPort("A") + assert.Equal(t, wantPort, gotPort) // port B d = initTestMCP23017(0) - expectedPort = mcp23017GetBank(0).portB - actualPort = d.getPort("B") - assert.Equal(t, actualPort, expectedPort) + wantPort = mcp23017GetBank(0).portB + gotPort = d.getPort("B") + assert.Equal(t, wantPort, gotPort) // default d = initTestMCP23017(0) - expectedPort = mcp23017GetBank(0).portA - actualPort = d.getPort("") - assert.Equal(t, actualPort, expectedPort) + wantPort = mcp23017GetBank(0).portA + gotPort = d.getPort("") + assert.Equal(t, wantPort, gotPort) // port A bank 1 d = initTestMCP23017(1) - expectedPort = mcp23017GetBank(1).portA - actualPort = d.getPort("") - assert.Equal(t, actualPort, expectedPort) + wantPort = mcp23017GetBank(1).portA + gotPort = d.getPort("") + assert.Equal(t, wantPort, gotPort) } diff --git a/drivers/i2c/mma7660_driver_test.go b/drivers/i2c/mma7660_driver_test.go index 9f6e4b537..a736f1ff8 100644 --- a/drivers/i2c/mma7660_driver_test.go +++ b/drivers/i2c/mma7660_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -43,29 +44,29 @@ func TestMMA7660Options(t *testing.T) { func TestMMA7660Start(t *testing.T) { d := NewMMA7660Driver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestMMA7660Halt(t *testing.T) { d, _ := initTestMMA7660DriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestMMA7660Acceleration(t *testing.T) { d, _ := initTestMMA7660DriverWithStubbedAdaptor() x, y, z := d.Acceleration(21.0, 21.0, 21.0) - assert.Equal(t, 1.0, x) - assert.Equal(t, 1.0, y) - assert.Equal(t, 1.0, z) + assert.InDelta(t, 1.0, x, 0.0) + assert.InDelta(t, 1.0, y, 0.0) + assert.InDelta(t, 1.0, z, 0.0) } func TestMMA7660NullXYZ(t *testing.T) { d, _ := initTestMMA7660DriverWithStubbedAdaptor() x, y, z, _ := d.XYZ() - assert.Equal(t, 0.0, x) - assert.Equal(t, 0.0, y) - assert.Equal(t, 0.0, z) + assert.InDelta(t, 0.0, x, 0.0) + assert.InDelta(t, 0.0, y, 0.0) + assert.InDelta(t, 0.0, z, 0.0) } func TestMMA7660XYZ(t *testing.T) { @@ -78,9 +79,9 @@ func TestMMA7660XYZ(t *testing.T) { } x, y, z, _ := d.XYZ() - assert.Equal(t, 17.0, x) - assert.Equal(t, 18.0, y) - assert.Equal(t, 19.0, z) + assert.InDelta(t, 17.0, x, 0.0) + assert.InDelta(t, 18.0, y, 0.0) + assert.InDelta(t, 19.0, z, 0.0) } func TestMMA7660XYZError(t *testing.T) { @@ -90,7 +91,7 @@ func TestMMA7660XYZError(t *testing.T) { } _, _, _, err := d.XYZ() - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestMMA7660XYZNotReady(t *testing.T) { diff --git a/drivers/i2c/mpl115a2_driver_test.go b/drivers/i2c/mpl115a2_driver_test.go index 1b885a61d..bd0ad6422 100644 --- a/drivers/i2c/mpl115a2_driver_test.go +++ b/drivers/i2c/mpl115a2_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -78,18 +79,18 @@ func TestMPL115A2ReadData(t *testing.T) { press, errP := d.Pressure() temp, errT := d.Temperature() // assert - assert.NoError(t, errP) - assert.NoError(t, errT) + require.NoError(t, errP) + require.NoError(t, errT) assert.Equal(t, 2, readCallCounter) - assert.Equal(t, 6, len(a.written)) + assert.Len(t, a.written, 6) assert.Equal(t, uint8(0x12), a.written[0]) assert.Equal(t, uint8(0x00), a.written[1]) assert.Equal(t, uint8(0x00), a.written[2]) 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.Equal(t, float32(96.585915), press) - assert.Equal(t, float32(23.317757), temp) + assert.InDelta(t, float32(96.585915), press, 0.0) + assert.InDelta(t, float32(23.317757), temp, 0.0) } func TestMPL115A2ReadDataError(t *testing.T) { @@ -101,7 +102,7 @@ func TestMPL115A2ReadDataError(t *testing.T) { } _, err := d.Pressure() - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestMPL115A2_initialization(t *testing.T) { @@ -124,12 +125,12 @@ func TestMPL115A2_initialization(t *testing.T) { // act, assert - initialization() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, readCallCounter) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(0x04), a.written[0]) - assert.Equal(t, float32(2009.75), d.a0) - assert.Equal(t, float32(-2.3758545), d.b1) - assert.Equal(t, float32(-0.9204712), d.b2) - assert.Equal(t, float32(0.0007901192), d.c12) + assert.InDelta(t, float32(2009.75), d.a0, 0.0) + assert.InDelta(t, float32(-2.3758545), d.b1, 0.0) + assert.InDelta(t, float32(-0.9204712), d.b2, 0.0) + assert.InDelta(t, float32(0.0007901192), d.c12, 0.0) } diff --git a/drivers/i2c/mpu6050_driver_test.go b/drivers/i2c/mpu6050_driver_test.go index 4281dce64..15ba6e44a 100644 --- a/drivers/i2c/mpu6050_driver_test.go +++ b/drivers/i2c/mpu6050_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -36,7 +37,7 @@ func TestNewMPU6050Driver(t *testing.T) { assert.Equal(t, MPU6050AccelFsConfig(0x00), d.accelFs) assert.Equal(t, MPU6050GyroFsConfig(0x00), d.gyroFs) assert.Equal(t, MPU6050Pwr1ClockConfig(0x01), d.clock) - assert.Equal(t, 9.80665, d.gravity) + assert.InDelta(t, 9.80665, d.gravity, 0.0) } func TestMPU6050Options(t *testing.T) { @@ -69,7 +70,7 @@ func TestWithMPU6050ClockSource(t *testing.T) { func TestWithMPU6050Gravity(t *testing.T) { d := NewMPU6050Driver(newI2cTestAdaptor(), WithMPU6050Gravity(1.0)) - assert.Equal(t, 1.0, d.gravity) + assert.InDelta(t, 1.0, d.gravity, 0.0) } func TestMPU6050GetData(t *testing.T) { @@ -113,7 +114,7 @@ func TestMPU6050GetData(t *testing.T) { // assert assert.Equal(t, wantAccel, d.Accelerometer) assert.Equal(t, wantGyro, d.Gyroscope) - assert.Equal(t, wantTemp, d.Temperature) + assert.InDelta(t, wantTemp, d.Temperature, 0.0) } func TestMPU6050GetDataReadError(t *testing.T) { @@ -124,7 +125,7 @@ func TestMPU6050GetDataReadError(t *testing.T) { return 0, errors.New("read error") } - assert.ErrorContains(t, d.GetData(), "read error") + require.ErrorContains(t, d.GetData(), "read error") } func TestMPU6050GetDataWriteError(t *testing.T) { @@ -135,7 +136,7 @@ func TestMPU6050GetDataWriteError(t *testing.T) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.GetData(), "write error") + require.ErrorContains(t, d.GetData(), "write error") } func TestMPU6050_initialize(t *testing.T) { @@ -172,9 +173,9 @@ func TestMPU6050_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, readCallCounter) - assert.Equal(t, 13, len(a.written)) + assert.Len(t, a.written, 13) assert.Equal(t, uint8(0x6B), a.written[0]) assert.Equal(t, uint8(0x80), a.written[1]) assert.Equal(t, uint8(0x6B), a.written[2]) diff --git a/drivers/i2c/pca9501_driver_test.go b/drivers/i2c/pca9501_driver_test.go index 284600d91..8f10608fb 100644 --- a/drivers/i2c/pca9501_driver_test.go +++ b/drivers/i2c/pca9501_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -160,9 +161,9 @@ func TestPCA9501WriteGPIO(t *testing.T) { // act err := d.WriteGPIO(tc.pin, tc.setVal) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, 2, len(a.written)) + assert.Len(t, a.written, 2) assert.Equal(t, tc.wantPin, a.written[0]) assert.Equal(t, tc.wantState, a.written[1]) }) @@ -193,7 +194,7 @@ func TestPCA9501WriteGPIOErrorAtWriteDirection(t *testing.T) { err := d.WriteGPIO(7, 0) // assert assert.Equal(t, wantErr, err) - assert.True(t, numCallsRead < 2) + assert.Less(t, numCallsRead, 2) assert.Equal(t, 1, numCallsWrite) } @@ -254,10 +255,10 @@ func TestPCA9501ReadGPIO(t *testing.T) { // act got, err := d.ReadGPIO(pin) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.want, got) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, wantCtrlState, a.written[0]) }) } @@ -334,7 +335,7 @@ func TestPCA9501WriteEEPROM(t *testing.T) { // act err := d.WriteEEPROM(addressEEPROM, want) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, addressEEPROM, a.written[0]) assert.Equal(t, want, a.written[1]) @@ -363,7 +364,7 @@ func TestPCA9501ReadEEPROM(t *testing.T) { // act val, err := d.ReadEEPROM(addressEEPROM) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, want, val) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, addressEEPROM, a.written[0]) @@ -419,6 +420,6 @@ func TestPCA9501_initialize(t *testing.T) { // act err := d.initialize() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, want, a.address) } diff --git a/drivers/i2c/pca953x_driver_test.go b/drivers/i2c/pca953x_driver_test.go index 8aac72dd0..5bee65857 100644 --- a/drivers/i2c/pca953x_driver_test.go +++ b/drivers/i2c/pca953x_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -159,7 +160,7 @@ func TestPCA953xReadGPIO(t *testing.T) { got, err := d.ReadGPIO(tc.idx) // assert assert.Equal(t, tc.wantErr, err) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, wantReg, a.written[0]) assert.Equal(t, tc.want, got) }) @@ -200,7 +201,7 @@ func TestPCA953xWritePeriod(t *testing.T) { // act err := d.WritePeriod(tc.idx, tc.val) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -251,7 +252,7 @@ func TestPCA953xReadPeriod(t *testing.T) { got, err := d.ReadPeriod(tc.idx) // assert assert.Equal(t, tc.wantErr, err) - assert.Equal(t, tc.want, got) + assert.InDelta(t, tc.want, got, 0.0) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -291,7 +292,7 @@ func TestPCA953xWriteFrequency(t *testing.T) { // act err := d.WriteFrequency(tc.idx, tc.val) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -342,7 +343,7 @@ func TestPCA953xReadFrequency(t *testing.T) { got, err := d.ReadFrequency(tc.idx) // assert assert.Equal(t, tc.wantErr, err) - assert.Equal(t, tc.want, got) + assert.InDelta(t, tc.want, got, 0.0) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -382,7 +383,7 @@ func TestPCA953xWriteDutyCyclePercent(t *testing.T) { // act err := d.WriteDutyCyclePercent(tc.idx, tc.val) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -433,7 +434,7 @@ func TestPCA953xReadDutyCyclePercent(t *testing.T) { got, err := d.ReadDutyCyclePercent(tc.idx) // assert assert.Equal(t, tc.wantErr, err) - assert.Equal(t, tc.want, got) + assert.InDelta(t, tc.want, got, 0.0) assert.Equal(t, tc.wantWritten, a.written) }) } @@ -465,12 +466,12 @@ func TestPCA953x_readRegister(t *testing.T) { // act val, err := d.readRegister(wantRegAddress) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, wantRegVal, val) assert.Equal(t, wantReadByteCount, readByteCount) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(wantRegAddress), a.written[0]) } @@ -491,10 +492,10 @@ func TestPCA953x_writeRegister(t *testing.T) { // act err := d.writeRegister(wantRegAddress, wantRegVal) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsWrite) assert.Equal(t, 1, numCallsWrite) - assert.Equal(t, wantByteCount, len(a.written)) + assert.Len(t, a.written, wantByteCount) assert.Equal(t, uint8(wantRegAddress), a.written[0]) assert.Equal(t, wantRegVal, a.written[1]) } @@ -539,7 +540,7 @@ func TestPCA953x_pca953xCalcPeriod(t *testing.T) { // act val := pca953xCalcPeriod(tc.psc) // assert - assert.Equal(t, tc.want, float32(math.Round(float64(val)*10000)/10000)) + assert.InDelta(t, tc.want, float32(math.Round(float64(val)*10000)/10000), 0.0) }) } } @@ -585,7 +586,7 @@ func TestPCA953x_pca953xCalcDutyCyclePercent(t *testing.T) { // act val := pca953xCalcDutyCyclePercent(tc.pwm) // assert - assert.Equal(t, tc.want, float32(math.Round(float64(val)*10)/10)) + assert.InDelta(t, tc.want, float32(math.Round(float64(val)*10)/10), 0.0) }) } } diff --git a/drivers/i2c/pca9685_driver_test.go b/drivers/i2c/pca9685_driver_test.go index b9a3b0730..4880ec140 100644 --- a/drivers/i2c/pca9685_driver_test.go +++ b/drivers/i2c/pca9685_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" ) @@ -57,7 +58,7 @@ func TestPCA9685Start(t *testing.T) { return 1, nil } // act & assert - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestPCA9685StartError(t *testing.T) { @@ -68,7 +69,7 @@ func TestPCA9685StartError(t *testing.T) { return 0, errors.New("write error") } // act & assert - assert.ErrorContains(t, d.Start(), "write error") + require.ErrorContains(t, d.Start(), "write error") } func TestPCA9685Halt(t *testing.T) { @@ -78,9 +79,9 @@ func TestPCA9685Halt(t *testing.T) { // act err := d.Halt() // assert - assert.NoError(t, err) - assert.NoError(t, err) - assert.Equal(t, 2, len(a.written)) + require.NoError(t, err) + require.NoError(t, err) + assert.Len(t, a.written, 2) assert.Equal(t, []byte{0xFD, 0x10}, a.written) } @@ -91,7 +92,7 @@ func TestPCA9685HaltError(t *testing.T) { return 0, errors.New("write error") } // act & assert - assert.ErrorContains(t, d.Halt(), "write error") + require.ErrorContains(t, d.Halt(), "write error") } func TestPCA9685SetPWM(t *testing.T) { @@ -126,8 +127,8 @@ func TestPCA9685SetPWM(t *testing.T) { // act err := d.SetPWM(tc.pin, tc.onCounts, tc.offCounts) // assert - assert.NoError(t, err) - assert.Equal(t, 8, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 8) for writeIdx, wantVal := range tc.wantLedOnTimeOffTimeSet { assert.Equal(t, wantVal, a.written[writeIdx], "index %d differs", writeIdx) } @@ -142,7 +143,7 @@ func TestPCA9685SetPWMError(t *testing.T) { return 0, errors.New("write error") } // act & assert - assert.ErrorContains(t, d.SetPWM(0, 0, 256), "write error") + require.ErrorContains(t, d.SetPWM(0, 0, 256), "write error") } func TestPCA9685SetAllPWM(t *testing.T) { @@ -180,8 +181,8 @@ func TestPCA9685SetAllPWM(t *testing.T) { // act err := d.SetAllPWM(tc.onCounts, tc.offCounts) // assert - assert.NoError(t, err) - assert.Equal(t, 8, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 8) for writeIdx, wantVal := range tc.wantLedOnTimeOffTimeSet { assert.Equal(t, wantVal, a.written[writeIdx], "index %d differs", writeIdx) } @@ -196,7 +197,7 @@ func TestPCA9685SetAllPWMError(t *testing.T) { return 0, errors.New("write error") } // act & assert - assert.ErrorContains(t, d.SetAllPWM(0, 256), "write error") + require.ErrorContains(t, d.SetAllPWM(0, 256), "write error") } func TestPCA9685SetPWMFreq(t *testing.T) { @@ -240,8 +241,8 @@ func TestPCA9685SetPWMFreq(t *testing.T) { // act err := d.SetPWMFreq(tc.freq) // assert - assert.NoError(t, err) - assert.Equal(t, 9, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 9) var writeIdx int // for read old mode: assert.Equal(t, wantMode1SleepSequence[0], a.written[writeIdx], "index %d differs", writeIdx) @@ -274,7 +275,7 @@ func TestPCA9685SetPWMFreqReadError(t *testing.T) { return 0, errors.New("read error") } // act & assert - assert.ErrorContains(t, d.SetPWMFreq(60), "read error") + require.ErrorContains(t, d.SetPWMFreq(60), "read error") } func TestPCA9685SetPWMFreqWriteError(t *testing.T) { @@ -284,7 +285,7 @@ func TestPCA9685SetPWMFreqWriteError(t *testing.T) { return 0, errors.New("write error") } // act & assert - assert.ErrorContains(t, d.SetPWMFreq(60), "write error") + require.ErrorContains(t, d.SetPWMFreq(60), "write error") } func TestPCA9685Commands(t *testing.T) { @@ -323,8 +324,8 @@ func TestPCA9685_initialize(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) - assert.Equal(t, 15, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 15) var writeIdx int for idx, wantVal := range wantAllLedOnTimeOffTimeSequence { assert.Equal(t, wantVal, a.written[writeIdx], "index %d (%d) differs", writeIdx, idx) diff --git a/drivers/i2c/pcf8583_driver_test.go b/drivers/i2c/pcf8583_driver_test.go index e37c26753..9fd6355b2 100644 --- a/drivers/i2c/pcf8583_driver_test.go +++ b/drivers/i2c/pcf8583_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -210,10 +211,10 @@ func TestPCF8583WriteTime(t *testing.T) { // act err := d.WriteTime(initDate) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, initDate.Year(), d.yearOffset) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 11, len(a.written)) + assert.Len(t, a.written, 11) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[1]) assert.Equal(t, wantCtrlStop, a.written[2]) @@ -246,9 +247,9 @@ func TestPCF8583WriteTimeNoTimeModeFails(t *testing.T) { // act err := d.WriteTime(time.Now()) // assert - assert.NotNil(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "wrong mode 0x30") - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 1, numCallsRead) } @@ -292,8 +293,8 @@ func TestPCF8583ReadTime(t *testing.T) { // act got, err := d.ReadTime() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 2, numCallsRead) assert.Equal(t, want, got) @@ -318,10 +319,10 @@ func TestPCF8583ReadTimeNoTimeModeFails(t *testing.T) { // act got, err := d.ReadTime() // assert - assert.NotNil(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "wrong mode 0x20") assert.Equal(t, time.Time{}, got) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 1, numCallsRead) } @@ -357,9 +358,9 @@ func TestPCF8583WriteCounter(t *testing.T) { // act err := d.WriteCounter(initCount) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 8, len(a.written)) + assert.Len(t, a.written, 8) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[1]) assert.Equal(t, wantCtrlStop, a.written[2]) @@ -389,9 +390,9 @@ func TestPCF8583WriteCounterNoCounterModeFails(t *testing.T) { // act err := d.WriteCounter(123) // assert - assert.NotNil(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "wrong mode 0x10") - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 1, numCallsRead) } @@ -430,8 +431,8 @@ func TestPCF8583ReadCounter(t *testing.T) { // act got, err := d.ReadCounter() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 2, numCallsRead) assert.Equal(t, want, got) @@ -456,10 +457,10 @@ func TestPCF8583ReadCounterNoCounterModeFails(t *testing.T) { // act got, err := d.ReadCounter() // assert - assert.NotNil(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "wrong mode 0x30") assert.Equal(t, int32(0), got) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 1, numCallsRead) } @@ -480,8 +481,8 @@ func TestPCF8583WriteRam(t *testing.T) { // act err := d.WriteRAM(wantRAMAddress-pcf8583RamOffset, wantRAMValue) // assert - assert.NoError(t, err) - assert.Equal(t, 2, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 2) assert.Equal(t, wantRAMAddress, a.written[0]) assert.Equal(t, wantRAMValue, a.written[1]) } @@ -493,9 +494,9 @@ func TestPCF8583WriteRamAddressOverflowFails(t *testing.T) { // act err := d.WriteRAM(uint8(0xF0), 15) // assert - assert.NotNil(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "overflow 256") - assert.Equal(t, 0, len(a.written)) + assert.Empty(t, a.written) } func TestPCF8583ReadRam(t *testing.T) { @@ -521,9 +522,9 @@ func TestPCF8583ReadRam(t *testing.T) { // act got, err := d.ReadRAM(wantRAMAddress - pcf8583RamOffset) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, want, got) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, wantRAMAddress, a.written[0]) assert.Equal(t, 1, numCallsRead) } @@ -545,10 +546,10 @@ func TestPCF8583ReadRamAddressOverflowFails(t *testing.T) { // act got, err := d.ReadRAM(uint8(0xF0)) // assert - assert.NotNil(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "overflow 256") assert.Equal(t, uint8(0), got) - assert.Equal(t, 0, len(a.written)) + assert.Empty(t, a.written) assert.Equal(t, 0, numCallsRead) } @@ -572,9 +573,9 @@ func TestPCF8583_initializeNoModeSwitch(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 1, len(a.written)) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) } @@ -604,9 +605,9 @@ func TestPCF8583_initializeWithModeSwitch(t *testing.T) { // act, assert - initialize() must be called on Start() err := d.Start() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, numCallsRead) - assert.Equal(t, 3, len(a.written)) + assert.Len(t, a.written, 3) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[1]) assert.Equal(t, wantReg0Val, a.written[2]) diff --git a/drivers/i2c/pcf8591_driver_test.go b/drivers/i2c/pcf8591_driver_test.go index 299d49f2c..0936631b4 100644 --- a/drivers/i2c/pcf8591_driver_test.go +++ b/drivers/i2c/pcf8591_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -35,12 +36,12 @@ func TestNewPCF8591Driver(t *testing.T) { func TestPCF8591Start(t *testing.T) { d := NewPCF8591Driver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestPCF8591Halt(t *testing.T) { d := NewPCF8591Driver(newI2cTestAdaptor()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestPCF8591WithPCF8591With400kbitStabilization(t *testing.T) { @@ -78,8 +79,8 @@ func TestPCF8591AnalogReadSingle(t *testing.T) { // act got, err := d.AnalogRead(description) // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, ctrlByteOn, a.written[0]) assert.Equal(t, 2, numCallsRead) assert.Equal(t, want, got) @@ -120,8 +121,8 @@ func TestPCF8591AnalogReadDiff(t *testing.T) { // act got, err := d.AnalogRead(description) // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, ctrlByteOn, a.written[0]) assert.Equal(t, 2, numCallsRead) assert.Equal(t, want, got) @@ -146,8 +147,8 @@ func TestPCF8591AnalogWrite(t *testing.T) { // act err := d.AnalogWrite("", int(want)) // assert - assert.NoError(t, err) - assert.Equal(t, 2, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 2) assert.Equal(t, ctrlByteOn, a.written[0]) assert.Equal(t, want, a.written[1]) } @@ -171,8 +172,8 @@ func TestPCF8591AnalogOutputState(t *testing.T) { // act err := d.AnalogOutputState(bitState == 1) // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, wantCtrlByteVal, a.written[0]) } } diff --git a/drivers/i2c/sht2x_driver_test.go b/drivers/i2c/sht2x_driver_test.go index a71509b0e..9ae532b02 100644 --- a/drivers/i2c/sht2x_driver_test.go +++ b/drivers/i2c/sht2x_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -42,12 +43,12 @@ func TestSHT2xOptions(t *testing.T) { func TestSHT2xStart(t *testing.T) { d := NewSHT2xDriver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestSHT2xHalt(t *testing.T) { d, _ := initTestSHT2xDriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestSHT2xReset(t *testing.T) { @@ -57,7 +58,7 @@ func TestSHT2xReset(t *testing.T) { } _ = d.Start() err := d.Reset() - assert.NoError(t, err) + require.NoError(t, err) } func TestSHT2xMeasurements(t *testing.T) { @@ -75,11 +76,11 @@ func TestSHT2xMeasurements(t *testing.T) { } _ = d.Start() temp, err := d.Temperature() - assert.NoError(t, err) - assert.Equal(t, float32(18.809052), temp) + require.NoError(t, err) + assert.InDelta(t, float32(18.809052), temp, 0.0) hum, err := d.Humidity() - assert.NoError(t, err) - assert.Equal(t, float32(40.279907), hum) + require.NoError(t, err) + assert.InDelta(t, float32(40.279907), hum, 0.0) } func TestSHT2xAccuracy(t *testing.T) { @@ -100,7 +101,7 @@ func TestSHT2xAccuracy(t *testing.T) { _ = d.SetAccuracy(SHT2xAccuracyLow) assert.Equal(t, SHT2xAccuracyLow, d.Accuracy()) err := d.sendAccuracy() - assert.NoError(t, err) + require.NoError(t, err) } func TestSHT2xTemperatureCrcError(t *testing.T) { @@ -116,8 +117,8 @@ func TestSHT2xTemperatureCrcError(t *testing.T) { return buf.Len(), nil } temp, err := d.Temperature() - assert.ErrorContains(t, err, "Invalid crc") - assert.Equal(t, float32(0.0), temp) + require.ErrorContains(t, err, "Invalid crc") + assert.InDelta(t, float32(0.0), temp, 0.0) } func TestSHT2xHumidityCrcError(t *testing.T) { @@ -133,8 +134,8 @@ func TestSHT2xHumidityCrcError(t *testing.T) { return buf.Len(), nil } hum, err := d.Humidity() - assert.ErrorContains(t, err, "Invalid crc") - assert.Equal(t, float32(0.0), hum) + require.ErrorContains(t, err, "Invalid crc") + assert.InDelta(t, float32(0.0), hum, 0.0) } func TestSHT2xTemperatureLengthError(t *testing.T) { @@ -151,7 +152,7 @@ func TestSHT2xTemperatureLengthError(t *testing.T) { } temp, err := d.Temperature() assert.Equal(t, ErrNotEnoughBytes, err) - assert.Equal(t, float32(0.0), temp) + assert.InDelta(t, float32(0.0), temp, 0.0) } func TestSHT2xHumidityLengthError(t *testing.T) { @@ -168,5 +169,5 @@ func TestSHT2xHumidityLengthError(t *testing.T) { } hum, err := d.Humidity() assert.Equal(t, ErrNotEnoughBytes, err) - assert.Equal(t, float32(0.0), hum) + assert.InDelta(t, float32(0.0), hum, 0.0) } diff --git a/drivers/i2c/sht3x_driver_test.go b/drivers/i2c/sht3x_driver_test.go index 29144a957..13611382c 100644 --- a/drivers/i2c/sht3x_driver_test.go +++ b/drivers/i2c/sht3x_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -42,12 +43,12 @@ func TestSHT3xOptions(t *testing.T) { func TestSHT3xStart(t *testing.T) { d := NewSHT3xDriver(newI2cTestAdaptor()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestSHT3xHalt(t *testing.T) { d, _ := initTestSHT3xDriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestSHT3xSampleNormal(t *testing.T) { @@ -58,13 +59,13 @@ func TestSHT3xSampleNormal(t *testing.T) { } temp, rh, _ := d.Sample() - assert.Equal(t, float32(85.523003), temp) - assert.Equal(t, float32(74.5845), rh) + assert.InDelta(t, float32(85.523003), temp, 0.0) + assert.InDelta(t, float32(74.5845), rh, 0.0) // check the temp with the units in F d.Units = "F" temp, _, _ = d.Sample() - assert.Equal(t, float32(185.9414), temp) + assert.InDelta(t, float32(185.9414), temp, 0.0) } func TestSHT3xSampleBadCrc(t *testing.T) { @@ -155,7 +156,7 @@ func TestSHT3xHeater(t *testing.T) { } status, err := d.Heater() - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, status) // heater disabled @@ -165,7 +166,7 @@ func TestSHT3xHeater(t *testing.T) { } status, err = d.Heater() - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, status) // heater crc failed @@ -184,7 +185,7 @@ func TestSHT3xHeater(t *testing.T) { } _, err = d.Heater() - assert.NotNil(t, err) + require.Error(t, err) } func TestSHT3xSetHeater(t *testing.T) { @@ -199,11 +200,11 @@ func TestSHT3xSetAccuracy(t *testing.T) { assert.Equal(t, byte(SHT3xAccuracyHigh), d.Accuracy()) err := d.SetAccuracy(SHT3xAccuracyMedium) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, byte(SHT3xAccuracyMedium), d.Accuracy()) err = d.SetAccuracy(SHT3xAccuracyLow) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, byte(SHT3xAccuracyLow), d.Accuracy()) err = d.SetAccuracy(0xff) @@ -219,6 +220,6 @@ func TestSHT3xSerialNumber(t *testing.T) { sn, err := d.SerialNumber() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uint32(0x2000beef), sn) } diff --git a/drivers/i2c/ssd1306_driver_test.go b/drivers/i2c/ssd1306_driver_test.go index c5869bff8..204c6dbd8 100644 --- a/drivers/i2c/ssd1306_driver_test.go +++ b/drivers/i2c/ssd1306_driver_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -47,7 +48,7 @@ func TestSSD1306StartDefault(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestSSD1306Start128x32(t *testing.T) { @@ -58,7 +59,7 @@ func TestSSD1306Start128x32(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestSSD1306Start96x16(t *testing.T) { @@ -69,7 +70,7 @@ func TestSSD1306Start96x16(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestSSD1306StartExternalVCC(t *testing.T) { @@ -80,7 +81,7 @@ func TestSSD1306StartExternalVCC(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestSSD1306StartSizeError(t *testing.T) { @@ -91,12 +92,12 @@ func TestSSD1306StartSizeError(t *testing.T) { ) d := NewSSD1306Driver(newI2cTestAdaptor(), WithSSD1306DisplayWidth(width), WithSSD1306DisplayHeight(height), WithSSD1306ExternalVCC(externalVCC)) - assert.ErrorContains(t, d.Start(), "128x54 resolution is unsupported, supported resolutions: 128x64, 128x32, 96x16") + require.ErrorContains(t, d.Start(), "128x54 resolution is unsupported, supported resolutions: 128x64, 128x32, 96x16") } func TestSSD1306Halt(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) - assert.NoError(t, s.Halt()) + require.NoError(t, s.Halt()) } func TestSSD1306Options(t *testing.T) { @@ -109,17 +110,17 @@ func TestSSD1306Options(t *testing.T) { func TestSSD1306Display(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(96, 16, false) _ = s.Start() - assert.NoError(t, s.Display()) + require.NoError(t, s.Display()) } func TestSSD1306ShowImage(t *testing.T) { s, _ := initTestSSD1306DriverWithStubbedAdaptor(128, 64, false) _ = s.Start() img := image.NewRGBA(image.Rect(0, 0, 640, 480)) - assert.ErrorContains(t, s.ShowImage(img), "image must match display width and height: 128x64") + require.ErrorContains(t, s.ShowImage(img), "image must match display width and height: 128x64") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) - assert.NoError(t, s.ShowImage(img)) + require.NoError(t, s.ShowImage(img)) } func TestSSD1306Command(t *testing.T) { @@ -135,7 +136,7 @@ func TestSSD1306Command(t *testing.T) { return 0, nil } err := s.command(0xFF) - assert.NoError(t, err) + require.NoError(t, err) } func TestSSD1306Commands(t *testing.T) { @@ -151,7 +152,7 @@ func TestSSD1306Commands(t *testing.T) { return 0, nil } err := s.commands([]byte{0x00, 0xFF}) - assert.NoError(t, err) + require.NoError(t, err) } func TestSSD1306On(t *testing.T) { @@ -167,7 +168,7 @@ func TestSSD1306On(t *testing.T) { return 0, nil } err := s.On() - assert.NoError(t, err) + require.NoError(t, err) } func TestSSD1306Off(t *testing.T) { @@ -183,7 +184,7 @@ func TestSSD1306Off(t *testing.T) { return 0, nil } err := s.Off() - assert.NoError(t, err) + require.NoError(t, err) } func TestSSD1306Reset(t *testing.T) { @@ -200,7 +201,7 @@ func TestSSD1306Reset(t *testing.T) { return 0, nil } err := s.Reset() - assert.NoError(t, err) + require.NoError(t, err) } // COMMANDS diff --git a/drivers/i2c/th02_driver_test.go b/drivers/i2c/th02_driver_test.go index 26e9b3ce5..369900629 100644 --- a/drivers/i2c/th02_driver_test.go +++ b/drivers/i2c/th02_driver_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -102,8 +103,8 @@ func TestTH02FastMode(t *testing.T) { // act got, err := d.FastMode() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(0x03), a.written[0]) assert.Equal(t, tc.want, got) }) @@ -130,9 +131,9 @@ func TestTH02SetHeater(t *testing.T) { // act err := d.SetHeater(tc.heater) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.heater, d.heating) - assert.Equal(t, 2, len(a.written)) + assert.Len(t, a.written, 2) assert.Equal(t, uint8(0x03), a.written[0]) assert.Equal(t, tc.want, a.written[1]) }) @@ -162,8 +163,8 @@ func TestTH02Heater(t *testing.T) { // act got, err := d.Heater() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(0x03), a.written[0]) assert.Equal(t, tc.want, got) }) @@ -186,8 +187,8 @@ func TestTH02SerialNumber(t *testing.T) { // act sn, err := d.SerialNumber() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(a.written)) + require.NoError(t, err) + assert.Len(t, a.written, 1) assert.Equal(t, uint8(0x11), a.written[0]) assert.Equal(t, want, sn) } @@ -297,9 +298,9 @@ func TestTH02Sample(t *testing.T) { // act temp, rh, err := d.Sample() // assert - assert.NoError(t, err) - assert.Equal(t, tc.wantRH, rh) - assert.Equal(t, tc.wantT, temp) + require.NoError(t, err) + assert.InDelta(t, tc.wantRH, rh, 0.0) + assert.InDelta(t, tc.wantT, temp, 0.0) }) } } @@ -485,7 +486,7 @@ func TestTH02_createConfig(t *testing.T) { d.fastMode = tc.fast d.heating = tc.heating got := d.createConfig(tc.meas, tc.readTemp) - assert.Equal(t, got, tc.want) + assert.Equal(t, tc.want, got) }) } } diff --git a/drivers/i2c/tsl2561_driver_test.go b/drivers/i2c/tsl2561_driver_test.go index 3609721a0..a027b9abf 100644 --- a/drivers/i2c/tsl2561_driver_test.go +++ b/drivers/i2c/tsl2561_driver_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -60,7 +61,7 @@ func TestTSL2561DriverStart(t *testing.T) { d := NewTSL2561Driver(a) a.i2cReadImpl = testIDReader - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestTSL2561DriverStartNotFound(t *testing.T) { @@ -72,12 +73,12 @@ func TestTSL2561DriverStartNotFound(t *testing.T) { copy(b, buf.Bytes()) return buf.Len(), nil } - assert.ErrorContains(t, d.Start(), "TSL2561 device not found (0x1)") + require.ErrorContains(t, d.Start(), "TSL2561 device not found (0x1)") } func TestTSL2561DriverHalt(t *testing.T) { d, _ := initTestTSL2561Driver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestTSL2561DriverRead16(t *testing.T) { @@ -93,7 +94,7 @@ func TestTSL2561DriverRead16(t *testing.T) { return buf.Len(), nil } val, err := d.connection.ReadWordData(1) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uint16(0xAEEA), val) } @@ -157,7 +158,7 @@ func TestTSL2561DriverGetDataWriteError(t *testing.T) { } _, _, err := d.getData() - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestTSL2561DriverGetDataReadError(t *testing.T) { @@ -167,7 +168,7 @@ func TestTSL2561DriverGetDataReadError(t *testing.T) { } _, _, err := d.getData() - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestTSL2561DriverGetLuminocity(t *testing.T) { @@ -180,7 +181,7 @@ func TestTSL2561DriverGetLuminocity(t *testing.T) { return buf.Len(), nil } bb, ir, err := d.GetLuminocity() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uint16(12365), bb) assert.Equal(t, uint16(12365), ir) assert.Equal(t, uint32(72), d.CalculateLux(bb, ir)) @@ -202,7 +203,7 @@ func TestTSL2561DriverGetLuminocityAutoGain(t *testing.T) { _ = d.Start() bb, ir, err := d.GetLuminocity() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uint16(12365), bb) assert.Equal(t, uint16(12365), ir) assert.Equal(t, uint32(72), d.CalculateLux(bb, ir)) @@ -213,7 +214,7 @@ func TestTSL2561SetIntegrationTimeError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.SetIntegrationTime(TSL2561IntegrationTime101MS), "write error") + require.ErrorContains(t, d.SetIntegrationTime(TSL2561IntegrationTime101MS), "write error") } func TestTSL2561SetGainError(t *testing.T) { @@ -221,7 +222,7 @@ func TestTSL2561SetGainError(t *testing.T) { a.i2cWriteImpl = func([]byte) (int, error) { return 0, errors.New("write error") } - assert.ErrorContains(t, d.SetGain(TSL2561Gain16X), "write error") + require.ErrorContains(t, d.SetGain(TSL2561Gain16X), "write error") } func TestTSL2561getHiLo13MS(t *testing.T) { diff --git a/drivers/i2c/wiichuck_driver_test.go b/drivers/i2c/wiichuck_driver_test.go index 94858de3b..348336d9a 100644 --- a/drivers/i2c/wiichuck_driver_test.go +++ b/drivers/i2c/wiichuck_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -44,7 +45,7 @@ func TestWiichuckDriverStart(t *testing.T) { d.interval = 1 * time.Millisecond sem := make(chan bool) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) go func() { for { @@ -67,7 +68,7 @@ func TestWiichuckDriverStart(t *testing.T) { func TestWiichuckDriverHalt(t *testing.T) { d := initTestWiichuckDriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestWiichuckDriverCanParse(t *testing.T) { @@ -78,10 +79,10 @@ func TestWiichuckDriverCanParse(t *testing.T) { _ = d.update(decryptedValue) // - This should be done by WiichuckDriver.parse - assert.Equal(t, float64(45), d.data["sx"]) - assert.Equal(t, float64(44), d.data["sy"]) - assert.Equal(t, float64(0), d.data["z"]) - assert.Equal(t, float64(0), d.data["c"]) + assert.InDelta(t, float64(45), d.data["sx"], 0.0) + assert.InDelta(t, float64(44), d.data["sy"], 0.0) + assert.InDelta(t, float64(0), d.data["z"], 0.0) + assert.InDelta(t, float64(0), d.data["c"], 0.0) } func TestWiichuckDriverCanAdjustOrigins(t *testing.T) { @@ -92,8 +93,8 @@ func TestWiichuckDriverCanAdjustOrigins(t *testing.T) { _ = d.update(decryptedValue) // - This should be done by WiichuckDriver.adjustOrigins - assert.Equal(t, float64(45), d.Joystick()["sx_origin"]) - assert.Equal(t, float64(44), d.Joystick()["sy_origin"]) + assert.InDelta(t, float64(45), d.Joystick()["sx_origin"], 0.0) + assert.InDelta(t, float64(44), d.Joystick()["sy_origin"], 0.0) } func TestWiichuckDriverCButton(t *testing.T) { @@ -107,7 +108,7 @@ func TestWiichuckDriverCButton(t *testing.T) { done := make(chan bool) _ = d.On(d.Event(C), func(data interface{}) { - assert.Equal(t, true, data) + assert.Equal(t, true, data) //nolint:testifylint // data is an interface done <- true }) @@ -130,7 +131,7 @@ func TestWiichuckDriverZButton(t *testing.T) { done := make(chan bool) _ = d.On(d.Event(Z), func(data interface{}) { - assert.Equal(t, true, data) + assert.Equal(t, true, data) //nolint:testifylint // data is an interface done <- true }) @@ -177,37 +178,37 @@ func TestWiichuckDriverEncrypted(t *testing.T) { _ = d.update(encryptedValue) - assert.Equal(t, float64(0), d.data["sx"]) - assert.Equal(t, float64(0), d.data["sy"]) - assert.Equal(t, float64(0), d.data["z"]) - assert.Equal(t, float64(0), d.data["c"]) + assert.InDelta(t, float64(0), d.data["sx"], 0.0) + assert.InDelta(t, float64(0), d.data["sy"], 0.0) + assert.InDelta(t, float64(0), d.data["z"], 0.0) + assert.InDelta(t, float64(0), d.data["c"], 0.0) - assert.Equal(t, float64(-1), d.Joystick()["sx_origin"]) - assert.Equal(t, float64(-1), d.Joystick()["sy_origin"]) + assert.InDelta(t, float64(-1), d.Joystick()["sx_origin"], 0.0) + assert.InDelta(t, float64(-1), d.Joystick()["sy_origin"], 0.0) } func TestWiichuckDriverSetJoystickDefaultValue(t *testing.T) { d := initTestWiichuckDriverWithStubbedAdaptor() - assert.Equal(t, float64(-1), d.Joystick()["sy_origin"]) + assert.InDelta(t, float64(-1), d.Joystick()["sy_origin"], 0.0) d.setJoystickDefaultValue("sy_origin", float64(2)) - assert.Equal(t, float64(2), d.Joystick()["sy_origin"]) + assert.InDelta(t, float64(2), d.Joystick()["sy_origin"], 0.0) // when current default value is not -1 it keeps the current value d.setJoystickDefaultValue("sy_origin", float64(20)) - assert.Equal(t, float64(2), d.Joystick()["sy_origin"]) + assert.InDelta(t, float64(2), d.Joystick()["sy_origin"], 0.0) } func TestWiichuckDriverCalculateJoystickValue(t *testing.T) { d := initTestWiichuckDriverWithStubbedAdaptor() - assert.Equal(t, float64(15), d.calculateJoystickValue(float64(20), float64(5))) - assert.Equal(t, float64(-1), d.calculateJoystickValue(float64(1), float64(2))) - assert.Equal(t, float64(5), d.calculateJoystickValue(float64(10), float64(5))) - assert.Equal(t, float64(-5), d.calculateJoystickValue(float64(5), float64(10))) + assert.InDelta(t, float64(15), d.calculateJoystickValue(float64(20), float64(5)), 0.0) + assert.InDelta(t, float64(-1), d.calculateJoystickValue(float64(1), float64(2)), 0.0) + assert.InDelta(t, float64(5), d.calculateJoystickValue(float64(10), float64(5)), 0.0) + assert.InDelta(t, float64(-5), d.calculateJoystickValue(float64(5), float64(10)), 0.0) } func TestWiichuckDriverIsEncrypted(t *testing.T) { @@ -232,49 +233,49 @@ func TestWiichuckDriverIsEncrypted(t *testing.T) { func TestWiichuckDriverDecode(t *testing.T) { d := initTestWiichuckDriverWithStubbedAdaptor() - assert.Equal(t, float64(46), d.decode(byte(0))) - assert.Equal(t, float64(138), d.decode(byte(100))) - assert.Equal(t, float64(246), d.decode(byte(200))) - assert.Equal(t, float64(0), d.decode(byte(254))) + assert.InDelta(t, float64(46), d.decode(byte(0)), 0.0) + assert.InDelta(t, float64(138), d.decode(byte(100)), 0.0) + assert.InDelta(t, float64(246), d.decode(byte(200)), 0.0) + assert.InDelta(t, float64(0), d.decode(byte(254)), 0.0) } func TestWiichuckDriverParse(t *testing.T) { d := initTestWiichuckDriverWithStubbedAdaptor() - assert.Equal(t, float64(0), d.data["sx"]) - assert.Equal(t, float64(0), d.data["sy"]) - assert.Equal(t, float64(0), d.data["z"]) - assert.Equal(t, float64(0), d.data["c"]) + assert.InDelta(t, float64(0), d.data["sx"], 0.0) + assert.InDelta(t, float64(0), d.data["sy"], 0.0) + assert.InDelta(t, float64(0), d.data["z"], 0.0) + assert.InDelta(t, float64(0), d.data["c"], 0.0) // First pass d.parse([]byte{12, 23, 34, 45, 56, 67}) - assert.Equal(t, float64(50), d.data["sx"]) - assert.Equal(t, float64(23), d.data["sy"]) - assert.Equal(t, float64(1), d.data["z"]) - assert.Equal(t, float64(2), d.data["c"]) + assert.InDelta(t, float64(50), d.data["sx"], 0.0) + assert.InDelta(t, float64(23), d.data["sy"], 0.0) + assert.InDelta(t, float64(1), d.data["z"], 0.0) + assert.InDelta(t, float64(2), d.data["c"], 0.0) // Second pass d.parse([]byte{70, 81, 92, 103, 204, 205}) - assert.Equal(t, float64(104), d.data["sx"]) - assert.Equal(t, float64(93), d.data["sy"]) - assert.Equal(t, float64(1), d.data["z"]) - assert.Equal(t, float64(0), d.data["c"]) + assert.InDelta(t, float64(104), d.data["sx"], 0.0) + assert.InDelta(t, float64(93), d.data["sy"], 0.0) + assert.InDelta(t, float64(1), d.data["z"], 0.0) + assert.InDelta(t, float64(0), d.data["c"], 0.0) } func TestWiichuckDriverAdjustOrigins(t *testing.T) { d := initTestWiichuckDriverWithStubbedAdaptor() - assert.Equal(t, float64(-1), d.Joystick()["sy_origin"]) - assert.Equal(t, float64(-1), d.Joystick()["sx_origin"]) + assert.InDelta(t, float64(-1), d.Joystick()["sy_origin"], 0.0) + assert.InDelta(t, float64(-1), d.Joystick()["sx_origin"], 0.0) // First pass d.parse([]byte{1, 2, 3, 4, 5, 6}) d.adjustOrigins() - assert.Equal(t, float64(44), d.Joystick()["sy_origin"]) - assert.Equal(t, float64(45), d.Joystick()["sx_origin"]) + assert.InDelta(t, float64(44), d.Joystick()["sy_origin"], 0.0) + assert.InDelta(t, float64(45), d.Joystick()["sx_origin"], 0.0) // Second pass d = initTestWiichuckDriverWithStubbedAdaptor() @@ -282,8 +283,8 @@ func TestWiichuckDriverAdjustOrigins(t *testing.T) { d.parse([]byte{61, 72, 83, 94, 105, 206}) d.adjustOrigins() - assert.Equal(t, float64(118), d.Joystick()["sy_origin"]) - assert.Equal(t, float64(65), d.Joystick()["sx_origin"]) + assert.InDelta(t, float64(118), d.Joystick()["sy_origin"], 0.0) + assert.InDelta(t, float64(65), d.Joystick()["sx_origin"], 0.0) } func TestWiichuckDriverSetName(t *testing.T) { diff --git a/drivers/i2c/yl40_driver_test.go b/drivers/i2c/yl40_driver_test.go index 33678172b..2975ceec1 100644 --- a/drivers/i2c/yl40_driver_test.go +++ b/drivers/i2c/yl40_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func initTestYL40DriverWithStubbedAdaptor() (*YL40Driver, *i2cTestAdaptor) { @@ -107,13 +108,13 @@ func TestYL40DriverReadBrightness(t *testing.T) { got, err := yl.ReadBrightness() got2, err2 := yl.Brightness() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(adaptor.written)) + require.NoError(t, err) + assert.Len(t, adaptor.written, 1) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, want, got) - assert.NoError(t, err2) - assert.Equal(t, want, got2) + assert.InDelta(t, want, got, 0.0) + require.NoError(t, err2) + assert.InDelta(t, want, got2, 0.0) } func TestYL40DriverReadTemperature(t *testing.T) { @@ -143,13 +144,13 @@ func TestYL40DriverReadTemperature(t *testing.T) { got, err := yl.ReadTemperature() got2, err2 := yl.Temperature() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(adaptor.written)) + require.NoError(t, err) + assert.Len(t, adaptor.written, 1) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, want, got) - assert.NoError(t, err2) - assert.Equal(t, want, got2) + assert.InDelta(t, want, got, 0.0) + require.NoError(t, err2) + assert.InDelta(t, want, got2, 0.0) } func TestYL40DriverReadAIN2(t *testing.T) { @@ -178,13 +179,13 @@ func TestYL40DriverReadAIN2(t *testing.T) { got, err := yl.ReadAIN2() got2, err2 := yl.AIN2() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(adaptor.written)) + require.NoError(t, err) + assert.Len(t, adaptor.written, 1) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, want, got) - assert.NoError(t, err2) - assert.Equal(t, want, got2) + assert.InDelta(t, want, got, 0.0) + require.NoError(t, err2) + assert.InDelta(t, want, got2, 0.0) } func TestYL40DriverReadPotentiometer(t *testing.T) { @@ -213,13 +214,13 @@ func TestYL40DriverReadPotentiometer(t *testing.T) { got, err := yl.ReadPotentiometer() got2, err2 := yl.Potentiometer() // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(adaptor.written)) + require.NoError(t, err) + assert.Len(t, adaptor.written, 1) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, 2, numCallsRead) - assert.Equal(t, want, got) - assert.NoError(t, err2) - assert.Equal(t, want, got2) + assert.InDelta(t, want, got, 0.0) + require.NoError(t, err2) + assert.InDelta(t, want, got2, 0.0) } func TestYL40DriverAnalogWrite(t *testing.T) { @@ -238,20 +239,20 @@ func TestYL40DriverAnalogWrite(t *testing.T) { // act err := pcf.Write(write) // assert - assert.NoError(t, err) - assert.Equal(t, 2, len(adaptor.written)) + require.NoError(t, err) + assert.Len(t, adaptor.written, 2) assert.Equal(t, ctrlByteOn, adaptor.written[0]) assert.Equal(t, want, adaptor.written[1]) } func TestYL40DriverStart(t *testing.T) { yl := NewYL40Driver(newI2cTestAdaptor()) - assert.NoError(t, yl.Start()) + require.NoError(t, yl.Start()) } func TestYL40DriverHalt(t *testing.T) { yl := NewYL40Driver(newI2cTestAdaptor()) - assert.NoError(t, yl.Halt()) + require.NoError(t, yl.Halt()) } func fEqual(want interface{}, got interface{}) bool { diff --git a/drivers/spi/apa102_test.go b/drivers/spi/apa102_test.go index a0a562eba..bca281a5f 100644 --- a/drivers/spi/apa102_test.go +++ b/drivers/spi/apa102_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -40,5 +41,5 @@ func TestDriverLEDs(t *testing.T) { d.SetRGBA(2, color.RGBA{255, 255, 255, 15}) d.SetRGBA(3, color.RGBA{255, 255, 255, 15}) - assert.NoError(t, d.Draw()) + require.NoError(t, d.Draw()) } diff --git a/drivers/spi/mcp3002_test.go b/drivers/spi/mcp3002_test.go index af328c9c6..c8b341d17 100644 --- a/drivers/spi/mcp3002_test.go +++ b/drivers/spi/mcp3002_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) @@ -87,6 +88,6 @@ func TestMCP3002ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.ErrorContains(t, err, "error while SPI read in mock") + require.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3004_test.go b/drivers/spi/mcp3004_test.go index adba27edf..c6b0660b7 100644 --- a/drivers/spi/mcp3004_test.go +++ b/drivers/spi/mcp3004_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) @@ -93,6 +94,6 @@ func TestMCP3004ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.ErrorContains(t, err, "error while SPI read in mock") + require.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3008_test.go b/drivers/spi/mcp3008_test.go index 095e8c3b0..4ad5d91a6 100644 --- a/drivers/spi/mcp3008_test.go +++ b/drivers/spi/mcp3008_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) @@ -93,6 +94,6 @@ func TestMCP3008ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.ErrorContains(t, err, "error while SPI read in mock") + require.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3202_test.go b/drivers/spi/mcp3202_test.go index e580a91b7..ec414964b 100644 --- a/drivers/spi/mcp3202_test.go +++ b/drivers/spi/mcp3202_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) @@ -87,6 +88,6 @@ func TestMCP3202ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.ErrorContains(t, err, "error while SPI read in mock") + require.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3204_test.go b/drivers/spi/mcp3204_test.go index 967043983..c948fe630 100644 --- a/drivers/spi/mcp3204_test.go +++ b/drivers/spi/mcp3204_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) @@ -93,6 +94,6 @@ func TestMCP3204ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.ErrorContains(t, err, "error while SPI read in mock") + require.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3208_test.go b/drivers/spi/mcp3208_test.go index 81d59ff70..9150aa61d 100644 --- a/drivers/spi/mcp3208_test.go +++ b/drivers/spi/mcp3208_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) @@ -93,6 +94,6 @@ func TestMCP3208ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.ErrorContains(t, err, "error while SPI read in mock") + require.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mcp3304_test.go b/drivers/spi/mcp3304_test.go index f8bf8e4ba..b9a3b3860 100644 --- a/drivers/spi/mcp3304_test.go +++ b/drivers/spi/mcp3304_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) @@ -93,6 +94,6 @@ func TestMCP3304ReadWithError(t *testing.T) { // act got, err := d.Read(0) // assert - assert.ErrorContains(t, err, "error while SPI read in mock") + require.ErrorContains(t, err, "error while SPI read in mock") assert.Equal(t, 0, got) } diff --git a/drivers/spi/mfrc522_driver_test.go b/drivers/spi/mfrc522_driver_test.go index f8acb88aa..bbfc54715 100644 --- a/drivers/spi/mfrc522_driver_test.go +++ b/drivers/spi/mfrc522_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -39,6 +40,6 @@ func TestMFRC522WriteByteData(t *testing.T) { // act err := d.connection.WriteByteData(0x00, 0x00) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []byte{0x00, 0x00}, a.spi.Written()) } diff --git a/drivers/spi/spi_connection_test.go b/drivers/spi/spi_connection_test.go index 9291a6892..d849e96b5 100644 --- a/drivers/spi/spi_connection_test.go +++ b/drivers/spi/spi_connection_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) @@ -38,7 +39,7 @@ func TestReadCommandData(t *testing.T) { got := []byte{0x01, 0x02} err := c.ReadCommandData(command, got) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, command, sysdev.Written()) assert.Equal(t, want, got) } @@ -54,7 +55,7 @@ func TestReadByteData(t *testing.T) { // act got, err := c.ReadByteData(reg) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []byte{reg, 0x00}, sysdev.Written()) // for read register we need n+1 bytes assert.Equal(t, want, got) } @@ -71,7 +72,7 @@ func TestReadBlockData(t *testing.T) { got := make([]byte, 4) err := c.ReadBlockData(reg, got) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []byte{reg, 0x00, 0x00, 0x00, 0x00}, sysdev.Written()) // for read registers we need n+1 bytes assert.Equal(t, want, got) } @@ -83,7 +84,7 @@ func TestWriteByte(t *testing.T) { // act err := c.WriteByte(want) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []byte{want}, sysdev.Written()) } @@ -97,7 +98,7 @@ func TestWriteByteData(t *testing.T) { // act err := c.WriteByteData(reg, val) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []byte{reg, val}, sysdev.Written()) } @@ -109,7 +110,7 @@ func TestWriteBlockData(t *testing.T) { // act err := c.WriteBlockData(reg, data) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, append([]byte{reg}, data...), sysdev.Written()) } @@ -120,6 +121,6 @@ func TestWriteBytes(t *testing.T) { // act err := c.WriteBytes(want) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, want, sysdev.Written()) } diff --git a/drivers/spi/spi_driver.go b/drivers/spi/spi_driver.go index bf5d0aa91..b18acc6a3 100644 --- a/drivers/spi/spi_driver.go +++ b/drivers/spi/spi_driver.go @@ -43,31 +43,31 @@ type Connection gobot.SpiOperations // optional SPI params such as which SPI bus it wants to use. type Config interface { // SetBusNumber sets which bus to use - SetBusNumber(int) + SetBusNumber(bus int) // GetBusNumberOrDefault gets which bus to use GetBusNumberOrDefault(def int) int // SetChipNumber sets which chip to use - SetChipNumber(int) + SetChipNumber(chip int) // GetChipNumberOrDefault gets which chip to use GetChipNumberOrDefault(def int) int // SetMode sets which mode to use - SetMode(int) + SetMode(mode int) // GetModeOrDefault gets which mode to use GetModeOrDefault(def int) int // SetUsedBits sets how many bits to use - SetBitCount(int) + SetBitCount(count int) // GetBitCountOrDefault gets how many bits to use GetBitCountOrDefault(def int) int // SetSpeed sets which speed to use (in Hz) - SetSpeed(int64) + SetSpeed(speed int64) // GetSpeedOrDefault gets which speed to use (in Hz) GetSpeedOrDefault(def int64) int64 diff --git a/drivers/spi/spi_driver_test.go b/drivers/spi/spi_driver_test.go index 6e4257f60..60ecb2b75 100644 --- a/drivers/spi/spi_driver_test.go +++ b/drivers/spi/spi_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -30,12 +31,12 @@ func TestNewDriver(t *testing.T) { func TestStart(t *testing.T) { d := NewDriver(newSpiTestAdaptor(), "SPI_BASIC") - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestHalt(t *testing.T) { d, _ := initTestDriverWithStubbedAdaptor() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestSetName(t *testing.T) { diff --git a/drivers/spi/ssd1306_driver_test.go b/drivers/spi/ssd1306_driver_test.go index b3ec7d791..57b39b7fc 100644 --- a/drivers/spi/ssd1306_driver_test.go +++ b/drivers/spi/ssd1306_driver_test.go @@ -5,7 +5,7 @@ import ( "sync" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -19,29 +19,29 @@ func initTestSSDDriver() *SSD1306Driver { func TestDriverSSDStart(t *testing.T) { d := initTestSSDDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestDriverSSDHalt(t *testing.T) { d := initTestSSDDriver() _ = d.Start() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestDriverSSDDisplay(t *testing.T) { d := initTestSSDDriver() _ = d.Start() - assert.NoError(t, d.Display()) + require.NoError(t, d.Display()) } func TestSSD1306DriverShowImage(t *testing.T) { d := initTestSSDDriver() _ = d.Start() img := image.NewRGBA(image.Rect(0, 0, 640, 480)) - assert.ErrorContains(t, d.ShowImage(img), "Image must match the display width and height") + require.ErrorContains(t, d.ShowImage(img), "Image must match the display width and height") img = image.NewRGBA(image.Rect(0, 0, 128, 64)) - assert.NoError(t, d.ShowImage(img)) + require.NoError(t, d.ShowImage(img)) } type gpioTestAdaptor struct { diff --git a/master_test.go b/master_test.go index e722a00e9..ac7cea80a 100644 --- a/master_test.go +++ b/master_test.go @@ -10,6 +10,7 @@ import ( multierror "github.com/hashicorp/go-multierror" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func initTestMaster() *Master { @@ -41,7 +42,7 @@ func TestNullReadWriteCloser(t *testing.T) { assert.Equal(t, 3, i) i, _ = n.Read(make([]byte, 10)) assert.Equal(t, 10, i) - assert.NoError(t, n.Close()) + require.NoError(t, n.Close()) } func TestMasterRobot(t *testing.T) { @@ -63,14 +64,14 @@ func TestMasterToJSON(t *testing.T) { return nil }) json := NewJSONMaster(g) - assert.Equal(t, g.Robots().Len(), len(json.Robots)) - assert.Equal(t, len(g.Commands()), len(json.Commands)) + assert.Len(t, json.Robots, g.Robots().Len()) + assert.Len(t, json.Commands, len(g.Commands())) } func TestMasterStart(t *testing.T) { g := initTestMaster() - assert.NoError(t, g.Start()) - assert.NoError(t, g.Stop()) + require.NoError(t, g.Start()) + require.NoError(t, g.Stop()) assert.False(t, g.Running()) } @@ -82,7 +83,7 @@ func TestMasterStartAutoRun(t *testing.T) { assert.True(t, g.Running()) // stop it - assert.NoError(t, g.Stop()) + require.NoError(t, g.Stop()) assert.False(t, g.Running()) } @@ -99,7 +100,7 @@ func TestMasterStartDriverErrors(t *testing.T) { want = multierror.Append(want, e) assert.Equal(t, want, g.Start()) - assert.NoError(t, g.Stop()) + require.NoError(t, g.Stop()) testDriverStart = func() (err error) { return } } @@ -138,7 +139,7 @@ func TestMasterStartRobotAdaptorErrors(t *testing.T) { } assert.Equal(t, want, g.Start()) - assert.NoError(t, g.Stop()) + require.NoError(t, g.Stop()) testAdaptorConnect = func() (err error) { return } } diff --git a/platforms/adaptors/digitalpinsadaptor.go b/platforms/adaptors/digitalpinsadaptor.go index 7ffc9de10..08cd04da6 100644 --- a/platforms/adaptors/digitalpinsadaptor.go +++ b/platforms/adaptors/digitalpinsadaptor.go @@ -17,7 +17,7 @@ type ( ) type digitalPinsOptioner interface { - setDigitalPinInitializer(digitalPinInitializer) + setDigitalPinInitializer(initializer digitalPinInitializer) setDigitalPinsForSystemGpiod() setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string) prepareDigitalPinsActiveLow(pin string, otherPins ...string) diff --git a/platforms/adaptors/digitalpinsadaptor_test.go b/platforms/adaptors/digitalpinsadaptor_test.go index f25feda58..2e91c561a 100644 --- a/platforms/adaptors/digitalpinsadaptor_test.go +++ b/platforms/adaptors/digitalpinsadaptor_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/system" @@ -49,7 +50,7 @@ func TestDigitalPinsWithGpiosActiveLow(t *testing.T) { // act a := NewDigitalPinsAdaptor(sys, translate, WithGpiosActiveLow("1", "12", "33")) // assert - assert.Equal(t, 3, len(a.pinOptions)) + assert.Len(t, a.pinOptions, 3) } func TestDigitalPinsConnect(t *testing.T) { @@ -60,15 +61,15 @@ func TestDigitalPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.DigitalPinner)(nil), a.pins) _, err := a.DigitalRead("13") - assert.ErrorContains(t, err, "not connected for pin 13") + require.ErrorContains(t, err, "not connected for pin 13") err = a.DigitalWrite("7", 1) - assert.ErrorContains(t, err, "not connected for pin 7") + require.ErrorContains(t, err, "not connected for pin 7") err = a.Connect() - assert.NoError(t, err) + require.NoError(t, err) assert.NotEqual(t, (map[string]gobot.DigitalPinner)(nil), a.pins) - assert.Equal(t, 0, len(a.pins)) + assert.Empty(t, a.pins) } func TestDigitalPinsFinalize(t *testing.T) { @@ -83,21 +84,21 @@ func TestDigitalPinsFinalize(t *testing.T) { fs := sys.UseMockFilesystem(mockedPaths) a := NewDigitalPinsAdaptor(sys, testDigitalPinTranslator) // assert that finalize before connect is working - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // arrange - assert.NoError(t, a.Connect()) - assert.NoError(t, a.DigitalWrite("3", 1)) - assert.Equal(t, 1, len(a.pins)) + require.NoError(t, a.Connect()) + require.NoError(t, a.DigitalWrite("3", 1)) + assert.Len(t, a.pins, 1) // act err := a.Finalize() // assert - assert.NoError(t, err) - assert.Equal(t, 0, len(a.pins)) + require.NoError(t, err) + assert.Empty(t, a.pins) // assert that finalize after finalize is working - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // arrange missing sysfs file - assert.NoError(t, a.Connect()) - assert.NoError(t, a.DigitalWrite("3", 2)) + require.NoError(t, a.Connect()) + require.NoError(t, a.DigitalWrite("3", 2)) delete(fs.Files, "/sys/class/gpio/unexport") err = a.Finalize() assert.Contains(t, err.Error(), "/sys/class/gpio/unexport: no such file") @@ -112,15 +113,15 @@ func TestDigitalPinsReConnect(t *testing.T) { "/sys/class/gpio/gpio15/value", } a, _ := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) - assert.NoError(t, a.DigitalWrite("4", 1)) - assert.Equal(t, 1, len(a.pins)) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.DigitalWrite("4", 1)) + assert.Len(t, a.pins, 1) + require.NoError(t, a.Finalize()) // act err := a.Connect() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, a.pins) - assert.Equal(t, 0, len(a.pins)) + assert.Empty(t, a.pins) } func TestDigitalIO(t *testing.T) { @@ -133,10 +134,10 @@ func TestDigitalIO(t *testing.T) { a, _ := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) err := a.DigitalWrite("14", 1) - assert.NoError(t, err) + require.NoError(t, err) i, err := a.DigitalRead("14") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, i) } @@ -153,18 +154,18 @@ func TestDigitalRead(t *testing.T) { // assert read correct value without error i, err := a.DigitalRead("13") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, i) // assert error bubbling for read errors fs.WithReadError = true _, err = a.DigitalRead("13") - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") // assert error bubbling for write errors fs.WithWriteError = true _, err = a.DigitalRead("7") - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestDigitalReadWithGpiosActiveLow(t *testing.T) { @@ -193,8 +194,8 @@ func TestDigitalReadWithGpiosActiveLow(t *testing.T) { got1, err1 := a.DigitalRead("14") // for a new pin got2, err2 := a.DigitalRead("15") // for an existing pin (calls ApplyOptions()) // assert - assert.NoError(t, err1) - assert.NoError(t, err2) + require.NoError(t, err1) + require.NoError(t, err2) assert.Equal(t, 1, got1) // there is no mechanism to negate mocked values assert.Equal(t, 0, got2) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio25/active_low"].Contents) @@ -217,7 +218,7 @@ func TestDigitalWrite(t *testing.T) { WithGpioEventOnFallingEdge("7", gpioEventHandler)(a) WithGpioPollForEdgeDetection("7", 0, nil)(a) err := a.DigitalWrite("7", 1) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio18/value"].Contents) // assert second write to same pin without error and just ignore unsupported options @@ -226,15 +227,15 @@ func TestDigitalWrite(t *testing.T) { WithGpioDebounce("7", 2*time.Second)(a) WithGpioEventOnRisingEdge("7", gpioEventHandler)(a) err = a.DigitalWrite("7", 1) - assert.NoError(t, err) + require.NoError(t, err) // assert error on bad id - assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "not a valid pin") + require.ErrorContains(t, a.DigitalWrite("notexist", 1), "not a valid pin") // assert error bubbling fs.WithWriteError = true err = a.DigitalWrite("7", 0) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestDigitalWriteWithGpiosActiveLow(t *testing.T) { @@ -252,7 +253,7 @@ func TestDigitalWriteWithGpiosActiveLow(t *testing.T) { // act err := a.DigitalWrite("8", 2) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "2", fs.Files["/sys/class/gpio/gpio19/value"].Contents) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio19/active_low"].Contents) } diff --git a/platforms/adaptors/i2cbusadaptor_test.go b/platforms/adaptors/i2cbusadaptor_test.go index f514bdccb..116f97524 100644 --- a/platforms/adaptors/i2cbusadaptor_test.go +++ b/platforms/adaptors/i2cbusadaptor_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/system" ) @@ -33,22 +34,22 @@ func initTestI2cAdaptorWithMockedFilesystem(mockPaths []string) (*I2cBusAdaptor, func TestI2cWorkflow(t *testing.T) { a, _ := initTestI2cAdaptorWithMockedFilesystem([]string{i2cBus1}) - assert.Equal(t, 0, len(a.buses)) + assert.Empty(t, a.buses) con, err := a.GetI2cConnection(0xff, 1) - assert.NoError(t, err) - assert.Equal(t, 1, len(a.buses)) + require.NoError(t, err) + assert.Len(t, a.buses, 1) _, err = con.Write([]byte{0x00, 0x01}) - assert.NoError(t, err) + require.NoError(t, err) data := []byte{42, 42} _, err = con.Read(data) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []byte{0x00, 0x01}, data) - assert.NoError(t, a.Finalize()) - assert.Equal(t, 0, len(a.buses)) + require.NoError(t, a.Finalize()) + assert.Empty(t, a.buses) } func TestI2cGetI2cConnection(t *testing.T) { @@ -56,40 +57,40 @@ func TestI2cGetI2cConnection(t *testing.T) { a, _ := initTestI2cAdaptorWithMockedFilesystem([]string{i2cBus1}) // assert working connection c1, e1 := a.GetI2cConnection(0xff, 1) - assert.NoError(t, e1) + require.NoError(t, e1) assert.NotNil(t, c1) - assert.Equal(t, 1, len(a.buses)) + assert.Len(t, a.buses, 1) // assert invalid bus gets error c2, e2 := a.GetI2cConnection(0x01, 99) - assert.ErrorContains(t, e2, "99 not valid") + require.ErrorContains(t, e2, "99 not valid") assert.Nil(t, c2) - assert.Equal(t, 1, len(a.buses)) + assert.Len(t, a.buses, 1) // assert unconnected gets error - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) c3, e3 := a.GetI2cConnection(0x01, 99) - assert.ErrorContains(t, e3, "not connected") + require.ErrorContains(t, e3, "not connected") assert.Nil(t, c3) - assert.Equal(t, 0, len(a.buses)) + assert.Empty(t, a.buses) } func TestI2cFinalize(t *testing.T) { // arrange a, fs := initTestI2cAdaptorWithMockedFilesystem([]string{i2cBus1}) // assert that finalize before connect is working - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // arrange - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) _, _ = a.GetI2cConnection(0xaf, 1) - assert.Equal(t, 1, len(a.buses)) + assert.Len(t, a.buses, 1) // assert that Finalize after GetI2cConnection is working and clean up - assert.NoError(t, a.Finalize()) - assert.Equal(t, 0, len(a.buses)) + require.NoError(t, a.Finalize()) + assert.Empty(t, a.buses) // assert that finalize after finalize is working - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // assert that close error is recognized - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, _ := a.GetI2cConnection(0xbf, 1) - assert.Equal(t, 1, len(a.buses)) + assert.Len(t, a.buses, 1) _, _ = con.Write([]byte{0xbf}) fs.WithCloseError = true err := a.Finalize() @@ -99,12 +100,12 @@ func TestI2cFinalize(t *testing.T) { func TestI2cReConnect(t *testing.T) { // arrange a, _ := initTestI2cAdaptorWithMockedFilesystem([]string{i2cBus1}) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // act - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) // assert assert.NotNil(t, a.buses) - assert.Equal(t, 0, len(a.buses)) + assert.Empty(t, a.buses) } func TestI2cGetDefaultBus(t *testing.T) { diff --git a/platforms/adaptors/pwmpinsadaptor.go b/platforms/adaptors/pwmpinsadaptor.go index f1b88de91..b3a159fcf 100644 --- a/platforms/adaptors/pwmpinsadaptor.go +++ b/platforms/adaptors/pwmpinsadaptor.go @@ -21,9 +21,9 @@ type ( ) type pwmPinsOption interface { - setInitializer(pwmPinInitializer) - setDefaultPeriod(uint32) - setPolarityInvertedIdentifier(string) + setInitializer(initializer pwmPinInitializer) + setDefaultPeriod(period uint32) + setPolarityInvertedIdentifier(id string) } // PWMPinsAdaptor is a adaptor for PWM pins, normally used for composition in platforms. diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index 15ff4bc23..94d8d61ca 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/system" @@ -117,12 +118,12 @@ func TestPWMPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.PWMPinner)(nil), a.pins) err := a.PwmWrite("33", 1) - assert.ErrorContains(t, err, "not connected") + require.ErrorContains(t, err, "not connected") err = a.Connect() - assert.NoError(t, err) + require.NoError(t, err) assert.NotEqual(t, (map[string]gobot.PWMPinner)(nil), a.pins) - assert.Equal(t, 0, len(a.pins)) + assert.Empty(t, a.pins) } func TestPWMPinsFinalize(t *testing.T) { @@ -133,27 +134,27 @@ func TestPWMPinsFinalize(t *testing.T) { fs.Files[pwmPeriodPath].Contents = "0" fs.Files[pwmDutyCyclePath].Contents = "0" // assert that finalize before connect is working - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // arrange - assert.NoError(t, a.Connect()) - assert.NoError(t, a.PwmWrite("33", 1)) - assert.Equal(t, 1, len(a.pins)) + require.NoError(t, a.Connect()) + require.NoError(t, a.PwmWrite("33", 1)) + assert.Len(t, a.pins, 1) // act err := a.Finalize() // assert - assert.NoError(t, err) - assert.Equal(t, 0, len(a.pins)) + require.NoError(t, err) + assert.Empty(t, a.pins) // assert that finalize after finalize is working - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // arrange missing sysfs file - assert.NoError(t, a.Connect()) - assert.NoError(t, a.PwmWrite("33", 2)) + require.NoError(t, a.Connect()) + require.NoError(t, a.PwmWrite("33", 2)) delete(fs.Files, pwmUnexportPath) err = a.Finalize() assert.Contains(t, err.Error(), pwmUnexportPath+": no such file") // arrange write error - assert.NoError(t, a.Connect()) - assert.NoError(t, a.PwmWrite("33", 2)) + require.NoError(t, a.Connect()) + require.NoError(t, a.PwmWrite("33", 2)) fs.WithWriteError = true err = a.Finalize() assert.Contains(t, err.Error(), "write error") @@ -162,31 +163,31 @@ func TestPWMPinsFinalize(t *testing.T) { func TestPWMPinsReConnect(t *testing.T) { // arrange a, _ := initTestPWMPinsAdaptorWithMockedFilesystem(pwmMockPaths) - assert.NoError(t, a.PwmWrite("33", 1)) - assert.Equal(t, 1, len(a.pins)) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.PwmWrite("33", 1)) + assert.Len(t, a.pins, 1) + require.NoError(t, a.Finalize()) // act err := a.Connect() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, a.pins) - assert.Equal(t, 0, len(a.pins)) + assert.Empty(t, a.pins) } func TestPwmWrite(t *testing.T) { a, fs := initTestPWMPinsAdaptorWithMockedFilesystem(pwmMockPaths) err := a.PwmWrite("33", 100) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", a.periodDefault), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, fmt.Sprintf("%d", a.periodDefault), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.PwmWrite("notexist", 42) - assert.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") + require.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") fs.WithWriteError = true err = a.PwmWrite("33", 100) @@ -204,17 +205,17 @@ func TestServoWrite(t *testing.T) { err := a.ServoWrite("33", 0) assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", a.periodDefault), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, fmt.Sprintf("%d", a.periodDefault), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) - assert.NoError(t, err) + require.NoError(t, err) err = a.ServoWrite("33", 180) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("notexist", 42) - assert.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") + require.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") fs.WithWriteError = true err = a.ServoWrite("33", 100) @@ -233,25 +234,25 @@ func TestSetPeriod(t *testing.T) { // act err := a.SetPeriod("33", newPeriod) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here assert.Equal(t, "0", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("33", 127) // 127 is a little bit smaller than 50% of period - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 1270000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(1270000), fs.Files[pwmDutyCyclePath].Contents) newPeriod = newPeriod / 10 // act err = a.SetPeriod("33", newPeriod) // assert - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 127000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(127000), fs.Files[pwmDutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value newPeriod = newPeriod * 20 @@ -260,13 +261,13 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("33", newPeriod) // assert - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 2540000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(2540000), fs.Files[pwmDutyCyclePath].Contents) // act err = a.SetPeriod("not_exist", newPeriod) // assert - assert.ErrorContains(t, err, "'not_exist' is not a valid id of a PWM pin") + require.ErrorContains(t, err, "'not_exist' is not a valid id of a PWM pin") } func Test_PWMPin(t *testing.T) { @@ -346,7 +347,7 @@ func Test_PWMPin(t *testing.T) { got, err := a.PWMPin(tc.pin) // assert if tc.wantErr == "" { - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, got) } else { if !strings.Contains(err.Error(), tc.wantErr) { diff --git a/platforms/adaptors/spibusadaptor_test.go b/platforms/adaptors/spibusadaptor_test.go index 1b0f0d7d2..ac3ca2a07 100644 --- a/platforms/adaptors/spibusadaptor_test.go +++ b/platforms/adaptors/spibusadaptor_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2/drivers/spi" "gobot.io/x/gobot/v2/system" ) @@ -40,7 +41,7 @@ func TestNewSpiAdaptor(t *testing.T) { assert.Equal(t, 4, a.SpiDefaultBitCount()) assert.Equal(t, int64(5), a.SpiDefaultMaxSpeed()) _, err := a.GetSpiConnection(10, 0, 0, 8, 10000000) - assert.ErrorContains(t, err, "not connected") + require.ErrorContains(t, err, "not connected") } func TestGetSpiConnection(t *testing.T) { @@ -53,32 +54,32 @@ func TestGetSpiConnection(t *testing.T) { maxSpeed = int64(11) ) a, spi := initTestSpiBusAdaptorWithMockedSpi() - assert.Equal(t, 0, len(a.connections)) + assert.Empty(t, a.connections) // act con1, err1 := a.GetSpiConnection(busNum, chipNum, mode, bits, maxSpeed) // assert - assert.NoError(t, err1) + require.NoError(t, err1) assert.NotNil(t, con1) - assert.Equal(t, 1, len(a.connections)) + assert.Len(t, a.connections, 1) // assert cached connection con1a, err2 := a.GetSpiConnection(busNum, chipNum, mode, bits, maxSpeed) - assert.NoError(t, err2) + require.NoError(t, err2) assert.Equal(t, con1, con1a) - assert.Equal(t, 1, len(a.connections)) + assert.Len(t, a.connections, 1) // assert second connection con2, err3 := a.GetSpiConnection(busNum, chipNum+1, mode, bits, maxSpeed) - assert.NoError(t, err3) + require.NoError(t, err3) assert.NotNil(t, con2) assert.NotEqual(t, con1, con2) - assert.Equal(t, 2, len(a.connections)) + assert.Len(t, a.connections, 2) // assert bus validation error con, err := a.GetSpiConnection(busNum+1, chipNum, mode, bits, maxSpeed) - assert.ErrorContains(t, err, "16 not valid") + require.ErrorContains(t, err, "16 not valid") assert.Nil(t, con) // assert create error spi.CreateError = true con, err = a.GetSpiConnection(busNum, chipNum+2, mode, bits, maxSpeed) - assert.ErrorContains(t, err, "error while create SPI connection in mock") + require.ErrorContains(t, err, "error while create SPI connection in mock") assert.Nil(t, con) } @@ -86,20 +87,20 @@ func TestSpiFinalize(t *testing.T) { // arrange a, _ := initTestSpiBusAdaptorWithMockedSpi() _, e := a.GetSpiConnection(spiTestAllowedBus, 2, 3, 4, 5) - assert.NoError(t, e) - assert.Equal(t, 1, len(a.connections)) + require.NoError(t, e) + assert.Len(t, a.connections, 1) // act err := a.Finalize() // assert - assert.NoError(t, err) - assert.Equal(t, 0, len(a.connections)) + require.NoError(t, err) + assert.Empty(t, a.connections) } func TestSpiFinalizeWithError(t *testing.T) { // arrange a, spi := initTestSpiBusAdaptorWithMockedSpi() _, e := a.GetSpiConnection(spiTestAllowedBus, 2, 3, 4, 5) - assert.NoError(t, e) + require.NoError(t, e) spi.SetCloseError(true) // act err := a.Finalize() @@ -110,10 +111,10 @@ func TestSpiFinalizeWithError(t *testing.T) { func TestSpiReConnect(t *testing.T) { // arrange a, _ := initTestSpiBusAdaptorWithMockedSpi() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // act - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) // assert assert.NotNil(t, a.connections) - assert.Equal(t, 0, len(a.connections)) + assert.Empty(t, a.connections) } diff --git a/platforms/audio/audio_adaptor_test.go b/platforms/audio/audio_adaptor_test.go index 823cce510..1545515fe 100644 --- a/platforms/audio/audio_adaptor_test.go +++ b/platforms/audio/audio_adaptor_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -16,8 +17,8 @@ var _ gobot.Adaptor = (*Adaptor)(nil) func TestAudioAdaptor(t *testing.T) { a := NewAdaptor() - assert.NoError(t, a.Connect()) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Connect()) + require.NoError(t, a.Finalize()) } func TestAudioAdaptorName(t *testing.T) { @@ -40,7 +41,7 @@ func TestAudioAdaptorCommandsMp3(t *testing.T) { func TestAudioAdaptorCommandsUnknown(t *testing.T) { cmd, err := CommandName("whatever.unk") assert.NotEqual(t, "mpg123", cmd) - assert.ErrorContains(t, err, "Unknown filetype for audio file.") + require.ErrorContains(t, err, "Unknown filetype for audio file.") } func TestAudioAdaptorSoundWithNoFilename(t *testing.T) { @@ -65,7 +66,7 @@ func TestAudioAdaptorSoundWithValidMP3Filename(t *testing.T) { errors := a.Sound("../../examples/laser.mp3") - assert.Equal(t, 0, len(errors)) + assert.Empty(t, errors) } func myExecCommand(command string, args ...string) *exec.Cmd { diff --git a/platforms/audio/audio_driver_test.go b/platforms/audio/audio_driver_test.go index cf5de2195..88c5cde4c 100644 --- a/platforms/audio/audio_driver_test.go +++ b/platforms/audio/audio_driver_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -20,9 +21,9 @@ func TestAudioDriver(t *testing.T) { assert.NotNil(t, d.Connection()) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestAudioDriverName(t *testing.T) { @@ -46,5 +47,5 @@ func TestAudioDriverSoundWithDefaultFilename(t *testing.T) { d := NewDriver(NewAdaptor(), "../../examples/laser.mp3") errors := d.Play() - assert.Equal(t, 0, len(errors)) + assert.Empty(t, errors) } diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index c7bf5a487..f9d03362f 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" @@ -58,7 +59,7 @@ func TestPWM(t *testing.T) { fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents = "0" fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/period"].Contents = "0" - assert.ErrorContains(t, a.PwmWrite("P9_99", 175), "'P9_99' is not a valid id for a PWM pin") + require.ErrorContains(t, a.PwmWrite("P9_99", 175), "'P9_99' is not a valid id for a PWM pin") _ = a.PwmWrite("P9_21", 175) assert.Equal( t, @@ -83,7 +84,7 @@ func TestPWM(t *testing.T) { fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents, ) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestAnalog(t *testing.T) { @@ -96,17 +97,17 @@ func TestAnalog(t *testing.T) { fs.Files["/sys/bus/iio/devices/iio:device0/in_voltage1_raw"].Contents = "567\n" i, err := a.AnalogRead("P9_40") assert.Equal(t, 567, i) - assert.NoError(t, err) + require.NoError(t, err) _, err = a.AnalogRead("P9_99") - assert.ErrorContains(t, err, "Not a valid analog pin") + require.ErrorContains(t, err, "Not a valid analog pin") fs.WithReadError = true _, err = a.AnalogRead("P9_40") - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") fs.WithReadError = false - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestDigitalIO(t *testing.T) { @@ -138,22 +139,22 @@ func TestDigitalIO(t *testing.T) { // no such LED err := a.DigitalWrite("usr10101", 1) - assert.ErrorContains(t, err, " : /sys/class/leds/beaglebone:green:usr10101/brightness: no such file") + require.ErrorContains(t, err, " : /sys/class/leds/beaglebone:green:usr10101/brightness: no such file") _ = a.DigitalWrite("P9_12", 1) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio60/value"].Contents) - assert.ErrorContains(t, a.DigitalWrite("P9_99", 1), "'P9_99' is not a valid id for a digital pin") + require.ErrorContains(t, a.DigitalWrite("P9_99", 1), "'P9_99' is not a valid id for a digital pin") _, err = a.DigitalRead("P9_99") - assert.ErrorContains(t, err, "'P9_99' is not a valid id for a digital pin") + require.ErrorContains(t, err, "'P9_99' is not a valid id for a digital pin") fs.Files["/sys/class/gpio/gpio66/value"].Contents = "1" i, err := a.DigitalRead("P8_07") assert.Equal(t, 1, i) - assert.NoError(t, err) + require.NoError(t, err) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestName(t *testing.T) { @@ -188,7 +189,7 @@ func TestDigitalPinDirectionFileError(t *testing.T) { // no pin added after previous problem, so no pin to unexport in finalize err = a.Finalize() - assert.Equal(t, err, nil) + require.NoError(t, err) } func TestDigitalPinFinalizeFileError(t *testing.T) { @@ -202,7 +203,7 @@ func TestDigitalPinFinalizeFileError(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) err := a.DigitalWrite("P9_12", 1) - assert.NoError(t, err) + require.NoError(t, err) err = a.Finalize() assert.Contains(t, err.Error(), "/sys/class/gpio/unexport: no such file") @@ -233,11 +234,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-2"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 2) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/ble/battery_driver_test.go b/platforms/ble/battery_driver_test.go index 8280d8a1c..70ee9d133 100644 --- a/platforms/ble/battery_driver_test.go +++ b/platforms/ble/battery_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -24,8 +25,8 @@ func TestBatteryDriver(t *testing.T) { func TestBatteryDriverStartAndHalt(t *testing.T) { d := initTestBatteryDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestBatteryDriverRead(t *testing.T) { diff --git a/platforms/ble/ble_client_adaptor.go b/platforms/ble/ble_client_adaptor.go index 8af9419dc..d3a270e0a 100644 --- a/platforms/ble/ble_client_adaptor.go +++ b/platforms/ble/ble_client_adaptor.go @@ -18,17 +18,16 @@ var ( // BLEConnector is the interface that a BLE ClientAdaptor must implement type BLEConnector interface { - Connect() error + gobot.Adaptor + Reconnect() error Disconnect() error - Finalize() error - Name() string - SetName(string) Address() string - ReadCharacteristic(string) ([]byte, error) - WriteCharacteristic(string, []byte) error - Subscribe(string, func([]byte, error)) error - WithoutResponses(bool) + + ReadCharacteristic(cUUID string) ([]byte, error) + WriteCharacteristic(cUUID string, data []byte) error + Subscribe(cUUID string, f func([]byte, error)) error + WithoutResponses(use bool) } // ClientAdaptor represents a Client Connection to a BLE Peripheral diff --git a/platforms/ble/device_information_driver_test.go b/platforms/ble/device_information_driver_test.go index 1a8234c51..72b14a908 100644 --- a/platforms/ble/device_information_driver_test.go +++ b/platforms/ble/device_information_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -24,8 +25,8 @@ func TestDeviceInformationDriver(t *testing.T) { func TestDeviceInformationDriverStartAndHalt(t *testing.T) { d := initTestDeviceInformationDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestDeviceInformationDriverGetModelNumber(t *testing.T) { diff --git a/platforms/ble/generic_access_driver_test.go b/platforms/ble/generic_access_driver_test.go index 8c5c90120..9b09d6435 100644 --- a/platforms/ble/generic_access_driver_test.go +++ b/platforms/ble/generic_access_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -24,8 +25,8 @@ func TestGenericAccessDriver(t *testing.T) { func TestGenericAccessDriverStartAndHalt(t *testing.T) { d := initTestGenericAccessDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestGenericAccessDriverGetDeviceName(t *testing.T) { diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index b5710e218..f8dc92ee2 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -71,8 +72,8 @@ func TestNewProAdaptor(t *testing.T) { func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() - assert.NoError(t, a.Connect()) - assert.NoError(t, a.DigitalWrite("CSID7", 1)) + require.NoError(t, a.Connect()) + require.NoError(t, a.DigitalWrite("CSID7", 1)) fs.WithWriteError = true @@ -85,8 +86,8 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" - assert.NoError(t, a.Connect()) - assert.NoError(t, a.PwmWrite("PWM0", 100)) + require.NoError(t, a.Connect()) + require.NoError(t, a.PwmWrite("PWM0", 100)) fs.WithWriteError = true @@ -105,8 +106,8 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("TWI2-SDA") assert.Equal(t, 1, i) - assert.ErrorContains(t, a.DigitalWrite("XIO-P10", 1), "'XIO-P10' is not a valid id for a digital pin") - assert.NoError(t, a.Finalize()) + require.ErrorContains(t, a.DigitalWrite("XIO-P10", 1), "'XIO-P10' is not a valid id for a digital pin") + require.NoError(t, a.Finalize()) } func TestProDigitalIO(t *testing.T) { @@ -120,8 +121,8 @@ func TestProDigitalIO(t *testing.T) { i, _ := a.DigitalRead("TWI2-SDA") assert.Equal(t, 1, i) - assert.ErrorContains(t, a.DigitalWrite("XIO-P0", 1), "'XIO-P0' is not a valid id for a digital pin") - assert.NoError(t, a.Finalize()) + require.ErrorContains(t, a.DigitalWrite("XIO-P0", 1), "'XIO-P0' is not a valid id for a digital pin") + require.NoError(t, a.Finalize()) } func TestPWM(t *testing.T) { @@ -132,7 +133,7 @@ func TestPWM(t *testing.T) { _ = a.Connect() err := a.PwmWrite("PWM0", 100) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "0", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents) @@ -141,18 +142,18 @@ func TestPWM(t *testing.T) { assert.Equal(t, "normal", fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents) err = a.ServoWrite("PWM0", 0) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) err = a.ServoWrite("PWM0", 180) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "2000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestI2cDefaultBus(t *testing.T) { @@ -165,11 +166,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-2"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 2) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/dexter/gopigo3/driver_test.go b/platforms/dexter/gopigo3/driver_test.go index ceb6982a8..10e20658d 100644 --- a/platforms/dexter/gopigo3/driver_test.go +++ b/platforms/dexter/gopigo3/driver_test.go @@ -4,7 +4,7 @@ import ( "encoding/hex" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/spi" ) @@ -22,12 +22,12 @@ func initTestDriver() *Driver { func TestDriverStart(t *testing.T) { d := initTestDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestDriverHalt(t *testing.T) { d := initTestDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestDriverManufacturerName(t *testing.T) { diff --git a/platforms/digispark/digispark_adaptor_test.go b/platforms/digispark/digispark_adaptor_test.go index 59c6105a1..2c1610d58 100644 --- a/platforms/digispark/digispark_adaptor_test.go +++ b/platforms/digispark/digispark_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" ) @@ -92,56 +93,56 @@ func TestDigisparkAdaptorName(t *testing.T) { func TestDigisparkAdaptorConnect(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) } func TestDigisparkAdaptorFinalize(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestDigisparkAdaptorDigitalWrite(t *testing.T) { a := initTestAdaptor() err := a.DigitalWrite("0", uint8(1)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uint8(0), a.littleWire.(*mock).pin) assert.Equal(t, uint8(1), a.littleWire.(*mock).state) err = a.DigitalWrite("?", uint8(1)) - assert.NotNil(t, err) + require.Error(t, err) errorFunc = func() error { return errors.New("pin mode error") } err = a.DigitalWrite("0", uint8(1)) - assert.ErrorContains(t, err, "pin mode error") + require.ErrorContains(t, err, "pin mode error") } func TestDigisparkAdaptorServoWrite(t *testing.T) { a := initTestAdaptor() err := a.ServoWrite("2", uint8(80)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uint8(80), a.littleWire.(*mock).locationA) assert.Equal(t, uint8(80), a.littleWire.(*mock).locationB) a = initTestAdaptor() errorFunc = func() error { return errors.New("servo error") } err = a.ServoWrite("2", uint8(80)) - assert.ErrorContains(t, err, "servo error") + require.ErrorContains(t, err, "servo error") } func TestDigisparkAdaptorPwmWrite(t *testing.T) { a := initTestAdaptor() err := a.PwmWrite("1", uint8(100)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uint8(100), a.littleWire.(*mock).pwmChannelA) assert.Equal(t, uint8(100), a.littleWire.(*mock).pwmChannelB) a = initTestAdaptor() pwmInitErrorFunc = func() error { return errors.New("pwminit error") } err = a.PwmWrite("1", uint8(100)) - assert.ErrorContains(t, err, "pwminit error") + require.ErrorContains(t, err, "pwminit error") a = initTestAdaptor() errorFunc = func() error { return errors.New("pwm error") } err = a.PwmWrite("1", uint8(100)) - assert.ErrorContains(t, err, "pwm error") + require.ErrorContains(t, err, "pwm error") } diff --git a/platforms/digispark/digispark_i2c_test.go b/platforms/digispark/digispark_i2c_test.go index 5019cc160..ff6412255 100644 --- a/platforms/digispark/digispark_i2c_test.go +++ b/platforms/digispark/digispark_i2c_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2/drivers/i2c" ) @@ -45,7 +46,7 @@ func TestDigisparkAdaptorI2cGetI2cConnection(t *testing.T) { c, err = a.GetI2cConnection(availableI2cAddress, a.DefaultI2cBus()) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, c) } @@ -57,7 +58,7 @@ func TestDigisparkAdaptorI2cGetI2cConnectionFailWithInvalidBus(t *testing.T) { c, err := a.GetI2cConnection(0x40, 1) // assert - assert.ErrorContains(t, err, "Invalid bus number 1, only 0 is supported") + require.ErrorContains(t, err, "Invalid bus number 1, only 0 is supported") assert.Nil(t, c) } @@ -72,7 +73,7 @@ func TestDigisparkAdaptorI2cStartFailWithWrongAddress(t *testing.T) { // assert assert.Equal(t, 0, count) - assert.ErrorContains(t, err, fmt.Sprintf("Invalid address, only %d is supported", availableI2cAddress)) + require.ErrorContains(t, err, fmt.Sprintf("Invalid address, only %d is supported", availableI2cAddress)) assert.Equal(t, maxUint8, a.littleWire.(*i2cMock).direction) } @@ -87,7 +88,7 @@ func TestDigisparkAdaptorI2cWrite(t *testing.T) { count, err := c.Write(data) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -107,7 +108,7 @@ func TestDigisparkAdaptorI2cWriteByte(t *testing.T) { err := c.WriteByte(data) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -127,7 +128,7 @@ func TestDigisparkAdaptorI2cWriteByteData(t *testing.T) { err := c.WriteByteData(reg, data) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -147,7 +148,7 @@ func TestDigisparkAdaptorI2cWriteWordData(t *testing.T) { err := c.WriteWordData(reg, data) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -167,7 +168,7 @@ func TestDigisparkAdaptorI2cWriteBlockData(t *testing.T) { err := c.WriteBlockData(reg, data) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.False(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(0), a.littleWire.(*i2cMock).direction) @@ -188,7 +189,7 @@ func TestDigisparkAdaptorI2cRead(t *testing.T) { // assert assert.Equal(t, dataLen, count) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -206,7 +207,7 @@ func TestDigisparkAdaptorI2cReadByte(t *testing.T) { data, err := c.ReadByte() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -225,7 +226,7 @@ func TestDigisparkAdaptorI2cReadByteData(t *testing.T) { data, err := c.ReadByteData(reg) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -247,7 +248,7 @@ func TestDigisparkAdaptorI2cReadWordData(t *testing.T) { data, err := c.ReadWordData(reg) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -269,7 +270,7 @@ func TestDigisparkAdaptorI2cReadBlockData(t *testing.T) { err := c.ReadBlockData(reg, data) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, a.littleWire.(*i2cMock).writeStartWasSend) assert.True(t, a.littleWire.(*i2cMock).readStartWasSend) assert.Equal(t, uint8(1), a.littleWire.(*i2cMock).direction) @@ -288,7 +289,7 @@ func TestDigisparkAdaptorI2cUpdateDelay(t *testing.T) { err := c.(*digisparkI2cConnection).UpdateDelay(uint(100)) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uint(100), a.littleWire.(*i2cMock).duration) } diff --git a/platforms/digispark/littleWire.go b/platforms/digispark/littleWire.go index 0f2236835..f88c8990b 100644 --- a/platforms/digispark/littleWire.go +++ b/platforms/digispark/littleWire.go @@ -12,14 +12,14 @@ import ( ) type lw interface { - digitalWrite(uint8, uint8) error - pinMode(uint8, uint8) error + digitalWrite(pin uint8, state uint8) error + pinMode(pin uint8, mode uint8) error pwmInit() error pwmStop() error - pwmUpdateCompare(uint8, uint8) error - pwmUpdatePrescaler(uint) error + pwmUpdateCompare(channelA uint8, channelb uint8) error + pwmUpdatePrescaler(value uint) error servoInit() error - servoUpdateLocation(uint8, uint8) error + servoUpdateLocation(locationA uint8, locationB uint8) error i2cInit() error i2cStart(address7bit uint8, direction uint8) error i2cWrite(sendBuffer []byte, length int, endWithStop uint8) error diff --git a/platforms/dragonboard/dragonboard_adaptor_test.go b/platforms/dragonboard/dragonboard_adaptor_test.go index b0b9c6e2f..d6c8fe4b0 100644 --- a/platforms/dragonboard/dragonboard_adaptor_test.go +++ b/platforms/dragonboard/dragonboard_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -54,8 +55,8 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("GPIO_A") assert.Equal(t, 1, i) - assert.ErrorContains(t, a.DigitalWrite("GPIO_M", 1), "'GPIO_M' is not a valid id for a digital pin") - assert.NoError(t, a.Finalize()) + require.ErrorContains(t, a.DigitalWrite("GPIO_M", 1), "'GPIO_M' is not a valid id for a digital pin") + require.NoError(t, a.Finalize()) } func TestFinalizeErrorAfterGPIO(t *testing.T) { @@ -70,8 +71,8 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { } fs := a.sys.UseMockFilesystem(mockPaths) - assert.NoError(t, a.Connect()) - assert.NoError(t, a.DigitalWrite("GPIO_B", 1)) + require.NoError(t, a.Connect()) + require.NoError(t, a.DigitalWrite("GPIO_B", 1)) fs.WithWriteError = true @@ -89,11 +90,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/firmata/client/client_test.go b/platforms/firmata/client/client_test.go index ca559ad37..0bf1690e4 100644 --- a/platforms/firmata/client/client_test.go +++ b/platforms/firmata/client/client_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const semPublishWait = 10 * time.Millisecond @@ -114,23 +115,23 @@ func initTestFirmataWithReadWriteCloser(name string, data ...[]byte) (*Client, r func TestPins(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name(), testDataCapabilitiesResponse, testDataAnalogMappingResponse) - assert.Equal(t, 20, len(b.Pins())) - assert.Equal(t, 6, len(b.analogPins)) + assert.Len(t, b.Pins(), 20) + assert.Len(t, b.analogPins, 6) } func TestProtocolVersionQuery(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.NoError(t, b.ProtocolVersionQuery()) + require.NoError(t, b.ProtocolVersionQuery()) } func TestFirmwareQuery(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.NoError(t, b.FirmwareQuery()) + require.NoError(t, b.FirmwareQuery()) } func TestPinStateQuery(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.NoError(t, b.PinStateQuery(1)) + require.NoError(t, b.PinStateQuery(1)) } func TestProcessProtocolVersion(t *testing.T) { @@ -232,23 +233,23 @@ func TestProcessDigitalRead4(t *testing.T) { func TestDigitalWrite(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name(), testDataCapabilitiesResponse) - assert.NoError(t, b.DigitalWrite(13, 0)) + require.NoError(t, b.DigitalWrite(13, 0)) } func TestSetPinMode(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name(), testDataCapabilitiesResponse) - assert.NoError(t, b.SetPinMode(13, Output)) + require.NoError(t, b.SetPinMode(13, Output)) } func TestAnalogWrite(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name(), testDataCapabilitiesResponse) - assert.NoError(t, b.AnalogWrite(0, 128)) + require.NoError(t, b.AnalogWrite(0, 128)) } func TestReportAnalog(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.NoError(t, b.ReportAnalog(0, 1)) - assert.NoError(t, b.ReportAnalog(0, 0)) + require.NoError(t, b.ReportAnalog(0, 1)) + require.NoError(t, b.ReportAnalog(0, 0)) } func TestProcessPinState13(t *testing.T) { @@ -272,22 +273,22 @@ func TestProcessPinState13(t *testing.T) { func TestI2cConfig(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.NoError(t, b.I2cConfig(100)) + require.NoError(t, b.I2cConfig(100)) } func TestI2cWrite(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.NoError(t, b.I2cWrite(0x00, []byte{0x01, 0x02})) + require.NoError(t, b.I2cWrite(0x00, []byte{0x01, 0x02})) } func TestI2cRead(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.NoError(t, b.I2cRead(0x00, 10)) + require.NoError(t, b.I2cRead(0x00, 10)) } func TestWriteSysex(t *testing.T) { b, _ := initTestFirmataWithReadWriteCloser(t.Name()) - assert.NoError(t, b.WriteSysex([]byte{0x01, 0x02})) + require.NoError(t, b.WriteSysex([]byte{0x01, 0x02})) } func TestProcessI2cReply(t *testing.T) { @@ -373,9 +374,9 @@ func TestConnect(t *testing.T) { rwc.addTestReadData(testDataProtocolResponse) }) - assert.NoError(t, b.Connect(rwc)) + require.NoError(t, b.Connect(rwc)) time.Sleep(150 * time.Millisecond) - assert.NoError(t, b.Disconnect()) + require.NoError(t, b.Disconnect()) } func TestServoConfig(t *testing.T) { diff --git a/platforms/firmata/firmata_adaptor.go b/platforms/firmata/firmata_adaptor.go index ddd06751e..4246b14d2 100644 --- a/platforms/firmata/firmata_adaptor.go +++ b/platforms/firmata/firmata_adaptor.go @@ -16,18 +16,18 @@ import ( ) type firmataBoard interface { - Connect(io.ReadWriteCloser) error + Connect(conn io.ReadWriteCloser) error Disconnect() error Pins() []client.Pin - AnalogWrite(int, int) error - SetPinMode(int, int) error - ReportAnalog(int, int) error - ReportDigital(int, int) error - DigitalWrite(int, int) error - I2cRead(int, int) error - I2cWrite(int, []byte) error - I2cConfig(int) error - ServoConfig(int, int, int) error + AnalogWrite(pin int, value int) (err error) + SetPinMode(pin int, mode int) error + ReportAnalog(pin int, state int) error + ReportDigital(pin int, state int) error + DigitalWrite(pin int, value int) error + I2cRead(address int, numBytes int) error + I2cWrite(address int, data []byte) error + I2cConfig(delay int) error + ServoConfig(pin int, max int, min int) error WriteSysex(data []byte) error gobot.Eventer } diff --git a/platforms/firmata/firmata_adaptor_test.go b/platforms/firmata/firmata_adaptor_test.go index fa095c193..23ecf4591 100644 --- a/platforms/firmata/firmata_adaptor_test.go +++ b/platforms/firmata/firmata_adaptor_test.go @@ -6,12 +6,11 @@ package firmata import ( "bytes" "errors" - "fmt" "io" - "strings" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" @@ -114,11 +113,11 @@ func TestNewAdaptor(t *testing.T) { func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) a = initTestAdaptor() a.Board.(*mockFirmataBoard).disconnectError = errors.New("close error") - assert.ErrorContains(t, a.Finalize(), "close error") + require.ErrorContains(t, a.Finalize(), "close error") } func TestAdaptorConnect(t *testing.T) { @@ -128,94 +127,94 @@ func TestAdaptorConnect(t *testing.T) { a := NewAdaptor("/dev/null") a.PortOpener = openSP a.Board = newMockFirmataBoard() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a = NewAdaptor("/dev/null") a.Board = newMockFirmataBoard() a.PortOpener = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - assert.ErrorContains(t, a.Connect(), "connect error") + require.ErrorContains(t, a.Connect(), "connect error") a = NewAdaptor(&readWriteCloser{}) a.Board = newMockFirmataBoard() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a = NewAdaptor("/dev/null") a.Board = nil - assert.NoError(t, a.Disconnect()) + require.NoError(t, a.Disconnect()) } func TestAdaptorServoWrite(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.ServoWrite("1", 50)) + require.NoError(t, a.ServoWrite("1", 50)) } func TestAdaptorServoWriteBadPin(t *testing.T) { a := initTestAdaptor() - assert.NotNil(t, a.ServoWrite("xyz", 50)) + require.Error(t, a.ServoWrite("xyz", 50)) } func TestAdaptorPwmWrite(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.PwmWrite("1", 50)) + require.NoError(t, a.PwmWrite("1", 50)) } func TestAdaptorPwmWriteBadPin(t *testing.T) { a := initTestAdaptor() - assert.NotNil(t, a.PwmWrite("xyz", 50)) + require.Error(t, a.PwmWrite("xyz", 50)) } func TestAdaptorDigitalWrite(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.DigitalWrite("1", 1)) + require.NoError(t, a.DigitalWrite("1", 1)) } func TestAdaptorDigitalWriteBadPin(t *testing.T) { a := initTestAdaptor() - assert.NotNil(t, a.DigitalWrite("xyz", 50)) + require.Error(t, a.DigitalWrite("xyz", 50)) } func TestAdaptorDigitalRead(t *testing.T) { a := initTestAdaptor() val, err := a.DigitalRead("1") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, val) val, err = a.DigitalRead("0") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 0, val) } func TestAdaptorDigitalReadBadPin(t *testing.T) { a := initTestAdaptor() _, err := a.DigitalRead("xyz") - assert.NotNil(t, err) + require.Error(t, err) } func TestAdaptorAnalogRead(t *testing.T) { a := initTestAdaptor() val, err := a.AnalogRead("1") assert.Equal(t, 133, val) - assert.NoError(t, err) + require.NoError(t, err) val, err = a.AnalogRead("0") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 0, val) } func TestAdaptorAnalogReadBadPin(t *testing.T) { a := initTestAdaptor() _, err := a.AnalogRead("xyz") - assert.NotNil(t, err) + require.Error(t, err) } func TestServoConfig(t *testing.T) { a := initTestAdaptor() err := a.ServoConfig("9", 0, 0) - assert.NoError(t, err) + require.NoError(t, err) // test atoi error err = a.ServoConfig("a", 0, 0) - assert.Equal(t, strings.Contains(fmt.Sprintf("%v", err), "invalid syntax"), true) + require.ErrorContains(t, err, "invalid syntax") } diff --git a/platforms/firmata/firmata_i2c_test.go b/platforms/firmata/firmata_i2c_test.go index cf9142998..4a12040ec 100644 --- a/platforms/firmata/firmata_i2c_test.go +++ b/platforms/firmata/firmata_i2c_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/platforms/firmata/client" @@ -75,7 +76,7 @@ func initTestTestAdaptorWithI2cConnection() (i2c.Connection, *i2cMockFirmataBoar func TestClose(t *testing.T) { i2c, _ := initTestTestAdaptorWithI2cConnection() - assert.NoError(t, i2c.Close()) + require.NoError(t, i2c.Close()) } func TestRead(t *testing.T) { @@ -85,11 +86,11 @@ func TestRead(t *testing.T) { buf := []byte{0} // act countRead, err := con.Read(buf) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, countRead) assert.Equal(t, 1, brd.numBytesToRead) assert.Equal(t, brd.i2cDataForRead, buf) - assert.Equal(t, 0, len(brd.i2cWritten)) + assert.Empty(t, brd.i2cWritten) } func TestReadByte(t *testing.T) { @@ -99,10 +100,10 @@ func TestReadByte(t *testing.T) { // act val, err := con.ReadByte() // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, brd.numBytesToRead) assert.Equal(t, brd.i2cDataForRead[0], val) - assert.Equal(t, 0, len(brd.i2cWritten)) + assert.Empty(t, brd.i2cWritten) } func TestReadByteData(t *testing.T) { @@ -113,10 +114,10 @@ func TestReadByteData(t *testing.T) { // act val, err := con.ReadByteData(reg) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, brd.numBytesToRead) assert.Equal(t, brd.i2cDataForRead[0], val) - assert.Equal(t, 1, len(brd.i2cWritten)) + assert.Len(t, brd.i2cWritten, 1) assert.Equal(t, reg, brd.i2cWritten[0]) } @@ -130,10 +131,10 @@ func TestReadWordData(t *testing.T) { // act val, err := con.ReadWordData(reg) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 2, brd.numBytesToRead) assert.Equal(t, uint16(lsb)|uint16(msb)<<8, val) - assert.Equal(t, 1, len(brd.i2cWritten)) + assert.Len(t, brd.i2cWritten, 1) assert.Equal(t, reg, brd.i2cWritten[0]) } @@ -146,10 +147,10 @@ func TestReadBlockData(t *testing.T) { // act err := con.ReadBlockData(reg, buf) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 5, brd.numBytesToRead) assert.Equal(t, brd.i2cDataForRead, buf) - assert.Equal(t, 1, len(brd.i2cWritten)) + assert.Len(t, brd.i2cWritten, 1) assert.Equal(t, reg, brd.i2cWritten[0]) } @@ -161,7 +162,7 @@ func TestWrite(t *testing.T) { // act written, err := con.Write(want) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, wantLen, written) assert.Equal(t, want, brd.i2cWritten) } @@ -174,7 +175,7 @@ func TestWrite20bytes(t *testing.T) { // act written, err := con.Write(want) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, wantLen, written) assert.Equal(t, want, brd.i2cWritten) } @@ -186,8 +187,8 @@ func TestWriteByte(t *testing.T) { // act err := con.WriteByte(want) // assert - assert.NoError(t, err) - assert.Equal(t, 1, len(brd.i2cWritten)) + require.NoError(t, err) + assert.Len(t, brd.i2cWritten, 1) assert.Equal(t, want, brd.i2cWritten[0]) } @@ -199,8 +200,8 @@ func TestWriteByteData(t *testing.T) { // act err := con.WriteByteData(reg, val) // assert - assert.NoError(t, err) - assert.Equal(t, 2, len(brd.i2cWritten)) + require.NoError(t, err) + assert.Len(t, brd.i2cWritten, 2) assert.Equal(t, reg, brd.i2cWritten[0]) assert.Equal(t, val, brd.i2cWritten[1]) } @@ -213,8 +214,8 @@ func TestWriteWordData(t *testing.T) { // act err := con.WriteWordData(reg, val) // assert - assert.NoError(t, err) - assert.Equal(t, 3, len(brd.i2cWritten)) + require.NoError(t, err) + assert.Len(t, brd.i2cWritten, 3) assert.Equal(t, reg, brd.i2cWritten[0]) assert.Equal(t, uint8(val&0x00FF), brd.i2cWritten[1]) assert.Equal(t, uint8(val>>8), brd.i2cWritten[2]) @@ -232,8 +233,8 @@ func TestWriteBlockData(t *testing.T) { // act err := con.WriteBlockData(reg, val) // assert - assert.NoError(t, err) - assert.Equal(t, 33, len(brd.i2cWritten)) + require.NoError(t, err) + assert.Len(t, brd.i2cWritten, 33) assert.Equal(t, reg, brd.i2cWritten[0]) assert.Equal(t, val[0:32], brd.i2cWritten[1:]) } @@ -246,5 +247,5 @@ func TestDefaultBus(t *testing.T) { func TestGetI2cConnectionInvalidBus(t *testing.T) { a := NewAdaptor() _, err := a.GetI2cConnection(0x01, 99) - assert.ErrorContains(t, err, "Invalid bus number 99, only 0 is supported") + require.ErrorContains(t, err, "Invalid bus number 99, only 0 is supported") } diff --git a/platforms/intel-iot/curie/imu_driver_test.go b/platforms/intel-iot/curie/imu_driver_test.go index 4e9a21ccd..051112fab 100644 --- a/platforms/intel-iot/curie/imu_driver_test.go +++ b/platforms/intel-iot/curie/imu_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/firmata" @@ -91,12 +92,12 @@ func initTestIMUDriver() *IMUDriver { func TestIMUDriverStart(t *testing.T) { d := initTestIMUDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestIMUDriverHalt(t *testing.T) { d := initTestIMUDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestIMUDriverDefaultName(t *testing.T) { @@ -118,105 +119,105 @@ func TestIMUDriverConnection(t *testing.T) { func TestIMUDriverReadAccelerometer(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.NoError(t, d.ReadAccelerometer()) + require.NoError(t, d.ReadAccelerometer()) } func TestIMUDriverReadAccelerometerData(t *testing.T) { _, err := parseAccelerometerData([]byte{}) - assert.ErrorContains(t, err, "Invalid data") + require.ErrorContains(t, err, "Invalid data") result, err := parseAccelerometerData([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, &AccelerometerData{X: 1920, Y: 1920, Z: 1920}, result) } func TestIMUDriverReadGyroscope(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.NoError(t, d.ReadGyroscope()) + require.NoError(t, d.ReadGyroscope()) } func TestIMUDriverReadGyroscopeData(t *testing.T) { _, err := parseGyroscopeData([]byte{}) - assert.ErrorContains(t, err, "Invalid data") + require.ErrorContains(t, err, "Invalid data") result, err := parseGyroscopeData([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, &GyroscopeData{X: 1920, Y: 1920, Z: 1920}, result) } func TestIMUDriverReadTemperature(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.NoError(t, d.ReadTemperature()) + require.NoError(t, d.ReadTemperature()) } func TestIMUDriverReadTemperatureData(t *testing.T) { _, err := parseTemperatureData([]byte{}) - assert.ErrorContains(t, err, "Invalid data") + require.ErrorContains(t, err, "Invalid data") result, err := parseTemperatureData([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7}) - assert.NoError(t, err) - assert.Equal(t, float32(31.546875), result) + require.NoError(t, err) + assert.InDelta(t, float32(31.546875), result, 0.0) } func TestIMUDriverEnableShockDetection(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.NoError(t, d.EnableShockDetection(true)) + require.NoError(t, d.EnableShockDetection(true)) } func TestIMUDriverShockDetectData(t *testing.T) { _, err := parseShockData([]byte{}) - assert.ErrorContains(t, err, "Invalid data") + require.ErrorContains(t, err, "Invalid data") result, err := parseShockData([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, &ShockData{Axis: 0, Direction: 2}, result) } func TestIMUDriverEnableStepCounter(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.NoError(t, d.EnableStepCounter(true)) + require.NoError(t, d.EnableStepCounter(true)) } func TestIMUDriverStepCountData(t *testing.T) { _, err := parseStepData([]byte{}) - assert.ErrorContains(t, err, "Invalid data") + require.ErrorContains(t, err, "Invalid data") result, err := parseStepData([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int16(256), result) } func TestIMUDriverEnableTapDetection(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.NoError(t, d.EnableTapDetection(true)) + require.NoError(t, d.EnableTapDetection(true)) } func TestIMUDriverTapDetectData(t *testing.T) { _, err := parseTapData([]byte{}) - assert.ErrorContains(t, err, "Invalid data") + require.ErrorContains(t, err, "Invalid data") result, err := parseTapData([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, &TapData{Axis: 0, Direction: 2}, result) } func TestIMUDriverEnableReadMotion(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.NoError(t, d.ReadMotion()) + require.NoError(t, d.ReadMotion()) } func TestIMUDriverReadMotionData(t *testing.T) { _, err := parseMotionData([]byte{}) - assert.ErrorContains(t, err, "Invalid data") + require.ErrorContains(t, err, "Invalid data") result, err := parseMotionData([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, &MotionData{AX: 1920, AY: 1920, AZ: 1920, GX: 1920, GY: 1920, GZ: 1920}, result) } @@ -224,11 +225,11 @@ func TestIMUDriverHandleEvents(t *testing.T) { d := initTestIMUDriver() _ = d.Start() - assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) - assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) - assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7})) - assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7})) - assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7})) - assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7})) - assert.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x02, 0x00, 0x02, 0x03, 0x04, 0xf7})) + require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7})) + require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7})) + require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7})) + require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) } diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index e4e998b79..64a2a7b6e 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" @@ -235,7 +236,7 @@ func TestConnect(t *testing.T) { assert.Equal(t, 6, a.DefaultI2cBus()) assert.Equal(t, "arduino", a.board) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) } func TestArduinoSetupFail263(t *testing.T) { @@ -272,17 +273,17 @@ func TestArduinoSetupFail131(t *testing.T) { func TestArduinoI2CSetupFailTristate(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.NoError(t, a.arduinoSetup()) + require.NoError(t, a.arduinoSetup()) fs.WithWriteError = true err := a.arduinoI2CSetup() - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestArduinoI2CSetupFail14(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.NoError(t, a.arduinoSetup()) + require.NoError(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/gpio14/direction") err := a.arduinoI2CSetup() @@ -292,7 +293,7 @@ func TestArduinoI2CSetupFail14(t *testing.T) { func TestArduinoI2CSetupUnexportFail(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.NoError(t, a.arduinoSetup()) + require.NoError(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/unexport") err := a.arduinoI2CSetup() @@ -302,7 +303,7 @@ func TestArduinoI2CSetupUnexportFail(t *testing.T) { func TestArduinoI2CSetupFail236(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.NoError(t, a.arduinoSetup()) + require.NoError(t, a.arduinoSetup()) delete(fs.Files, "/sys/class/gpio/gpio236/direction") err := a.arduinoI2CSetup() @@ -312,7 +313,7 @@ func TestArduinoI2CSetupFail236(t *testing.T) { func TestArduinoI2CSetupFail28(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - assert.NoError(t, a.arduinoSetup()) + require.NoError(t, a.arduinoSetup()) delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux") err := a.arduinoI2CSetup() @@ -338,7 +339,7 @@ func TestConnectArduinoWriteError(t *testing.T) { func TestConnectSparkfun(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem("sparkfun") - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) assert.Equal(t, 1, a.DefaultI2cBus()) assert.Equal(t, "sparkfun", a.board) } @@ -346,7 +347,7 @@ func TestConnectSparkfun(t *testing.T) { func TestConnectMiniboard(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem("miniboard") - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) assert.Equal(t, 1, a.DefaultI2cBus()) assert.Equal(t, "miniboard", a.board) } @@ -365,10 +366,10 @@ func TestFinalize(t *testing.T) { _ = a.PwmWrite("5", 100) _, _ = a.GetI2cConnection(0xff, 6) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // assert that finalize after finalize is working - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // assert that re-connect is working _ = a.Connect() @@ -400,7 +401,7 @@ func TestDigitalIO(t *testing.T) { _ = a.DigitalWrite("2", 0) i, err := a.DigitalRead("2") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 0, i) } @@ -453,7 +454,7 @@ func TestDigitalWriteError(t *testing.T) { fs.WithWriteError = true err := a.DigitalWrite("13", 1) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestDigitalReadWriteError(t *testing.T) { @@ -461,18 +462,18 @@ func TestDigitalReadWriteError(t *testing.T) { fs.WithWriteError = true _, err := a.DigitalRead("13") - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestPwm(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") err := a.PwmWrite("5", 100) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "1960", fs.Files["/sys/class/pwm/pwmchip0/pwm1/duty_cycle"].Contents) err = a.PwmWrite("7", 100) - assert.ErrorContains(t, err, "'7' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'7' is not a valid id for a PWM pin") } func TestPwmExportError(t *testing.T) { @@ -480,7 +481,7 @@ func TestPwmExportError(t *testing.T) { fs := a.sys.UseMockFilesystem(pwmMockPathsMux13Arduino) delete(fs.Files, "/sys/class/pwm/pwmchip0/export") err := a.Connect() - assert.NoError(t, err) + require.NoError(t, err) err = a.PwmWrite("5", 100) assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/export: no such file") @@ -501,7 +502,7 @@ func TestPwmWritePinError(t *testing.T) { fs.WithWriteError = true err := a.PwmWrite("5", 100) - assert.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "write error") } func TestPwmWriteError(t *testing.T) { @@ -533,7 +534,7 @@ func TestAnalogError(t *testing.T) { fs.WithReadError = true _, err := a.AnalogRead("0") - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } func TestI2cWorkflow(t *testing.T) { @@ -541,17 +542,17 @@ func TestI2cWorkflow(t *testing.T) { a.sys.UseMockSyscall() con, err := a.GetI2cConnection(0xff, 6) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0x00, 0x01}) - assert.NoError(t, err) + require.NoError(t, err) data := []byte{42, 42} _, err = con.Read(data) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []byte{0x00, 0x01}, data) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestI2cFinalizeWithErrors(t *testing.T) { @@ -559,16 +560,16 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem(pwmMockPathsMux13ArduinoI2c) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 6) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0x0A}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() // assert - assert.NotNil(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "close error") } diff --git a/platforms/intel-iot/joule/joule_adaptor_test.go b/platforms/intel-iot/joule/joule_adaptor_test.go index 178825733..21896a35d 100644 --- a/platforms/intel-iot/joule/joule_adaptor_test.go +++ b/platforms/intel-iot/joule/joule_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -111,13 +112,13 @@ func TestFinalize(t *testing.T) { _ = a.DigitalWrite("J12_1", 1) _ = a.PwmWrite("J12_26", 100) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // assert finalize after finalize is working - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) // assert re-connect is working - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) } func TestDigitalIO(t *testing.T) { @@ -129,25 +130,25 @@ func TestDigitalIO(t *testing.T) { _ = a.DigitalWrite("J12_1", 0) i, err := a.DigitalRead("J12_1") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 0, i) _, err = a.DigitalRead("P9_99") - assert.ErrorContains(t, err, "'P9_99' is not a valid id for a digital pin") + require.ErrorContains(t, err, "'P9_99' is not a valid id for a digital pin") } func TestPwm(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() err := a.PwmWrite("J12_26", 100) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "3921568", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) err = a.PwmWrite("4", 100) - assert.ErrorContains(t, err, "'4' is not a valid id for a pin") + require.ErrorContains(t, err, "'4' is not a valid id for a pin") err = a.PwmWrite("J12_1", 100) - assert.ErrorContains(t, err, "'J12_1' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'J12_1' is not a valid id for a PWM pin") } func TestPwmPinExportError(t *testing.T) { @@ -176,11 +177,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-2"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 2) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/jetson/jetson_adaptor_test.go b/platforms/jetson/jetson_adaptor_test.go index a3ccec3f9..dd74c8327 100644 --- a/platforms/jetson/jetson_adaptor_test.go +++ b/platforms/jetson/jetson_adaptor_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -59,7 +60,7 @@ func TestFinalize(t *testing.T) { _ = a.DigitalWrite("3", 1) _, _ = a.GetI2cConnection(0xff, 0) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestPWMPinsConnect(t *testing.T) { @@ -67,12 +68,12 @@ func TestPWMPinsConnect(t *testing.T) { assert.Equal(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) err := a.PwmWrite("33", 1) - assert.ErrorContains(t, err, "not connected") + require.ErrorContains(t, err, "not connected") err = a.Connect() - assert.NoError(t, err) + require.NoError(t, err) assert.NotEqual(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) - assert.Equal(t, 0, len(a.pwmPins)) + assert.Empty(t, a.pwmPins) } func TestPWMPinsReConnect(t *testing.T) { @@ -85,15 +86,15 @@ func TestPWMPinsReConnect(t *testing.T) { "/sys/class/pwm/pwmchip0/pwm2/enable", } a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) - assert.Equal(t, 0, len(a.pwmPins)) - assert.NoError(t, a.PwmWrite("33", 1)) - assert.Equal(t, 1, len(a.pwmPins)) - assert.NoError(t, a.Finalize()) + assert.Empty(t, a.pwmPins) + require.NoError(t, a.PwmWrite("33", 1)) + assert.Len(t, a.pwmPins, 1) + require.NoError(t, a.Finalize()) // act err := a.Connect() // assert - assert.NoError(t, err) - assert.Equal(t, 0, len(a.pwmPins)) + require.NoError(t, err) + assert.Empty(t, a.pwmPins) } func TestDigitalIO(t *testing.T) { @@ -108,17 +109,17 @@ func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) err := a.DigitalWrite("7", 1) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio216/value"].Contents) err = a.DigitalWrite("13", 1) - assert.NoError(t, err) + require.NoError(t, err) i, err := a.DigitalRead("13") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, i) - assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid id for a digital pin") - assert.NoError(t, a.Finalize()) + require.ErrorContains(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid id for a digital pin") + require.NoError(t, a.Finalize()) } func TestDigitalPinConcurrency(t *testing.T) { @@ -163,11 +164,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/jetson/pwm_pin.go b/platforms/jetson/pwm_pin.go index 93a3f57aa..78f1ad407 100644 --- a/platforms/jetson/pwm_pin.go +++ b/platforms/jetson/pwm_pin.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path" + "strconv" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" @@ -54,7 +55,7 @@ func (p *PWMPin) Enabled() (bool, error) { // SetEnabled enables/disables the PWM pin func (p *PWMPin) SetEnabled(e bool) error { - if err := p.writeFile(fmt.Sprintf("pwm%s/enable", p.fn), fmt.Sprintf("%v", bool2int(e))); err != nil { + if err := p.writeFile(fmt.Sprintf("pwm%s/enable", p.fn), strconv.Itoa(bool2int(e))); err != nil { return err } p.enabled = e @@ -89,6 +90,7 @@ func (p *PWMPin) SetPeriod(period uint32) error { if period < minimumPeriod { return errors.New("Cannot set the period more then minimum") } + //nolint:perfsprint // ok here if err := p.writeFile(fmt.Sprintf("pwm%s/period", p.fn), fmt.Sprintf("%v", period)); err != nil { return err } @@ -116,6 +118,7 @@ func (p *PWMPin) SetDutyCycle(duty uint32) error { if rate < minimumRate { duty = uint32(minimumRate * float64(p.period) / 100) } + //nolint:perfsprint // ok here if err := p.writeFile(fmt.Sprintf("pwm%s/duty_cycle", p.fn), fmt.Sprintf("%v", duty)); err != nil { return err } diff --git a/platforms/jetson/pwm_pin_test.go b/platforms/jetson/pwm_pin_test.go index a61e22753..14cf878e0 100644 --- a/platforms/jetson/pwm_pin_test.go +++ b/platforms/jetson/pwm_pin_test.go @@ -37,43 +37,43 @@ func TestPwmPin(t *testing.T) { require.Equal(t, "", fs.Files[periodPath].Contents) require.Equal(t, "", fs.Files[dutyCyclePath].Contents) - assert.NoError(t, pin.Export()) + require.NoError(t, pin.Export()) assert.Equal(t, "3", fs.Files[exportPath].Contents) - assert.NoError(t, pin.SetEnabled(true)) + require.NoError(t, pin.SetEnabled(true)) assert.Equal(t, "1", fs.Files[enablePath].Contents) val, _ := pin.Polarity() assert.True(t, val) - assert.NoError(t, pin.SetPolarity(false)) + require.NoError(t, pin.SetPolarity(false)) val, _ = pin.Polarity() assert.True(t, val) _, err := pin.Period() - assert.ErrorContains(t, err, "Jetson PWM pin period not set") - assert.ErrorContains(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") + require.ErrorContains(t, err, "Jetson PWM pin period not set") + require.ErrorContains(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") assert.Equal(t, "", fs.Files[dutyCyclePath].Contents) - assert.NoError(t, pin.SetPeriod(20000000)) + require.NoError(t, pin.SetPeriod(20000000)) assert.Equal(t, "20000000", fs.Files[periodPath].Contents) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) - assert.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") + require.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") assert.Equal(t, "20000000", fs.Files[periodPath].Contents) dc, _ := pin.DutyCycle() assert.Equal(t, uint32(0), dc) - assert.NoError(t, pin.SetDutyCycle(10000)) + require.NoError(t, pin.SetDutyCycle(10000)) assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) - assert.ErrorContains(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") + require.ErrorContains(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") dc, _ = pin.DutyCycle() assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) assert.Equal(t, uint32(10000), dc) - assert.NoError(t, pin.Unexport()) + require.NoError(t, pin.Unexport()) assert.Equal(t, "3", fs.Files[unexportPath].Contents) } diff --git a/platforms/joystick/bin/scanner.go b/platforms/joystick/bin/scanner.go index fb4816fcf..2940ed605 100644 --- a/platforms/joystick/bin/scanner.go +++ b/platforms/joystick/bin/scanner.go @@ -50,8 +50,6 @@ func readJoystick(js joystick.Joystick) { for axis := 0; axis < js.AxisCount(); axis++ { printAt(1, axis+8, fmt.Sprintf("Axis %2d Value: %7d", axis, jinfo.AxisData[axis])) } - - return } func main() { diff --git a/platforms/joystick/joystick_adaptor_test.go b/platforms/joystick/joystick_adaptor_test.go index 98ef288fd..c638bd201 100644 --- a/platforms/joystick/joystick_adaptor_test.go +++ b/platforms/joystick/joystick_adaptor_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -24,12 +25,12 @@ func TestJoystickAdaptorName(t *testing.T) { a := initTestAdaptor() assert.True(t, strings.HasPrefix(a.Name(), "Joystick")) a.SetName("NewName") - assert.Equal(t, a.Name(), "NewName") + assert.Equal(t, "NewName", a.Name()) } func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a = NewAdaptor("6") err := a.Connect() @@ -39,5 +40,5 @@ func TestAdaptorConnect(t *testing.T) { func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() _ = a.Connect() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index 61ce25f7d..87996fc28 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" @@ -30,13 +31,13 @@ func TestJoystickDriverName(t *testing.T) { d, _ := initTestDriver("./configs/dualshock3.json") assert.True(t, strings.HasPrefix(d.Name(), "Joystick")) d.SetName("NewName") - assert.Equal(t, d.Name(), "NewName") + assert.Equal(t, "NewName", d.Name()) } func TestDriverStart(t *testing.T) { d, _ := initTestDriver("./configs/dualshock3.json") d.interval = 1 * time.Millisecond - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) time.Sleep(2 * time.Millisecond) } @@ -45,7 +46,7 @@ func TestDriverHalt(t *testing.T) { go func() { <-d.halt }() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestDriverHandleEventDS3(t *testing.T) { diff --git a/platforms/keyboard/keyboard_driver_test.go b/platforms/keyboard/keyboard_driver_test.go index a611c0e51..0d3500ac1 100644 --- a/platforms/keyboard/keyboard_driver_test.go +++ b/platforms/keyboard/keyboard_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -35,10 +36,10 @@ func TestKeyboardDriverName(t *testing.T) { func TestKeyboardDriverStart(t *testing.T) { d := initTestKeyboardDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestKeyboardDriverHalt(t *testing.T) { d := initTestKeyboardDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } diff --git a/platforms/leap/leap_motion_adaptor_test.go b/platforms/leap/leap_motion_adaptor_test.go index ac0cadddd..b16018480 100644 --- a/platforms/leap/leap_motion_adaptor_test.go +++ b/platforms/leap/leap_motion_adaptor_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -32,15 +33,15 @@ func TestLeapMotionAdaptorName(t *testing.T) { func TestLeapMotionAdaptorConnect(t *testing.T) { a := initTestLeapMotionAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") } - assert.ErrorContains(t, a.Connect(), "connection error") + require.ErrorContains(t, a.Connect(), "connection error") } func TestLeapMotionAdaptorFinalize(t *testing.T) { a := initTestLeapMotionAdaptor() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } diff --git a/platforms/leap/leap_motion_driver_test.go b/platforms/leap/leap_motion_driver_test.go index 2da70f8fa..7d6a43f8c 100644 --- a/platforms/leap/leap_motion_driver_test.go +++ b/platforms/leap/leap_motion_driver_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -69,7 +70,7 @@ func TestLeapMotionDriverName(t *testing.T) { func TestLeapMotionDriverStart(t *testing.T) { d, _ := initTestLeapMotionDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) d2, rwc := initTestLeapMotionDriver() e := errors.New("write error") @@ -79,7 +80,7 @@ func TestLeapMotionDriverStart(t *testing.T) { func TestLeapMotionDriverHalt(t *testing.T) { d, _ := initTestLeapMotionDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestLeapMotionDriverParser(t *testing.T) { @@ -92,17 +93,17 @@ func TestLeapMotionDriverParser(t *testing.T) { } assert.Equal(t, uint64(134211791358), parsedFrame.Timestamp) - assert.Equal(t, 247.410, parsedFrame.Hands[0].X()) - assert.Equal(t, 275.868, parsedFrame.Hands[0].Y()) - assert.Equal(t, 132.843, parsedFrame.Hands[0].Z()) + assert.InDelta(t, 247.410, parsedFrame.Hands[0].X(), 0.0) + assert.InDelta(t, 275.868, parsedFrame.Hands[0].Y(), 0.0) + assert.InDelta(t, 132.843, parsedFrame.Hands[0].Z(), 0.0) - assert.Equal(t, 214.293, parsedFrame.Pointables[0].BTipPosition[0]) - assert.Equal(t, 213.865, parsedFrame.Pointables[0].BTipPosition[1]) - assert.Equal(t, 95.0224, parsedFrame.Pointables[0].BTipPosition[2]) + assert.InDelta(t, 214.293, parsedFrame.Pointables[0].BTipPosition[0], 0.0) + assert.InDelta(t, 213.865, parsedFrame.Pointables[0].BTipPosition[1], 0.0) + assert.InDelta(t, 95.0224, parsedFrame.Pointables[0].BTipPosition[2], 0.0) - assert.Equal(t, -0.468069, parsedFrame.Pointables[0].Bases[0][0][0]) - assert.Equal(t, 0.807844, parsedFrame.Pointables[0].Bases[0][0][1]) - assert.Equal(t, -0.358190, parsedFrame.Pointables[0].Bases[0][0][2]) + assert.InDelta(t, -0.468069, parsedFrame.Pointables[0].Bases[0][0][0], 0.0) + assert.InDelta(t, 0.807844, parsedFrame.Pointables[0].Bases[0][0][1], 0.0) + assert.InDelta(t, -0.358190, parsedFrame.Pointables[0].Bases[0][0][2], 0.0) - assert.Equal(t, 19.7871, parsedFrame.Pointables[0].Width) + assert.InDelta(t, 19.7871, parsedFrame.Pointables[0].Width, 0.0) } diff --git a/platforms/mavlink/common/mavlink.go b/platforms/mavlink/common/mavlink.go index 895a84531..2d794e8c3 100644 --- a/platforms/mavlink/common/mavlink.go +++ b/platforms/mavlink/common/mavlink.go @@ -37,7 +37,7 @@ type MAVLinkMessage interface { Len() uint8 Crc() uint8 Pack() []byte - Decode([]byte) + Decode(buf []byte) } // A MAVLinkPacket represents a raw packet received from a micro air vehicle diff --git a/platforms/mavlink/mavlink_adaptor_test.go b/platforms/mavlink/mavlink_adaptor_test.go index 194bc54ee..2c71068e0 100644 --- a/platforms/mavlink/mavlink_adaptor_test.go +++ b/platforms/mavlink/mavlink_adaptor_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -66,18 +67,18 @@ func TestMavlinkAdaptorName(t *testing.T) { func TestMavlinkAdaptorConnect(t *testing.T) { a := initTestMavlinkAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a.connect = func(port string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - assert.ErrorContains(t, a.Connect(), "connect error") + require.ErrorContains(t, a.Connect(), "connect error") } func TestMavlinkAdaptorFinalize(t *testing.T) { a := initTestMavlinkAdaptor() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) testAdaptorClose = func() error { return errors.New("close error") } - assert.ErrorContains(t, a.Finalize(), "close error") + require.ErrorContains(t, a.Finalize(), "close error") } diff --git a/platforms/mavlink/mavlink_driver_test.go b/platforms/mavlink/mavlink_driver_test.go index 5c6846f82..a357181d4 100644 --- a/platforms/mavlink/mavlink_driver_test.go +++ b/platforms/mavlink/mavlink_driver_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" common "gobot.io/x/gobot/v2/platforms/mavlink/common" ) @@ -59,11 +60,11 @@ func TestMavlinkDriverStart(t *testing.T) { err <- data.(error) }) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) select { case p := <-packet: - assert.NoError(t, d.SendPacket(p)) + require.NoError(t, d.SendPacket(p)) case <-time.After(100 * time.Millisecond): t.Errorf("packet was not emitted") @@ -82,5 +83,5 @@ func TestMavlinkDriverStart(t *testing.T) { func TestMavlinkDriverHalt(t *testing.T) { d := initTestMavlinkDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } diff --git a/platforms/mavlink/mavlink_udp_adaptor.go b/platforms/mavlink/mavlink_udp_adaptor.go index d56a07d5b..f4cb22e50 100644 --- a/platforms/mavlink/mavlink_udp_adaptor.go +++ b/platforms/mavlink/mavlink_udp_adaptor.go @@ -8,8 +8,8 @@ import ( type UDPConnection interface { Close() error - ReadFromUDP([]byte) (int, *net.UDPAddr, error) - WriteTo([]byte, net.Addr) (int, error) + ReadFromUDP(b []byte) (int, *net.UDPAddr, error) + WriteTo(b []byte, a net.Addr) (int, error) } type UDPAdaptor struct { diff --git a/platforms/mavlink/mavlink_udp_adaptor_test.go b/platforms/mavlink/mavlink_udp_adaptor_test.go index 8705a3f6d..513eca2db 100644 --- a/platforms/mavlink/mavlink_udp_adaptor_test.go +++ b/platforms/mavlink/mavlink_udp_adaptor_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" mavlink "gobot.io/x/gobot/v2/platforms/mavlink/common" ) @@ -65,8 +66,8 @@ func TestMavlinkUDPAdaptorName(t *testing.T) { func TestMavlinkUDPAdaptorConnectAndFinalize(t *testing.T) { a := initTestMavlinkUDPAdaptor() - assert.NoError(t, a.Connect()) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Connect()) + require.NoError(t, a.Finalize()) } func TestMavlinkUDPAdaptorWrite(t *testing.T) { @@ -82,7 +83,7 @@ func TestMavlinkUDPAdaptorWrite(t *testing.T) { i, err := a.Write([]byte{0x01, 0x02, 0x03}) assert.Equal(t, 3, i) - assert.NoError(t, err) + require.NoError(t, err) } func TestMavlinkReadMAVLinkReadDefaultPacket(t *testing.T) { @@ -136,5 +137,5 @@ func TestMavlinkReadMAVLinkPacketReadError(t *testing.T) { a.sock = m _, err := a.ReadMAVLinkPacket() - assert.ErrorContains(t, err, "read error") + require.ErrorContains(t, err, "read error") } diff --git a/platforms/microbit/accelerometer_driver_test.go b/platforms/microbit/accelerometer_driver_test.go index 2ff9fbd94..312edc23d 100644 --- a/platforms/microbit/accelerometer_driver_test.go +++ b/platforms/microbit/accelerometer_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -25,8 +26,8 @@ func TestAccelerometerDriver(t *testing.T) { func TestAccelerometerDriverStartAndHalt(t *testing.T) { d := initTestAccelerometerDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestAccelerometerDriverReadData(t *testing.T) { @@ -35,9 +36,9 @@ func TestAccelerometerDriverReadData(t *testing.T) { d := NewAccelerometerDriver(a) _ = d.Start() _ = d.On(Accelerometer, func(data interface{}) { - assert.Equal(t, float32(8.738), data.(*AccelerometerData).X) - assert.Equal(t, float32(8.995), data.(*AccelerometerData).Y) - assert.Equal(t, float32(9.252), data.(*AccelerometerData).Z) + assert.InDelta(t, float32(8.738), data.(*AccelerometerData).X, 0.0) + assert.InDelta(t, float32(8.995), data.(*AccelerometerData).Y, 0.0) + assert.InDelta(t, float32(9.252), data.(*AccelerometerData).Z, 0.0) sem <- true }) diff --git a/platforms/microbit/button_driver_test.go b/platforms/microbit/button_driver_test.go index 6cc965f03..6af815e8d 100644 --- a/platforms/microbit/button_driver_test.go +++ b/platforms/microbit/button_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -25,8 +26,8 @@ func TestButtonDriver(t *testing.T) { func TestButtonDriverStartAndHalt(t *testing.T) { d := initTestButtonDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestButtonDriverReadData(t *testing.T) { diff --git a/platforms/microbit/io_pin_driver_test.go b/platforms/microbit/io_pin_driver_test.go index 11bf2e57d..21794606d 100644 --- a/platforms/microbit/io_pin_driver_test.go +++ b/platforms/microbit/io_pin_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" @@ -39,8 +40,8 @@ func TestIOPinDriverStartAndHalt(t *testing.T) { a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { return []byte{0, 1, 1, 0}, nil }) - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestIOPinDriverStartError(t *testing.T) { @@ -49,7 +50,7 @@ func TestIOPinDriverStartError(t *testing.T) { a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { return nil, errors.New("read error") }) - assert.ErrorContains(t, d.Start(), "read error") + require.ErrorContains(t, d.Start(), "read error") } func TestIOPinDriverDigitalRead(t *testing.T) { @@ -71,10 +72,10 @@ func TestIOPinDriverDigitalReadInvalidPin(t *testing.T) { d := NewIOPinDriver(a) _, err := d.DigitalRead("A3") - assert.NotNil(t, err) + require.Error(t, err) _, err = d.DigitalRead("6") - assert.ErrorContains(t, err, "Invalid pin.") + require.ErrorContains(t, err, "Invalid pin.") } func TestIOPinDriverDigitalWrite(t *testing.T) { @@ -82,15 +83,15 @@ func TestIOPinDriverDigitalWrite(t *testing.T) { d := NewIOPinDriver(a) // TODO: a better test - assert.NoError(t, d.DigitalWrite("0", 1)) + require.NoError(t, d.DigitalWrite("0", 1)) } func TestIOPinDriverDigitalWriteInvalidPin(t *testing.T) { a := NewBleTestAdaptor() d := NewIOPinDriver(a) - assert.NotNil(t, d.DigitalWrite("A3", 1)) - assert.ErrorContains(t, d.DigitalWrite("6", 1), "Invalid pin.") + require.Error(t, d.DigitalWrite("A3", 1)) + require.ErrorContains(t, d.DigitalWrite("6", 1), "Invalid pin.") } func TestIOPinDriverAnalogRead(t *testing.T) { @@ -112,10 +113,10 @@ func TestIOPinDriverAnalogReadInvalidPin(t *testing.T) { d := NewIOPinDriver(a) _, err := d.AnalogRead("A3") - assert.NotNil(t, err) + require.Error(t, err) _, err = d.AnalogRead("6") - assert.ErrorContains(t, err, "Invalid pin.") + require.ErrorContains(t, err, "Invalid pin.") } func TestIOPinDriverDigitalAnalogRead(t *testing.T) { @@ -139,7 +140,7 @@ func TestIOPinDriverDigitalWriteAnalogRead(t *testing.T) { return []byte{0, 0, 1, 128, 2, 1}, nil }) - assert.NoError(t, d.DigitalWrite("1", 0)) + require.NoError(t, d.DigitalWrite("1", 0)) val, _ := d.AnalogRead("1") assert.Equal(t, 128, val) @@ -155,5 +156,5 @@ func TestIOPinDriverAnalogReadDigitalWrite(t *testing.T) { val, _ := d.AnalogRead("1") assert.Equal(t, 128, val) - assert.NoError(t, d.DigitalWrite("1", 0)) + require.NoError(t, d.DigitalWrite("1", 0)) } diff --git a/platforms/microbit/led_driver_test.go b/platforms/microbit/led_driver_test.go index 963759fe3..5be9376a7 100644 --- a/platforms/microbit/led_driver_test.go +++ b/platforms/microbit/led_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -24,32 +25,32 @@ func TestLEDDriver(t *testing.T) { func TestLEDDriverStartAndHalt(t *testing.T) { d := initTestLEDDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestLEDDriverWriteMatrix(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - assert.NoError(t, d.WriteMatrix([]byte{0x01, 0x02})) + require.NoError(t, d.WriteMatrix([]byte{0x01, 0x02})) } func TestLEDDriverWriteText(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - assert.NoError(t, d.WriteText("Hello")) + require.NoError(t, d.WriteText("Hello")) } func TestLEDDriverCommands(t *testing.T) { d := initTestLEDDriver() _ = d.Start() - assert.NoError(t, d.Blank()) - assert.NoError(t, d.Solid()) - assert.NoError(t, d.UpRightArrow()) - assert.NoError(t, d.UpLeftArrow()) - assert.NoError(t, d.DownRightArrow()) - assert.NoError(t, d.DownLeftArrow()) - assert.NoError(t, d.Dimond()) - assert.NoError(t, d.Smile()) - assert.NoError(t, d.Wink()) + require.NoError(t, d.Blank()) + require.NoError(t, d.Solid()) + require.NoError(t, d.UpRightArrow()) + require.NoError(t, d.UpLeftArrow()) + require.NoError(t, d.DownRightArrow()) + require.NoError(t, d.DownLeftArrow()) + require.NoError(t, d.Dimond()) + require.NoError(t, d.Smile()) + require.NoError(t, d.Wink()) } diff --git a/platforms/microbit/magnetometer_driver_test.go b/platforms/microbit/magnetometer_driver_test.go index 884c9d8ae..53a48f5f1 100644 --- a/platforms/microbit/magnetometer_driver_test.go +++ b/platforms/microbit/magnetometer_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -25,8 +26,8 @@ func TestMagnetometerDriver(t *testing.T) { func TestMagnetometerDriverStartAndHalt(t *testing.T) { d := initTestMagnetometerDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestMagnetometerDriverReadData(t *testing.T) { @@ -35,9 +36,9 @@ func TestMagnetometerDriverReadData(t *testing.T) { d := NewMagnetometerDriver(a) _ = d.Start() _ = d.On(Magnetometer, func(data interface{}) { - assert.Equal(t, float32(8.738), data.(*MagnetometerData).X) - assert.Equal(t, float32(8.995), data.(*MagnetometerData).Y) - assert.Equal(t, float32(9.252), data.(*MagnetometerData).Z) + assert.InDelta(t, float32(8.738), data.(*MagnetometerData).X, 0.0) + assert.InDelta(t, float32(8.995), data.(*MagnetometerData).Y, 0.0) + assert.InDelta(t, float32(9.252), data.(*MagnetometerData).Z, 0.0) sem <- true }) diff --git a/platforms/microbit/temperature_driver_test.go b/platforms/microbit/temperature_driver_test.go index 5bd352799..a24c0f2cb 100644 --- a/platforms/microbit/temperature_driver_test.go +++ b/platforms/microbit/temperature_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -25,8 +26,8 @@ func TestTemperatureDriver(t *testing.T) { func TestTemperatureDriverStartAndHalt(t *testing.T) { d := initTestTemperatureDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestTemperatureDriverReadData(t *testing.T) { diff --git a/platforms/mqtt/mqtt_adaptor_test.go b/platforms/mqtt/mqtt_adaptor_test.go index 77a38b0ee..9a60e4470 100644 --- a/platforms/mqtt/mqtt_adaptor_test.go +++ b/platforms/mqtt/mqtt_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -85,12 +86,12 @@ func TestMqttAdaptorConnectSSLError(t *testing.T) { func TestMqttAdaptorConnectWithAuthError(t *testing.T) { a := NewAdaptorWithAuth("xyz://localhost:1883", "client", "user", "pass") - assert.ErrorContains(t, a.Connect(), "network Error : unknown protocol") + require.ErrorContains(t, a.Connect(), "network Error : unknown protocol") } func TestMqttAdaptorFinalize(t *testing.T) { a := initTestMqttAdaptor() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestMqttAdaptorCannotPublishUnlessConnected(t *testing.T) { @@ -124,5 +125,5 @@ func TestMqttAdaptorOnWhenConnected(t *testing.T) { func TestMqttAdaptorQoS(t *testing.T) { a := initTestMqttAdaptor() a.SetQoS(1) - assert.Equal(t, a.qos, 1) + assert.Equal(t, 1, a.qos) } diff --git a/platforms/mqtt/mqtt_driver_test.go b/platforms/mqtt/mqtt_driver_test.go index bf77fcdfa..8ee028ea5 100644 --- a/platforms/mqtt/mqtt_driver_test.go +++ b/platforms/mqtt/mqtt_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -16,8 +17,8 @@ func TestMqttDriver(t *testing.T) { assert.True(t, strings.HasPrefix(d.Name(), "MQTT")) assert.True(t, strings.HasPrefix(d.Connection().Name(), "MQTT")) - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestMqttDriverName(t *testing.T) { diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index fe922621d..46a36bf08 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -2,10 +2,12 @@ package nanopi import ( "fmt" + "strconv" "strings" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -92,8 +94,8 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("10") assert.Equal(t, 1, i) - assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") - assert.NoError(t, a.Finalize()) + require.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + require.NoError(t, a.Finalize()) } func TestInvalidPWMPin(t *testing.T) { @@ -101,16 +103,16 @@ func TestInvalidPWMPin(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("666", 42) - assert.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") err = a.ServoWrite("666", 120) - assert.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") err = a.PwmWrite("3", 42) - assert.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") err = a.ServoWrite("3", 120) - assert.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") } func TestPwmWrite(t *testing.T) { @@ -118,24 +120,24 @@ func TestPwmWrite(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("PWM", 100) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", 10000000), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, strconv.Itoa(10000000), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.ServoWrite("PWM", 0) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("PWM", 180) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestSetPeriod(t *testing.T) { @@ -147,25 +149,25 @@ func TestSetPeriod(t *testing.T) { // act err := a.SetPeriod("PWM", newPeriod) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here assert.Equal(t, "0", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("PWM", 127) // 127 is a little bit smaller than 50% of period - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 1270000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(1270000), fs.Files[pwmDutyCyclePath].Contents) newPeriod = newPeriod / 10 // act err = a.SetPeriod("PWM", newPeriod) // assert - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 127000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(127000), fs.Files[pwmDutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value newPeriod = newPeriod * 20 @@ -174,14 +176,14 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("PWM", newPeriod) // assert - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 2540000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(2540000), fs.Files[pwmDutyCyclePath].Contents) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - assert.NoError(t, a.DigitalWrite("7", 1)) + require.NoError(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true @@ -193,7 +195,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) - assert.NoError(t, a.PwmWrite("PWM", 1)) + require.NoError(t, a.PwmWrite("PWM", 1)) fs.WithWriteError = true @@ -221,11 +223,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewNeoAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/nats/nats_adaptor_test.go b/platforms/nats/nats_adaptor_test.go index feccd0a94..92023cdf0 100644 --- a/platforms/nats/nats_adaptor_test.go +++ b/platforms/nats/nats_adaptor_test.go @@ -8,6 +8,7 @@ import ( "github.com/nats-io/nats.go" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -74,7 +75,7 @@ func TestNatsAdapterSetsRootCAs(t *testing.T) { _ = a.Connect() o := a.client.Opts casPool, err := o.RootCAsCB() - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, casPool) assert.True(t, o.Secure) } @@ -84,7 +85,7 @@ func TestNatsAdapterSetsClientCerts(t *testing.T) { assert.Equal(t, "tls://localhost:4242", a.Host) _ = a.Connect() cert, err := a.client.Opts.TLSCertCB() - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, cert) assert.NotNil(t, cert.Leaf) assert.True(t, a.client.Opts.Secure) @@ -95,7 +96,7 @@ func TestNatsAdapterSetsClientCertsWithUserInfo(t *testing.T) { assert.Equal(t, "tls://localhost:4242", a.Host) _ = a.Connect() cert, err := a.client.Opts.TLSCertCB() - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, cert) assert.NotNil(t, cert.Leaf) assert.True(t, a.client.Opts.Secure) @@ -148,12 +149,12 @@ func TestNatsAdaptorFailedConnect(t *testing.T) { if err != nil && strings.Contains(err.Error(), "cannot assign requested address") { t.Skip("FLAKY: Can not test, because IP or port is in use.") } - assert.ErrorContains(t, err, "nats: no servers available for connection") + require.ErrorContains(t, err, "nats: no servers available for connection") } func TestNatsAdaptorFinalize(t *testing.T) { a := NewAdaptor("localhost:9999", 79999) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestNatsAdaptorCannotPublishUnlessConnected(t *testing.T) { diff --git a/platforms/nats/nats_driver_test.go b/platforms/nats/nats_driver_test.go index d9a4a970b..d35b1d9e4 100644 --- a/platforms/nats/nats_driver_test.go +++ b/platforms/nats/nats_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -17,8 +18,8 @@ func TestNatsDriver(t *testing.T) { assert.True(t, strings.HasPrefix(d.Connection().Name(), "NATS")) assert.NotNil(t, d.adaptor()) - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestNatsDriverName(t *testing.T) { diff --git a/platforms/neurosky/neurosky_adaptor_test.go b/platforms/neurosky/neurosky_adaptor_test.go index 68528c391..6f36be7fb 100644 --- a/platforms/neurosky/neurosky_adaptor_test.go +++ b/platforms/neurosky/neurosky_adaptor_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -69,12 +70,12 @@ func TestNeuroskyAdaptorName(t *testing.T) { func TestNeuroskyAdaptorConnect(t *testing.T) { a := initTestNeuroskyAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { return nil, errors.New("connection error") } - assert.ErrorContains(t, a.Connect(), "connection error") + require.ErrorContains(t, a.Connect(), "connection error") } func TestNeuroskyAdaptorFinalize(t *testing.T) { @@ -84,9 +85,9 @@ func TestNeuroskyAdaptorFinalize(t *testing.T) { return rwc, nil } _ = a.Connect() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) rwc.CloseError(errors.New("close error")) _ = a.Connect() - assert.ErrorContains(t, a.Finalize(), "close error") + require.ErrorContains(t, a.Finalize(), "close error") } diff --git a/platforms/neurosky/neurosky_driver_test.go b/platforms/neurosky/neurosky_driver_test.go index d5d3cfee5..a3c86b048 100644 --- a/platforms/neurosky/neurosky_driver_test.go +++ b/platforms/neurosky/neurosky_driver_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -52,7 +53,7 @@ func TestNeuroskyDriverStart(t *testing.T) { sem <- true }) - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) time.Sleep(50 * time.Millisecond) rwc.ReadError(e) @@ -69,7 +70,7 @@ func TestNeuroskyDriverStart(t *testing.T) { func TestNeuroskyDriverHalt(t *testing.T) { d := initTestNeuroskyDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestNeuroskyDriverParse(t *testing.T) { diff --git a/platforms/opencv/camera_driver_test.go b/platforms/opencv/camera_driver_test.go index 973f36cf2..5b4adda1a 100644 --- a/platforms/opencv/camera_driver_test.go +++ b/platforms/opencv/camera_driver_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -36,7 +37,7 @@ func TestCameraDriverName(t *testing.T) { func TestCameraDriverStart(t *testing.T) { sem := make(chan bool) d := initTestCameraDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) d.On(d.Event("frame"), func(data interface{}) { sem <- true }) @@ -47,7 +48,7 @@ func TestCameraDriverStart(t *testing.T) { } d = NewCameraDriver("") - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) d = NewCameraDriver(true) assert.NotNil(t, d.Start()) @@ -55,5 +56,5 @@ func TestCameraDriverStart(t *testing.T) { func TestCameraDriverHalt(t *testing.T) { d := initTestCameraDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } diff --git a/platforms/opencv/window_driver_test.go b/platforms/opencv/window_driver_test.go index bc652ccb9..ae7ba808e 100644 --- a/platforms/opencv/window_driver_test.go +++ b/platforms/opencv/window_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gocv.io/x/gocv" ) @@ -33,12 +34,12 @@ func TestWindowDriverName(t *testing.T) { func TestWindowDriverStart(t *testing.T) { d := initTestWindowDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestWindowDriverHalt(t *testing.T) { d := initTestWindowDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestWindowDriverShowImage(t *testing.T) { diff --git a/platforms/parrot/ardrone/ardrone_adaptor_test.go b/platforms/parrot/ardrone/ardrone_adaptor_test.go index 90bed54ef..c8eb5c59c 100644 --- a/platforms/parrot/ardrone/ardrone_adaptor_test.go +++ b/platforms/parrot/ardrone/ardrone_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -29,12 +30,12 @@ func TestArdroneAdaptor(t *testing.T) { func TestArdroneAdaptorConnect(t *testing.T) { a := initTestArdroneAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a.connect = func(a *Adaptor) (drone, error) { return nil, errors.New("connection error") } - assert.ErrorContains(t, a.Connect(), "connection error") + require.ErrorContains(t, a.Connect(), "connection error") } func TestArdroneAdaptorName(t *testing.T) { @@ -46,5 +47,5 @@ func TestArdroneAdaptorName(t *testing.T) { func TestArdroneAdaptorFinalize(t *testing.T) { a := initTestArdroneAdaptor() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } diff --git a/platforms/parrot/ardrone/ardrone_driver_test.go b/platforms/parrot/ardrone/ardrone_driver_test.go index 2d35a189b..9664cd71f 100644 --- a/platforms/parrot/ardrone/ardrone_driver_test.go +++ b/platforms/parrot/ardrone/ardrone_driver_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -34,12 +35,12 @@ func TestArdroneDriverName(t *testing.T) { func TestArdroneDriverStart(t *testing.T) { d := initTestArdroneDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestArdroneDriverHalt(t *testing.T) { d := initTestArdroneDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestArdroneDriverTakeOff(t *testing.T) { diff --git a/platforms/parrot/ardrone/pitch_test.go b/platforms/parrot/ardrone/pitch_test.go index c4f5870c2..3820855bd 100644 --- a/platforms/parrot/ardrone/pitch_test.go +++ b/platforms/parrot/ardrone/pitch_test.go @@ -7,13 +7,13 @@ import ( ) func TestArdroneValidatePitchWhenEqualOffset(t *testing.T) { - assert.Equal(t, 1.0, ValidatePitch(32767.0, 32767.0)) + assert.InDelta(t, 1.0, ValidatePitch(32767.0, 32767.0), 0.0) } func TestArdroneValidatePitchWhenTiny(t *testing.T) { - assert.Equal(t, 0.0, ValidatePitch(1.1, 32767.0)) + assert.InDelta(t, 0.0, ValidatePitch(1.1, 32767.0), 0.0) } func TestArdroneValidatePitchWhenCentered(t *testing.T) { - assert.Equal(t, 0.5, ValidatePitch(16383.5, 32767.0)) + assert.InDelta(t, 0.5, ValidatePitch(16383.5, 32767.0), 0.0) } diff --git a/platforms/parrot/bebop/bebop_adaptor_test.go b/platforms/parrot/bebop/bebop_adaptor_test.go index 6c5e0301c..c5c2dd039 100644 --- a/platforms/parrot/bebop/bebop_adaptor_test.go +++ b/platforms/parrot/bebop/bebop_adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -29,16 +30,16 @@ func TestBebopAdaptorName(t *testing.T) { func TestBebopAdaptorConnect(t *testing.T) { a := initTestBebopAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a.connect = func(a *Adaptor) error { return errors.New("connection error") } - assert.ErrorContains(t, a.Connect(), "connection error") + require.ErrorContains(t, a.Connect(), "connection error") } func TestBebopAdaptorFinalize(t *testing.T) { a := initTestBebopAdaptor() _ = a.Connect() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } diff --git a/platforms/parrot/minidrone/minidrone_driver_test.go b/platforms/parrot/minidrone/minidrone_driver_test.go index a197a8947..ec65a3ff5 100644 --- a/platforms/parrot/minidrone/minidrone_driver_test.go +++ b/platforms/parrot/minidrone/minidrone_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -24,133 +25,133 @@ func TestMinidroneDriver(t *testing.T) { func TestMinidroneDriverStartAndHalt(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestMinidroneTakeoff(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.TakeOff()) + require.NoError(t, d.Start()) + require.NoError(t, d.TakeOff()) } func TestMinidroneEmergency(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Emergency()) + require.NoError(t, d.Start()) + require.NoError(t, d.Emergency()) } func TestMinidroneTakePicture(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.TakePicture()) + require.NoError(t, d.Start()) + require.NoError(t, d.TakePicture()) } func TestMinidroneUp(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Up(25)) + require.NoError(t, d.Start()) + require.NoError(t, d.Up(25)) } func TestMinidroneUpTooFar(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Up(125)) - assert.NoError(t, d.Up(-50)) + require.NoError(t, d.Start()) + require.NoError(t, d.Up(125)) + require.NoError(t, d.Up(-50)) } func TestMinidroneDown(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Down(25)) + require.NoError(t, d.Start()) + require.NoError(t, d.Down(25)) } func TestMinidroneForward(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Forward(25)) + require.NoError(t, d.Start()) + require.NoError(t, d.Forward(25)) } func TestMinidroneBackward(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Backward(25)) + require.NoError(t, d.Start()) + require.NoError(t, d.Backward(25)) } func TestMinidroneRight(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Right(25)) + require.NoError(t, d.Start()) + require.NoError(t, d.Right(25)) } func TestMinidroneLeft(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Left(25)) + require.NoError(t, d.Start()) + require.NoError(t, d.Left(25)) } func TestMinidroneClockwise(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Clockwise(25)) + require.NoError(t, d.Start()) + require.NoError(t, d.Clockwise(25)) } func TestMinidroneCounterClockwise(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.CounterClockwise(25)) + require.NoError(t, d.Start()) + require.NoError(t, d.CounterClockwise(25)) } func TestMinidroneStop(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Stop()) + require.NoError(t, d.Start()) + require.NoError(t, d.Stop()) } func TestMinidroneStartStopRecording(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.StartRecording()) - assert.NoError(t, d.StopRecording()) + require.NoError(t, d.Start()) + require.NoError(t, d.StartRecording()) + require.NoError(t, d.StopRecording()) } func TestMinidroneHullProtectionOutdoor(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.HullProtection(true)) - assert.NoError(t, d.Outdoor(true)) + require.NoError(t, d.Start()) + require.NoError(t, d.HullProtection(true)) + require.NoError(t, d.Outdoor(true)) } func TestMinidroneHullFlips(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.FrontFlip()) - assert.NoError(t, d.BackFlip()) - assert.NoError(t, d.RightFlip()) - assert.NoError(t, d.LeftFlip()) + require.NoError(t, d.Start()) + require.NoError(t, d.FrontFlip()) + require.NoError(t, d.BackFlip()) + require.NoError(t, d.RightFlip()) + require.NoError(t, d.LeftFlip()) } func TestMinidroneLightControl(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.LightControl(0, LightBlinked, 25)) + require.NoError(t, d.Start()) + require.NoError(t, d.LightControl(0, LightBlinked, 25)) } func TestMinidroneClawControl(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.ClawControl(0, ClawOpen)) + require.NoError(t, d.Start()) + require.NoError(t, d.ClawControl(0, ClawOpen)) } func TestMinidroneGunControl(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.GunControl(0)) + require.NoError(t, d.Start()) + require.NoError(t, d.GunControl(0)) } func TestMinidroneProcessFlightData(t *testing.T) { d := initTestMinidroneDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) d.processFlightStatus([]byte{0x00, 0x00, 0x00}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x00}) @@ -166,5 +167,5 @@ func TestMinidroneProcessFlightData(t *testing.T) { d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06}) - assert.NoError(t, d.Stop()) + require.NoError(t, d.Stop()) } diff --git a/platforms/particle/adaptor.go b/platforms/particle/adaptor.go index 2d6b3262f..365621a2c 100644 --- a/platforms/particle/adaptor.go +++ b/platforms/particle/adaptor.go @@ -273,7 +273,7 @@ func (s *Adaptor) request(method string, url string, params url.Values) (m map[s func (s *Adaptor) servoPinOpen(pin string) error { params := url.Values{ - "params": {fmt.Sprintf("%v", pin)}, + "params": {pin}, "access_token": {s.AccessToken}, } url := fmt.Sprintf("%v/servoOpen", s.deviceURL()) diff --git a/platforms/particle/adaptor_test.go b/platforms/particle/adaptor_test.go index 544804e76..20b5c632d 100644 --- a/platforms/particle/adaptor_test.go +++ b/platforms/particle/adaptor_test.go @@ -10,6 +10,7 @@ import ( "github.com/donovanhide/eventsource" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -88,13 +89,13 @@ func TestNewAdaptor(t *testing.T) { func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) } func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() _ = a.Connect() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestAdaptorAnalogRead(t *testing.T) { @@ -254,7 +255,7 @@ func TestAdaptorFunction(t *testing.T) { a.setAPIServer(testServer.URL) _, err := a.Function("hello", "") - assert.ErrorContains(t, err, "timeout") + require.ErrorContains(t, err, "timeout") testServer.Close() } @@ -309,7 +310,7 @@ func TestAdaptorVariable(t *testing.T) { a.setAPIServer(testServer.URL) _, err := a.Variable("not_existent") - assert.ErrorContains(t, err, "Variable not found") + require.ErrorContains(t, err, "Variable not found") testServer.Close() } @@ -386,14 +387,14 @@ func TestAdaptorEventStream(t *testing.T) { assert.Equal(t, "https://api.particle.io/v1/devices/myDevice/events/ping?access_token=token", url) _, err := a.EventStream("nothing", "ping") - assert.ErrorContains(t, err, "source param should be: all, devices or device") + require.ErrorContains(t, err, "source param should be: all, devices or device") eventSource = func(u string) (chan eventsource.Event, chan error, error) { return nil, nil, errors.New("error connecting sse") } _, err = a.EventStream("devices", "") - assert.ErrorContains(t, err, "error connecting sse") + require.ErrorContains(t, err, "error connecting sse") eventChan := make(chan eventsource.Event) errorChan := make(chan error) @@ -403,5 +404,5 @@ func TestAdaptorEventStream(t *testing.T) { } _, err = a.EventStream("devices", "") - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/platforms/pebble/pebble_adaptor_test.go b/platforms/pebble/pebble_adaptor_test.go index b7b4577ac..03e3eb64f 100644 --- a/platforms/pebble/pebble_adaptor_test.go +++ b/platforms/pebble/pebble_adaptor_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -20,10 +21,10 @@ func TestAdaptor(t *testing.T) { func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) } func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } diff --git a/platforms/pebble/pebble_driver_test.go b/platforms/pebble/pebble_driver_test.go index b68f3f3f8..2087f1477 100644 --- a/platforms/pebble/pebble_driver_test.go +++ b/platforms/pebble/pebble_driver_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -16,12 +17,12 @@ func initTestDriver() *Driver { func TestDriverStart(t *testing.T) { d := initTestDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestDriverHalt(t *testing.T) { d := initTestDriver() - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestDriver(t *testing.T) { diff --git a/platforms/raspi/pwm_pin_test.go b/platforms/raspi/pwm_pin_test.go index ea3cc6f82..c2bfa6155 100644 --- a/platforms/raspi/pwm_pin_test.go +++ b/platforms/raspi/pwm_pin_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) @@ -17,37 +18,37 @@ func TestPwmPin(t *testing.T) { pin := NewPWMPin(a, path, "1") - assert.NoError(t, pin.Export()) - assert.NoError(t, pin.SetEnabled(true)) + require.NoError(t, pin.Export()) + require.NoError(t, pin.SetEnabled(true)) val, _ := pin.Polarity() assert.True(t, val) - assert.NoError(t, pin.SetPolarity(false)) + require.NoError(t, pin.SetPolarity(false)) val, _ = pin.Polarity() assert.True(t, val) _, err := pin.Period() - assert.ErrorContains(t, err, "Raspi PWM pin period not set") - assert.ErrorContains(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") + require.ErrorContains(t, err, "Raspi PWM pin period not set") + require.ErrorContains(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") - assert.NoError(t, pin.SetPeriod(20000000)) + require.NoError(t, pin.SetPeriod(20000000)) period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) - assert.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") + require.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") dc, _ := pin.DutyCycle() assert.Equal(t, uint32(0), dc) - assert.NoError(t, pin.SetDutyCycle(10000)) + require.NoError(t, pin.SetDutyCycle(10000)) dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) - assert.ErrorContains(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") + require.ErrorContains(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") dc, _ = pin.DutyCycle() assert.Equal(t, uint32(10000), dc) - assert.NoError(t, pin.Unexport()) + require.NoError(t, pin.Unexport()) } diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index 402916421..cd78959c8 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -103,7 +104,7 @@ func TestFinalize(t *testing.T) { _ = a.PwmWrite("7", 255) _, _ = a.GetI2cConnection(0xff, 0) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestDigitalPWM(t *testing.T) { @@ -111,28 +112,28 @@ func TestDigitalPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockedPaths) a.PiBlasterPeriod = 20000000 - assert.NoError(t, a.PwmWrite("7", 4)) + require.NoError(t, a.PwmWrite("7", 4)) pin, _ := a.PWMPin("7") period, _ := pin.Period() assert.Equal(t, uint32(20000000), period) - assert.NoError(t, a.PwmWrite("7", 255)) + require.NoError(t, a.PwmWrite("7", 255)) assert.Equal(t, "4=1", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - assert.NoError(t, a.ServoWrite("11", 90)) + require.NoError(t, a.ServoWrite("11", 90)) assert.Equal(t, "17=0.5", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - assert.ErrorContains(t, a.PwmWrite("notexist", 1), "Not a valid pin") - assert.ErrorContains(t, a.ServoWrite("notexist", 1), "Not a valid pin") + require.ErrorContains(t, a.PwmWrite("notexist", 1), "Not a valid pin") + require.ErrorContains(t, a.ServoWrite("notexist", 1), "Not a valid pin") pin, _ = a.PWMPin("12") period, _ = pin.Period() assert.Equal(t, uint32(20000000), period) - assert.NoError(t, pin.SetDutyCycle(1.5*1000*1000)) + require.NoError(t, pin.SetDutyCycle(1.5*1000*1000)) assert.Equal(t, "18=0.075", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) } @@ -149,19 +150,19 @@ func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(mockedPaths) err := a.DigitalWrite("7", 1) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio4/value"].Contents) a.revision = "2" err = a.DigitalWrite("13", 1) - assert.NoError(t, err) + require.NoError(t, err) i, err := a.DigitalRead("13") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 1, i) - assert.ErrorContains(t, a.DigitalWrite("notexist", 1), "Not a valid pin") - assert.NoError(t, a.Finalize()) + require.ErrorContains(t, a.DigitalWrite("notexist", 1), "Not a valid pin") + require.NoError(t, a.Finalize()) } func TestDigitalPinConcurrency(t *testing.T) { @@ -193,23 +194,23 @@ func TestPWMPin(t *testing.T) { panic(err) } - assert.Equal(t, 0, len(a.pwmPins)) + assert.Empty(t, a.pwmPins) a.revision = "3" firstSysPin, err := a.PWMPin("35") - assert.NoError(t, err) - assert.Equal(t, 1, len(a.pwmPins)) + require.NoError(t, err) + assert.Len(t, a.pwmPins, 1) secondSysPin, err := a.PWMPin("35") - assert.NoError(t, err) - assert.Equal(t, 1, len(a.pwmPins)) + require.NoError(t, err) + assert.Len(t, a.pwmPins, 1) assert.Equal(t, secondSysPin, firstSysPin) otherSysPin, err := a.PWMPin("36") - assert.NoError(t, err) - assert.Equal(t, 2, len(a.pwmPins)) + require.NoError(t, err) + assert.Len(t, a.pwmPins, 2) assert.NotEqual(t, otherSysPin, firstSysPin) } @@ -222,18 +223,18 @@ func TestPWMPinsReConnect(t *testing.T) { } _, err := a.PWMPin("35") - assert.NoError(t, err) - assert.Equal(t, 1, len(a.pwmPins)) - assert.NoError(t, a.Finalize()) + require.NoError(t, err) + assert.Len(t, a.pwmPins, 1) + require.NoError(t, a.Finalize()) // act err = a.Connect() // assert - assert.NoError(t, err) - assert.Equal(t, 0, len(a.pwmPins)) + require.NoError(t, err) + assert.Empty(t, a.pwmPins) _, _ = a.PWMPin("35") _, err = a.PWMPin("36") - assert.NoError(t, err) - assert.Equal(t, 2, len(a.pwmPins)) + require.NoError(t, err) + assert.Len(t, a.pwmPins, 2) } func TestSpiDefaultValues(t *testing.T) { @@ -262,11 +263,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-1"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 1) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/sphero/bb8/bb8_driver_test.go b/platforms/sphero/bb8/bb8_driver_test.go index d937730f7..05c3f425d 100644 --- a/platforms/sphero/bb8/bb8_driver_test.go +++ b/platforms/sphero/bb8/bb8_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -24,6 +25,6 @@ func TestBB8Driver(t *testing.T) { func TestBB8DriverStartAndHalt(t *testing.T) { d := initTestBB8Driver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } diff --git a/platforms/sphero/ollie/ollie_driver_test.go b/platforms/sphero/ollie/ollie_driver_test.go index 4da63a2e4..5294bb569 100644 --- a/platforms/sphero/ollie/ollie_driver_test.go +++ b/platforms/sphero/ollie/ollie_driver_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/sphero" ) @@ -26,8 +27,8 @@ func TestOllieDriver(t *testing.T) { func TestOllieDriverStartAndHalt(t *testing.T) { d := initTestOllieDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } func TestLocatorData(t *testing.T) { diff --git a/platforms/sphero/sphero_adaptor_test.go b/platforms/sphero/sphero_adaptor_test.go index 1ca2a7205..f9e4f3c89 100644 --- a/platforms/sphero/sphero_adaptor_test.go +++ b/platforms/sphero/sphero_adaptor_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -82,23 +83,23 @@ func TestSpheroAdaptorReconnect(t *testing.T) { func TestSpheroAdaptorFinalize(t *testing.T) { a, rwc := initTestSpheroAdaptor() _ = a.Connect() - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) rwc.testAdaptorClose = func() error { return errors.New("close error") } a.connected = true - assert.ErrorContains(t, a.Finalize(), "close error") + require.ErrorContains(t, a.Finalize(), "close error") } func TestSpheroAdaptorConnect(t *testing.T) { a, _ := initTestSpheroAdaptor() - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) a.connect = func(string) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } - assert.ErrorContains(t, a.Connect(), "connect error") + require.ErrorContains(t, a.Connect(), "connect error") } diff --git a/platforms/sphero/sphero_driver_test.go b/platforms/sphero/sphero_driver_test.go index 879455c62..728bf3063 100644 --- a/platforms/sphero/sphero_driver_test.go +++ b/platforms/sphero/sphero_driver_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -84,13 +85,13 @@ func TestSpheroDriver(t *testing.T) { func TestSpheroDriverStart(t *testing.T) { d := initTestSpheroDriver() - assert.NoError(t, d.Start()) + require.NoError(t, d.Start()) } func TestSpheroDriverHalt(t *testing.T) { d := initTestSpheroDriver() d.adaptor().connected = true - assert.NoError(t, d.Halt()) + require.NoError(t, d.Halt()) } func TestSpheroDriverSetDataStreaming(t *testing.T) { diff --git a/platforms/sphero/sprkplus/sprkplus_driver_test.go b/platforms/sphero/sprkplus/sprkplus_driver_test.go index 80097850f..a050e505a 100644 --- a/platforms/sphero/sprkplus/sprkplus_driver_test.go +++ b/platforms/sphero/sprkplus/sprkplus_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -24,6 +25,6 @@ func TestSPRKPlusDriver(t *testing.T) { func TestSPRKPlusDriverStartAndHalt(t *testing.T) { d := initTestSPRKPlusDriver() - assert.NoError(t, d.Start()) - assert.NoError(t, d.Halt()) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) } diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 14a9dae1c..4835b66a3 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -2,10 +2,12 @@ package tinkerboard import ( "fmt" + "strconv" "strings" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -92,8 +94,8 @@ func TestDigitalIO(t *testing.T) { i, _ := a.DigitalRead("10") assert.Equal(t, 1, i) - assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") - assert.NoError(t, a.Finalize()) + require.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + require.NoError(t, a.Finalize()) } func TestInvalidPWMPin(t *testing.T) { @@ -101,16 +103,16 @@ func TestInvalidPWMPin(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("666", 42) - assert.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") err = a.ServoWrite("666", 120) - assert.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") err = a.PwmWrite("3", 42) - assert.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") err = a.ServoWrite("3", 120) - assert.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") + require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") } func TestPwmWrite(t *testing.T) { @@ -118,24 +120,24 @@ func TestPwmWrite(t *testing.T) { preparePwmFs(fs) err := a.PwmWrite("33", 100) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", 10000000), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, strconv.Itoa(10000000), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) err = a.ServoWrite("33", 0) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("33", 180) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestSetPeriod(t *testing.T) { @@ -147,25 +149,25 @@ func TestSetPeriod(t *testing.T) { // act err := a.SetPeriod("33", newPeriod) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here assert.Equal(t, "0", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("33", 127) // 127 is a little bit smaller than 50% of period - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 1270000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(1270000), fs.Files[pwmDutyCyclePath].Contents) newPeriod = newPeriod / 10 // act err = a.SetPeriod("33", newPeriod) // assert - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 127000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(127000), fs.Files[pwmDutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value newPeriod = newPeriod * 20 @@ -174,14 +176,14 @@ func TestSetPeriod(t *testing.T) { err = a.SetPeriod("33", newPeriod) // assert - assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%d", 2540000), fs.Files[pwmDutyCyclePath].Contents) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(2540000), fs.Files[pwmDutyCyclePath].Contents) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - assert.NoError(t, a.DigitalWrite("7", 1)) + require.NoError(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true @@ -193,7 +195,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) - assert.NoError(t, a.PwmWrite("33", 1)) + require.NoError(t, a.PwmWrite("33", 1)) fs.WithWriteError = true @@ -221,11 +223,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-4"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 4) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index 859a324a5..82faaa203 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -77,8 +78,8 @@ func TestDigitalIO(t *testing.T) { fs.Files["/sys/class/leds/upboard:green:/brightness"].Contents, ) - assert.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") - assert.NoError(t, a.Finalize()) + require.ErrorContains(t, a.DigitalWrite("99", 1), "'99' is not a valid id for a digital pin") + require.NoError(t, a.Finalize()) } func TestPWM(t *testing.T) { @@ -87,7 +88,7 @@ func TestPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" err := a.PwmWrite("32", 100) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "0", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents) @@ -96,24 +97,24 @@ func TestPWM(t *testing.T) { assert.Equal(t, "normal", fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents) err = a.ServoWrite("32", 0) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) err = a.ServoWrite("32", 180) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "2000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) - assert.NoError(t, a.Finalize()) + require.NoError(t, a.Finalize()) } func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) - assert.NoError(t, a.DigitalWrite("7", 1)) + require.NoError(t, a.DigitalWrite("7", 1)) fs.WithWriteError = true @@ -126,7 +127,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" - assert.NoError(t, a.PwmWrite("32", 1)) + require.NoError(t, a.PwmWrite("32", 1)) fs.WithWriteError = true @@ -184,11 +185,11 @@ func TestI2cFinalizeWithErrors(t *testing.T) { a := NewAdaptor() a.sys.UseMockSyscall() fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-5"}) - assert.NoError(t, a.Connect()) + require.NoError(t, a.Connect()) con, err := a.GetI2cConnection(0xff, 5) - assert.NoError(t, err) + require.NoError(t, err) _, err = con.Write([]byte{0xbf}) - assert.NoError(t, err) + require.NoError(t, err) fs.WithCloseError = true // act err = a.Finalize() diff --git a/robot_test.go b/robot_test.go index dcf9df1cf..2c7571621 100644 --- a/robot_test.go +++ b/robot_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestRobotConnectionEach(t *testing.T) { @@ -23,24 +24,24 @@ func TestRobotToJSON(t *testing.T) { return nil }) json := NewJSONRobot(r) - assert.Equal(t, r.Devices().Len(), len(json.Devices)) - assert.Equal(t, len(r.Commands()), len(json.Commands)) + assert.Len(t, json.Devices, r.Devices().Len()) + assert.Len(t, json.Commands, len(r.Commands())) } func TestRobotDevicesToJSON(t *testing.T) { r := newTestRobot("Robot99") json := NewJSONRobot(r) - assert.Equal(t, r.Devices().Len(), len(json.Devices)) + assert.Len(t, json.Devices, r.Devices().Len()) assert.Equal(t, "Device1", json.Devices[0].Name) assert.Equal(t, "*gobot.testDriver", json.Devices[0].Driver) assert.Equal(t, "Connection1", json.Devices[0].Connection) - assert.Equal(t, 1, len(json.Devices[0].Commands)) + assert.Len(t, json.Devices[0].Commands, 1) } func TestRobotStart(t *testing.T) { r := newTestRobot("Robot99") - assert.NoError(t, r.Start()) - assert.NoError(t, r.Stop()) + require.NoError(t, r.Start()) + require.NoError(t, r.Stop()) assert.False(t, r.Running()) } @@ -55,13 +56,13 @@ func TestRobotStartAutoRun(t *testing.T) { ) go func() { - assert.NoError(t, r.Start()) + require.NoError(t, r.Start()) }() time.Sleep(10 * time.Millisecond) assert.True(t, r.Running()) // stop it - assert.NoError(t, r.Stop()) + require.NoError(t, r.Stop()) assert.False(t, r.Running()) } diff --git a/system/digitalpin_gpiod_test.go b/system/digitalpin_gpiod_test.go index 30d7ba823..a6e086202 100644 --- a/system/digitalpin_gpiod_test.go +++ b/system/digitalpin_gpiod_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -259,7 +260,7 @@ func TestWriteGpiod(t *testing.T) { assert.Contains(t, err.Error(), want) } } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tc.want, lm.lastVal) }) @@ -294,7 +295,7 @@ func TestReadGpiod(t *testing.T) { assert.Contains(t, err.Error(), want) } } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, got, tc.simVal) }) diff --git a/system/digitalpin_poll_test.go b/system/digitalpin_poll_test.go index c9a9fd3d1..d72011008 100644 --- a/system/digitalpin_poll_test.go +++ b/system/digitalpin_poll_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_startEdgePolling(t *testing.T) { @@ -164,11 +165,11 @@ func Test_startEdgePolling(t *testing.T) { wg.Wait() // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } - assert.Equal(t, len(tc.simulateReadValues), numCallsRead) + assert.Len(t, tc.simulateReadValues, numCallsRead) assert.Equal(t, tc.wantEdgeTypes, edgeTypes) }) } diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index 04b025ecd..6efa8117f 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -92,9 +92,9 @@ func TestApplyOptionsSysfs(t *testing.T) { err := pin.ApplyOptions(optionFunction1, optionFunction2) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, OUT, pin.digitalPinConfig.direction) assert.Equal(t, 15, pin.digitalPinConfig.drive) @@ -321,9 +321,9 @@ func TestDigitalPinExportSysfs(t *testing.T) { err := pin.Export() // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, pin.valFile) assert.NotNil(t, pin.dirFile) assert.Equal(t, tc.wantDirection, fs.Files[dirPath].Contents) @@ -351,28 +351,28 @@ func TestDigitalPinSysfs(t *testing.T) { assert.Nil(t, pin.valFile) err := pin.Unexport() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "10", fs.Files["/sys/class/gpio/unexport"].Contents) require.NoError(t, pin.Export()) err = pin.Write(1) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio10/value"].Contents) err = pin.ApplyOptions(WithPinDirectionInput()) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "in", fs.Files["/sys/class/gpio/gpio10/direction"].Contents) data, _ := pin.Read() - assert.Equal(t, data, 1) + assert.Equal(t, 1, data) pin2 := newDigitalPinSysfs(fs, "30") err = pin2.Write(1) - assert.ErrorContains(t, err, "pin has not been exported") + require.ErrorContains(t, err, "pin has not been exported") data, err = pin2.Read() - assert.ErrorContains(t, err, "pin has not been exported") + require.ErrorContains(t, err, "pin has not been exported") assert.Equal(t, 0, data) writeFile = func(File, []byte) error { @@ -380,14 +380,14 @@ func TestDigitalPinSysfs(t *testing.T) { } err = pin.Unexport() - assert.NoError(t, err) + require.NoError(t, err) writeFile = func(File, []byte) error { return &os.PathError{Err: errors.New("write error")} } err = pin.Unexport() - assert.ErrorContains(t, err.(*os.PathError).Err, "write error") + require.ErrorContains(t, err.(*os.PathError).Err, "write error") } func TestDigitalPinUnexportErrorSysfs(t *testing.T) { @@ -401,5 +401,5 @@ func TestDigitalPinUnexportErrorSysfs(t *testing.T) { } err := pin.Unexport() - assert.ErrorContains(t, err, " : device or resource busy") + require.ErrorContains(t, err, " : device or resource busy") } diff --git a/system/fs_mock_test.go b/system/fs_mock_test.go index 17296912d..849c8e4ee 100644 --- a/system/fs_mock_test.go +++ b/system/fs_mock_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMockFilesystemOpen(t *testing.T) { @@ -14,13 +15,13 @@ func TestMockFilesystemOpen(t *testing.T) { assert.False(t, f1.Opened) f2, err := fs.openFile("foo", 0, 0o666) assert.Equal(t, f2, f1) - assert.NoError(t, err) + require.NoError(t, err) err = f2.Sync() - assert.NoError(t, err) + require.NoError(t, err) _, err = fs.openFile("bar", 0, 0o666) - assert.ErrorContains(t, err, " : bar: no such file") + require.ErrorContains(t, err, " : bar: no such file") fs.Add("bar") f4, _ := fs.openFile("bar", 0, 0o666) @@ -31,15 +32,15 @@ func TestMockFilesystemStat(t *testing.T) { fs := newMockFilesystem([]string{"foo", "bar/baz"}) fileStat, err := fs.stat("foo") - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, fileStat.IsDir()) dirStat, err := fs.stat("bar") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, dirStat.IsDir()) _, err = fs.stat("plonk") - assert.ErrorContains(t, err, " : plonk: no such file") + require.ErrorContains(t, err, " : plonk: no such file") } func TestMockFilesystemFind(t *testing.T) { @@ -61,7 +62,7 @@ func TestMockFilesystemFind(t *testing.T) { // act dirs, err := fs.find(tt.baseDir, tt.pattern) // assert - assert.NoError(t, err) + require.NoError(t, err) sort.Strings(dirs) assert.Equal(t, tt.want, dirs) }) @@ -73,13 +74,13 @@ func TestMockFilesystemWrite(t *testing.T) { f1 := fs.Files["bar"] f2, err := fs.openFile("bar", 0, 0o666) - assert.NoError(t, err) + require.NoError(t, err) // Never been read or written. - assert.True(t, f1.Seq <= 0) + assert.LessOrEqual(t, f1.Seq, 0) _, _ = f2.WriteString("testing") // Was written. - assert.True(t, f1.Seq > 0) + assert.Greater(t, f1.Seq, 0) assert.Equal(t, "testing", f1.Contents) } @@ -89,15 +90,15 @@ func TestMockFilesystemRead(t *testing.T) { f1.Contents = "Yip" f2, err := fs.openFile("bar", 0, 0o666) - assert.NoError(t, err) + require.NoError(t, err) // Never been read or written. - assert.True(t, f1.Seq <= 0) + assert.LessOrEqual(t, f1.Seq, 0) buffer := make([]byte, 20) n, _ := f2.Read(buffer) // Was read. - assert.True(t, f1.Seq > 0) + assert.Greater(t, f1.Seq, 0) assert.Equal(t, 3, n) assert.Equal(t, "Yip", string(buffer[:3])) diff --git a/system/fs_test.go b/system/fs_test.go index ae7d79113..954cc97c4 100644 --- a/system/fs_test.go +++ b/system/fs_test.go @@ -5,18 +5,19 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestFilesystemOpen(t *testing.T) { fs := &nativeFilesystem{} file, err := fs.openFile(os.DevNull, os.O_RDONLY, 0o666) - assert.NoError(t, err) + require.NoError(t, err) var _ File = file } func TestFilesystemStat(t *testing.T) { fs := &nativeFilesystem{} fileInfo, err := fs.stat(os.DevNull) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, fileInfo) } diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index 31dc1d333..78e59823d 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -6,6 +6,7 @@ import ( "unsafe" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -81,11 +82,11 @@ func TestNewI2cDevice(t *testing.T) { d, err := a.NewI2cDevice(tc.dev) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) assert.Equal(t, (*i2cDevice)(nil), d) } else { var _ gobot.I2cSystemDevicer = d - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -95,7 +96,7 @@ func TestClose(t *testing.T) { // arrange d, _ := initTestI2cDeviceWithMockedSys() // act & assert - assert.NoError(t, d.Close()) + require.NoError(t, d.Close()) } func TestWriteRead(t *testing.T) { @@ -107,10 +108,10 @@ func TestWriteRead(t *testing.T) { wn, werr := d.Write(1, wbuf) rn, rerr := d.Read(1, rbuf) // assert - assert.NoError(t, werr) - assert.NoError(t, rerr) - assert.Equal(t, len(wbuf), wn) - assert.Equal(t, len(wbuf), rn) // will read only the written values + require.NoError(t, werr) + require.NoError(t, rerr) + assert.Len(t, wbuf, wn) + assert.Len(t, wbuf, rn) // will read only the written values assert.Equal(t, rbuf[:len(wbuf)], wbuf) } @@ -145,9 +146,9 @@ func TestReadByte(t *testing.T) { got, err := d.ReadByte(2) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) @@ -193,9 +194,9 @@ func TestReadByteData(t *testing.T) { got, err := d.ReadByteData(3, reg) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) @@ -244,9 +245,9 @@ func TestReadWordData(t *testing.T) { got, err := d.ReadWordData(4, reg) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, want, got) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) @@ -303,9 +304,9 @@ func TestReadBlockData(t *testing.T) { err := d.ReadBlockData(5, reg, buf) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, msc.dataSlice, buf) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) @@ -348,9 +349,9 @@ func TestWriteByte(t *testing.T) { err := d.WriteByte(6, val) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) @@ -394,15 +395,15 @@ func TestWriteByteData(t *testing.T) { err := d.WriteByteData(7, reg, val) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) assert.Equal(t, reg, msc.smbus.command) assert.Equal(t, uint32(I2C_SMBUS_BYTE_DATA), msc.smbus.protocol) - assert.Equal(t, 1, len(msc.dataSlice)) + assert.Len(t, msc.dataSlice, 1) assert.Equal(t, val, msc.dataSlice[0]) } }) @@ -444,15 +445,15 @@ func TestWriteWordData(t *testing.T) { err := d.WriteWordData(8, reg, val) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) assert.Equal(t, byte(I2C_SMBUS_WRITE), msc.smbus.readWrite) assert.Equal(t, reg, msc.smbus.command) assert.Equal(t, uint32(I2C_SMBUS_WORD_DATA), msc.smbus.protocol) - assert.Equal(t, 2, len(msc.dataSlice)) + assert.Len(t, msc.dataSlice, 2) // all common drivers write LSByte first assert.Equal(t, wantLSByte, msc.dataSlice[0]) assert.Equal(t, wantMSByte, msc.dataSlice[1]) @@ -502,9 +503,9 @@ func TestWriteBlockData(t *testing.T) { err := d.WriteBlockData(9, reg, data) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, d.file, msc.lastFile) assert.Equal(t, uintptr(I2C_SMBUS), msc.lastSignal) assert.Equal(t, uint8(len(data)+1), msc.sliceSize) // including size element @@ -524,7 +525,7 @@ func TestWriteBlockDataTooMuch(t *testing.T) { // act err := d.WriteBlockData(10, 0x01, make([]byte, 33)) // assert - assert.ErrorContains(t, err, "Writing blocks larger than 32 bytes (33) not supported") + require.ErrorContains(t, err, "Writing blocks larger than 32 bytes (33) not supported") } func Test_setAddress(t *testing.T) { @@ -533,7 +534,7 @@ func Test_setAddress(t *testing.T) { // act err := d.setAddress(0xff) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uintptr(0xff), msc.devAddress) } @@ -575,9 +576,9 @@ func Test_queryFunctionality(t *testing.T) { err := d.queryFunctionality(tc.requested, "test"+name) // assert if tc.wantErr != "" { - assert.ErrorContains(t, err, tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) } else { - assert.NoError(t, err) + require.NoError(t, err) } if tc.wantFile { assert.NotNil(t, d.file) diff --git a/system/pwmpin_sysfs.go b/system/pwmpin_sysfs.go index 5950b7674..2980a977f 100644 --- a/system/pwmpin_sysfs.go +++ b/system/pwmpin_sysfs.go @@ -91,7 +91,7 @@ func (p *pwmPinSysFs) SetEnabled(enable bool) error { if enable { enableVal = 1 } - if _, err := p.write(p.fs, p.pwmEnablePath(), []byte(fmt.Sprintf("%v", enableVal))); err != nil { + if _, err := p.write(p.fs, p.pwmEnablePath(), []byte(strconv.Itoa(enableVal))); err != nil { if pwmDebug { p.printState() } @@ -158,6 +158,7 @@ func (p *pwmPinSysFs) Period() (uint32, error) { // SetPeriod writes the current period in nanoseconds func (p *pwmPinSysFs) SetPeriod(period uint32) error { + //nolint:perfsprint // ok here if _, err := p.write(p.fs, p.pwmPeriodPath(), []byte(fmt.Sprintf("%v", period))); err != nil { if pwmDebug { @@ -181,6 +182,7 @@ func (p *pwmPinSysFs) DutyCycle() (uint32, error) { // SetDutyCycle writes the duty cycle in nanoseconds func (p *pwmPinSysFs) SetDutyCycle(duty uint32) error { + //nolint:perfsprint // ok here if _, err := p.write(p.fs, p.pwmDutyCyclePath(), []byte(fmt.Sprintf("%v", duty))); err != nil { if pwmDebug { p.printState() diff --git a/system/pwmpin_sysfs_test.go b/system/pwmpin_sysfs_test.go index 63f458935..c0ba78967 100644 --- a/system/pwmpin_sysfs_test.go +++ b/system/pwmpin_sysfs_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -35,39 +36,39 @@ func TestPwmPin(t *testing.T) { assert.Equal(t, "10", pin.pin) err := pin.Unexport() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "10", fs.Files["/sys/class/pwm/pwmchip0/unexport"].Contents) err = pin.Export() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "10", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) - assert.NoError(t, pin.SetPolarity(false)) + require.NoError(t, pin.SetPolarity(false)) assert.Equal(t, inverted, fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].Contents) pol, _ := pin.Polarity() assert.False(t, pol) - assert.NoError(t, pin.SetPolarity(true)) + require.NoError(t, pin.SetPolarity(true)) assert.Equal(t, normal, fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].Contents) pol, _ = pin.Polarity() assert.True(t, pol) assert.NotEqual(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents) err = pin.SetEnabled(true) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/enable"].Contents) err = pin.SetPolarity(true) - assert.ErrorContains(t, err, "Cannot set PWM polarity when enabled") + require.ErrorContains(t, err, "Cannot set PWM polarity when enabled") fs.Files["/sys/class/pwm/pwmchip0/pwm10/period"].Contents = "6" data, _ := pin.Period() assert.Equal(t, uint32(6), data) - assert.NoError(t, pin.SetPeriod(100000)) + require.NoError(t, pin.SetPeriod(100000)) data, _ = pin.Period() assert.Equal(t, uint32(100000), data) assert.NotEqual(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].Contents) err = pin.SetDutyCycle(100) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "100", fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].Contents) data, _ = pin.DutyCycle() assert.Equal(t, uint32(100), data) @@ -88,7 +89,7 @@ func TestPwmPinAlreadyExported(t *testing.T) { } // no error indicates that the pin was already exported - assert.NoError(t, pin.Export()) + require.NoError(t, pin.Export()) } func TestPwmPinExportError(t *testing.T) { @@ -107,7 +108,7 @@ func TestPwmPinExportError(t *testing.T) { // no error indicates that the pin was already exported err := pin.Export() - assert.ErrorContains(t, err, "Export() failed for id 10 with : bad address") + require.ErrorContains(t, err, "Export() failed for id 10 with : bad address") } func TestPwmPinUnxportError(t *testing.T) { @@ -125,7 +126,7 @@ func TestPwmPinUnxportError(t *testing.T) { } err := pin.Unexport() - assert.ErrorContains(t, err, "Unexport() failed for id 10 with : device or resource busy") + require.ErrorContains(t, err, "Unexport() failed for id 10 with : device or resource busy") } func TestPwmPinPeriodError(t *testing.T) { @@ -143,7 +144,7 @@ func TestPwmPinPeriodError(t *testing.T) { } _, err := pin.Period() - assert.ErrorContains(t, err, "Period() failed for id 10 with : device or resource busy") + require.ErrorContains(t, err, "Period() failed for id 10 with : device or resource busy") } func TestPwmPinPolarityError(t *testing.T) { @@ -161,7 +162,7 @@ func TestPwmPinPolarityError(t *testing.T) { } _, err := pin.Polarity() - assert.ErrorContains(t, err, "Polarity() failed for id 10 with : device or resource busy") + require.ErrorContains(t, err, "Polarity() failed for id 10 with : device or resource busy") } func TestPwmPinDutyCycleError(t *testing.T) { @@ -179,5 +180,5 @@ func TestPwmPinDutyCycleError(t *testing.T) { } _, err := pin.DutyCycle() - assert.ErrorContains(t, err, "DutyCycle() failed for id 10 with : device or resource busy") + require.ErrorContains(t, err, "DutyCycle() failed for id 10 with : device or resource busy") } diff --git a/system/system_test.go b/system/system_test.go index 83f1c46df..b29bd52d3 100644 --- a/system/system_test.go +++ b/system/system_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNewAccesser(t *testing.T) { @@ -34,7 +35,7 @@ func TestNewAccesser_NewSpiDevice(t *testing.T) { // act con, err := a.NewSpiDevice(busNum, chipNum, mode, bits, maxSpeed) // assert - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, con) assert.Equal(t, busNum, spi.busNum) assert.Equal(t, chipNum, spi.chipNum) diff --git a/utils_test.go b/utils_test.go index e07e299e6..19238a501 100644 --- a/utils_test.go +++ b/utils_test.go @@ -64,18 +64,18 @@ func TestAfter(t *testing.T) { } func TestFromScale(t *testing.T) { - assert.Equal(t, 0.5, FromScale(5, 0, 10)) + assert.InDelta(t, 0.5, FromScale(5, 0, 10), 0.0) } func TestToScale(t *testing.T) { - assert.Equal(t, 10.0, ToScale(500, 0, 10)) - assert.Equal(t, 0.0, ToScale(-1, 0, 10)) - assert.Equal(t, 5.0, ToScale(0.5, 0, 10)) + assert.InDelta(t, 10.0, ToScale(500, 0, 10), 0.0) + assert.InDelta(t, 0.0, ToScale(-1, 0, 10), 0.0) + assert.InDelta(t, 5.0, ToScale(0.5, 0, 10), 0.0) } func TestRescale(t *testing.T) { - assert.Equal(t, 5.0, Rescale(500, 0, 1000, 0, 10)) - assert.Equal(t, 490.0, Rescale(-1.0, -1, 0, 490, 350)) + assert.InDelta(t, 5.0, Rescale(500, 0, 1000, 0, 10), 0.0) + assert.InDelta(t, 490.0, Rescale(-1.0, -1, 0, 490, 350), 0.0) } func TestRand(t *testing.T) { From 7f78edefcdf4bb1a09e011090175af4c401a57a1 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Wed, 15 Nov 2023 20:51:52 +0100 Subject: [PATCH 29/57] lint(all): fix issues of errorlint etc (#1037) --- .golangci.yml | 55 +-- api/api.go | 46 +-- api/api_test.go | 4 +- api/basic_auth_test.go | 1 + api/cors.go | 13 +- api/cors_test.go | 1 + api/helpers_test.go | 19 +- connection.go | 6 +- device.go | 6 +- doc.go | 9 +- drivers/aio/aio.go | 2 +- drivers/aio/analog_actuator_driver.go | 26 +- drivers/aio/analog_sensor_driver.go | 24 +- drivers/aio/analog_sensor_driver_test.go | 29 +- drivers/aio/grove_drivers.go | 8 +- drivers/aio/grove_drivers_test.go | 7 +- .../aio/grove_temperature_sensor_driver.go | 2 +- .../grove_temperature_sensor_driver_test.go | 12 +- drivers/aio/helpers_test.go | 20 +- drivers/aio/temperature_sensor_driver.go | 9 +- drivers/aio/temperature_sensor_driver_test.go | 29 +- .../common/mfrc522/mfrc522_pcd_register.go | 1 + drivers/common/mfrc522/mfrc522_pcd_test.go | 4 +- drivers/common/mfrc522/mfrc522_picc.go | 5 +- drivers/gpio/aip1640_driver_test.go | 7 +- drivers/gpio/button_driver.go | 69 ++-- drivers/gpio/button_driver_test.go | 1 + drivers/gpio/buzzer_driver.go | 68 ++-- drivers/gpio/buzzer_driver_test.go | 7 +- drivers/gpio/direct_pin_driver.go | 40 +-- drivers/gpio/direct_pin_driver_test.go | 13 +- drivers/gpio/easy_driver.go | 7 + drivers/gpio/gpio_driver.go | 14 +- drivers/gpio/gpio_driver_test.go | 1 + drivers/gpio/grove_drivers_test.go | 7 +- drivers/gpio/hcsr04_driver_test.go | 1 + drivers/gpio/hd44780_driver.go | 56 +-- drivers/gpio/hd44780_driver_test.go | 4 +- drivers/gpio/helpers_test.go | 48 +-- drivers/gpio/led_driver.go | 87 ++--- drivers/gpio/led_driver_test.go | 15 +- drivers/gpio/max7219_driver.go | 1 + drivers/gpio/max7219_driver_test.go | 7 +- drivers/gpio/motor_driver.go | 214 ++++++------ drivers/gpio/motor_driver_test.go | 1 + drivers/gpio/pir_motion_driver.go | 61 ++-- drivers/gpio/pir_motion_driver_test.go | 1 + drivers/gpio/relay_driver.go | 92 ++--- drivers/gpio/relay_driver_test.go | 5 +- drivers/gpio/rgb_led_driver.go | 119 ++++--- drivers/gpio/rgb_led_driver_test.go | 15 +- drivers/gpio/servo_driver.go | 65 ++-- drivers/gpio/servo_driver_test.go | 4 +- drivers/gpio/stepper_driver.go | 9 +- drivers/gpio/tm1638_driver.go | 2 +- drivers/gpio/tm1638_driver_test.go | 7 +- drivers/i2c/adafruit1109_driver.go | 2 +- drivers/i2c/adafruit1109_driver_test.go | 1 + drivers/i2c/adafruit2327_driver_test.go | 1 + drivers/i2c/adafruit2348_driver.go | 9 +- drivers/i2c/adafruit2348_driver_test.go | 1 + drivers/i2c/ads1x15_driver.go | 121 ++++--- drivers/i2c/ads1x15_driver_test.go | 2 + drivers/i2c/adxl345_driver.go | 21 +- drivers/i2c/adxl345_driver_test.go | 11 +- drivers/i2c/bh1750_driver.go | 24 +- drivers/i2c/bh1750_driver_test.go | 1 + drivers/i2c/blinkm_driver.go | 36 +- drivers/i2c/blinkm_driver_test.go | 2 + drivers/i2c/bme280_driver.go | 10 +- drivers/i2c/bme280_driver_test.go | 53 +-- drivers/i2c/bmp180_driver.go | 30 +- drivers/i2c/bmp180_driver_test.go | 28 +- drivers/i2c/bmp280_driver.go | 33 +- drivers/i2c/bmp280_driver_test.go | 12 +- drivers/i2c/bmp388_driver.go | 45 +-- drivers/i2c/bmp388_driver_test.go | 9 +- drivers/i2c/ccs811_driver.go | 26 +- drivers/i2c/ccs811_driver_test.go | 1 + drivers/i2c/drv2605l_driver.go | 36 +- drivers/i2c/drv2605l_driver_test.go | 4 +- drivers/i2c/generic_driver_test.go | 1 + drivers/i2c/grove_drivers_test.go | 13 +- drivers/i2c/grovepi_driver.go | 10 +- drivers/i2c/grovepi_driver_test.go | 5 +- drivers/i2c/helpers_test.go | 54 +-- drivers/i2c/hmc5883l_driver.go | 55 +-- drivers/i2c/hmc5883l_driver_test.go | 1 + drivers/i2c/hmc6352_driver.go | 15 +- drivers/i2c/hmc6352_driver_test.go | 1 + drivers/i2c/i2c_config_test.go | 1 + drivers/i2c/i2c_connection.go | 12 +- drivers/i2c/i2c_connection_test.go | 2 + drivers/i2c/i2c_driver.go | 8 +- drivers/i2c/i2c_driver_test.go | 1 + drivers/i2c/ina3221_driver_test.go | 1 + drivers/i2c/jhd1313m1_driver.go | 135 ++++---- drivers/i2c/jhd1313m1_driver_test.go | 7 +- drivers/i2c/l3gd20h_driver.go | 3 + drivers/i2c/l3gd20h_driver_test.go | 17 +- drivers/i2c/lidarlite_driver.go | 28 +- drivers/i2c/lidarlite_driver_test.go | 7 +- drivers/i2c/mcp23017_driver.go | 80 ++--- drivers/i2c/mcp23017_driver_test.go | 4 +- drivers/i2c/mma7660_driver.go | 4 + drivers/i2c/mma7660_driver_test.go | 11 +- drivers/i2c/mpl115a2_driver.go | 18 +- drivers/i2c/mpl115a2_driver_test.go | 1 + drivers/i2c/mpu6050_driver_test.go | 1 + drivers/i2c/pca9501_driver.go | 9 +- drivers/i2c/pca9501_driver_test.go | 2 + drivers/i2c/pca953x_driver_test.go | 1 + drivers/i2c/pca9685_driver.go | 35 +- drivers/i2c/pca9685_driver_test.go | 1 + drivers/i2c/pcf8583_driver.go | 44 +-- drivers/i2c/pcf8583_driver_test.go | 14 +- drivers/i2c/pcf8591_driver.go | 23 +- drivers/i2c/pcf8591_driver_test.go | 1 + drivers/i2c/sht2x_driver.go | 72 ++-- drivers/i2c/sht2x_driver_test.go | 8 +- drivers/i2c/sht3x_driver.go | 67 ++-- drivers/i2c/sht3x_driver_test.go | 1 + drivers/i2c/ssd1306_driver.go | 59 ++-- drivers/i2c/ssd1306_driver_test.go | 2 + drivers/i2c/th02_driver.go | 5 +- drivers/i2c/th02_driver_test.go | 1 + drivers/i2c/tsl2561_driver.go | 56 +-- drivers/i2c/tsl2561_driver_test.go | 1 + drivers/i2c/wiichuck_driver.go | 4 +- drivers/i2c/wiichuck_driver_test.go | 1 + drivers/i2c/yl40_driver.go | 28 +- drivers/i2c/yl40_driver_test.go | 10 +- drivers/spi/apa102_test.go | 1 + drivers/spi/mcp3002.go | 6 +- drivers/spi/mcp3002_test.go | 1 + drivers/spi/mcp3004.go | 17 +- drivers/spi/mcp3004_test.go | 1 + drivers/spi/mcp3008.go | 17 +- drivers/spi/mcp3008_test.go | 1 + drivers/spi/mcp3202.go | 19 +- drivers/spi/mcp3202_test.go | 1 + drivers/spi/mcp3204.go | 19 +- drivers/spi/mcp3204_test.go | 1 + drivers/spi/mcp3208.go | 19 +- drivers/spi/mcp3208_test.go | 1 + drivers/spi/mcp3304.go | 19 +- drivers/spi/mcp3304_test.go | 1 + drivers/spi/mfrc522_driver_test.go | 1 + drivers/spi/spi_connection_test.go | 1 + drivers/spi/spi_driver.go | 12 +- drivers/spi/spi_driver_test.go | 1 + drivers/spi/ssd1306_driver.go | 2 + drivers/spi/ssd1306_driver_test.go | 37 +- eventer.go | 12 +- examples/batty.go | 14 +- examples/raspi_adafruit2327_servo.go | 20 +- examples/raspi_adafruit2348_dcmotor.go | 24 +- examples/raspi_adafruit2348_stepper.go | 12 +- helpers_test.go | 22 +- master.go | 2 +- master_test.go | 12 +- platforms/adaptors/digitalpinsadaptor.go | 16 +- platforms/adaptors/digitalpinsadaptor_test.go | 4 +- platforms/adaptors/i2cbusadaptor.go | 1 + platforms/adaptors/i2cbusadaptor_test.go | 3 +- platforms/adaptors/pwmpinsadaptor.go | 12 +- platforms/adaptors/pwmpinsadaptor_test.go | 33 +- platforms/adaptors/spibusadaptor.go | 1 + platforms/adaptors/spibusadaptor_test.go | 3 +- platforms/audio/audio_adaptor.go | 13 +- platforms/audio/audio_adaptor_test.go | 7 +- platforms/audio/audio_driver.go | 9 +- platforms/audio/audio_driver_test.go | 3 +- platforms/beaglebone/beaglebone_adaptor.go | 19 +- .../beaglebone/beaglebone_adaptor_test.go | 9 +- platforms/beaglebone/black_pins.go | 29 +- platforms/ble/battery_driver.go | 16 +- platforms/ble/battery_driver_test.go | 1 + platforms/ble/ble_client_adaptor.go | 6 +- platforms/ble/ble_client_adaptor_test.go | 1 + platforms/ble/device_information_driver.go | 31 +- .../ble/device_information_driver_test.go | 1 + platforms/ble/generic_access_driver.go | 1 + platforms/ble/generic_access_driver_test.go | 1 + platforms/ble/helpers_test.go | 26 +- platforms/ble/serial_port.go | 16 +- platforms/chip/chip_adaptor.go | 7 +- platforms/chip/chip_adaptor_test.go | 7 +- platforms/dexter/gopigo3/driver.go | 324 +++++++++--------- platforms/dexter/gopigo3/driver_test.go | 165 +++------ platforms/digispark/digispark_adaptor.go | 40 +-- platforms/digispark/digispark_adaptor_test.go | 4 +- platforms/digispark/digispark_i2c.go | 91 ++--- platforms/digispark/digispark_i2c_test.go | 4 +- platforms/digispark/littleWire.go | 2 +- platforms/dji/tello/crc.go | 1 + platforms/dji/tello/driver.go | 13 +- platforms/dji/tello/driver_test.go | 8 +- platforms/dragonboard/dragonboard_adaptor.go | 1 + .../dragonboard/dragonboard_adaptor_test.go | 5 +- platforms/firmata/ble_firmata_adaptor.go | 3 +- platforms/firmata/ble_firmata_adaptor_test.go | 1 + platforms/firmata/client/client.go | 6 +- platforms/firmata/client/client_test.go | 2 +- platforms/firmata/firmata_adaptor.go | 15 +- platforms/firmata/firmata_adaptor_test.go | 2 + platforms/firmata/firmata_i2c.go | 10 +- platforms/firmata/firmata_i2c_test.go | 2 + platforms/firmata/tcp_firmata_adaptor.go | 14 +- platforms/firmata/tcp_firmata_adaptor_test.go | 1 + platforms/holystone/holystone.go | 2 + platforms/holystone/hs200/hs200_driver.go | 8 +- .../holystone/hs200/hs200_driver_test.go | 1 + platforms/intel-iot/curie/imu_driver.go | 1 + platforms/intel-iot/curie/imu_driver_test.go | 10 +- platforms/intel-iot/edison/edison_adaptor.go | 27 +- .../intel-iot/edison/edison_adaptor_test.go | 53 +-- platforms/intel-iot/joule/joule_adaptor.go | 4 +- .../intel-iot/joule/joule_adaptor_test.go | 7 +- platforms/jetson/jetson_adaptor.go | 7 +- platforms/jetson/jetson_adaptor_test.go | 3 +- platforms/jetson/pwm_pin.go | 2 +- platforms/joystick/joystick_adaptor.go | 8 +- platforms/joystick/joystick_adaptor_test.go | 4 +- platforms/joystick/joystick_driver.go | 6 +- platforms/joystick/joystick_driver_test.go | 8 +- platforms/keyboard/keyboard.go | 20 +- platforms/keyboard/keyboard_driver_test.go | 3 +- platforms/leap/leap_motion_adaptor.go | 16 +- platforms/leap/leap_motion_adaptor_test.go | 1 + platforms/leap/leap_motion_driver.go | 5 +- platforms/leap/leap_motion_driver_test.go | 1 + platforms/mavlink/common/common.go | 1 + platforms/mavlink/common/mavlink.go | 38 +- platforms/mavlink/mavlink_adaptor.go | 19 +- platforms/mavlink/mavlink_adaptor_test.go | 5 +- platforms/mavlink/mavlink_driver.go | 7 +- platforms/mavlink/mavlink_driver_test.go | 2 + platforms/mavlink/mavlink_udp_adaptor.go | 2 +- platforms/mavlink/mavlink_udp_adaptor_test.go | 1 + platforms/megapi/megapi_adaptor.go | 3 +- platforms/megapi/motor_driver.go | 54 +-- platforms/microbit/accelerometer_driver.go | 1 + .../microbit/accelerometer_driver_test.go | 2 + platforms/microbit/button_driver.go | 1 + platforms/microbit/button_driver_test.go | 1 + platforms/microbit/helpers_test.go | 26 +- platforms/microbit/io_pin_driver.go | 3 +- platforms/microbit/io_pin_driver_test.go | 1 + platforms/microbit/led_driver.go | 78 ++--- platforms/microbit/led_driver_test.go | 1 + platforms/microbit/magnetometer_driver.go | 1 + .../microbit/magnetometer_driver_test.go | 2 + platforms/microbit/temperature_driver.go | 1 + platforms/microbit/temperature_driver_test.go | 1 + platforms/mqtt/mqtt_adaptor.go | 7 +- platforms/mqtt/mqtt_adaptor_test.go | 5 +- platforms/mqtt/mqtt_driver.go | 2 + platforms/mqtt/mqtt_driver_test.go | 1 + platforms/nanopi/nanopi_adaptor.go | 7 +- platforms/nanopi/nanopi_adaptor_test.go | 7 +- platforms/nats/nats_adaptor.go | 1 + platforms/nats/nats_adaptor_test.go | 4 +- platforms/nats/nats_driver.go | 2 + platforms/nats/nats_driver_test.go | 1 + platforms/neurosky/neurosky_adaptor.go | 5 +- platforms/neurosky/neurosky_adaptor_test.go | 1 + platforms/neurosky/neurosky_driver.go | 3 +- platforms/neurosky/neurosky_driver_test.go | 2 + platforms/opencv/camera_driver.go | 8 +- platforms/opencv/camera_driver_test.go | 3 +- platforms/opencv/utils_test.go | 1 + platforms/opencv/window_driver.go | 4 +- platforms/opencv/window_driver_test.go | 1 + platforms/parrot/ardrone/ardrone_adaptor.go | 7 +- .../parrot/ardrone/ardrone_adaptor_test.go | 1 + platforms/parrot/ardrone/ardrone_driver.go | 9 +- .../parrot/ardrone/ardrone_driver_test.go | 1 + platforms/parrot/bebop/bebop_adaptor_test.go | 3 +- platforms/parrot/bebop/bebop_driver.go | 12 +- platforms/parrot/bebop/bebop_driver_test.go | 1 + platforms/parrot/bebop/client/client.go | 2 +- platforms/parrot/minidrone/helpers_test.go | 26 +- .../parrot/minidrone/minidrone_driver.go | 5 +- .../parrot/minidrone/minidrone_driver_test.go | 1 + platforms/particle/adaptor.go | 45 ++- platforms/particle/adaptor_test.go | 46 ++- platforms/pebble/doc.go | 3 +- platforms/pebble/pebble_adaptor.go | 8 +- platforms/pebble/pebble_adaptor_test.go | 1 + platforms/pebble/pebble_driver.go | 7 +- platforms/pebble/pebble_driver_test.go | 1 + platforms/raspi/pwm_pin.go | 6 +- platforms/raspi/pwm_pin_test.go | 1 + platforms/raspi/raspi_adaptor.go | 18 +- platforms/raspi/raspi_adaptor_test.go | 3 +- platforms/rockpi/rockpi_adaptor.go | 9 +- platforms/rockpi/rockpi_adaptor_test.go | 1 + platforms/sphero/bb8/bb8_driver_test.go | 1 + platforms/sphero/bb8/helpers_test.go | 26 +- platforms/sphero/ollie/helpers_test.go | 26 +- platforms/sphero/ollie/ollie_driver.go | 19 +- platforms/sphero/ollie/ollie_driver_test.go | 2 + platforms/sphero/sphero_adaptor.go | 20 +- platforms/sphero/sphero_adaptor_test.go | 1 + platforms/sphero/sphero_driver.go | 30 +- platforms/sphero/sphero_driver_test.go | 2 + platforms/sphero/sphero_packets.go | 9 +- platforms/sphero/sprkplus/helpers_test.go | 26 +- .../sphero/sprkplus/sprkplus_driver_test.go | 1 + platforms/tinkerboard/adaptor.go | 7 +- platforms/tinkerboard/adaptor_test.go | 7 +- platforms/upboard/up2/adaptor.go | 1 + platforms/upboard/up2/adaptor_test.go | 7 +- robot.go | 24 +- robot_work.go | 2 +- system/digitalpin_access_test.go | 1 + system/digitalpin_config.go | 2 + system/digitalpin_config_test.go | 1 + system/digitalpin_gpiod.go | 1 + system/digitalpin_gpiod_test.go | 5 +- system/digitalpin_mock.go | 4 +- system/digitalpin_sysfs.go | 18 +- system/digitalpin_sysfs_test.go | 5 +- system/fs.go | 2 +- system/fs_mock.go | 14 +- system/i2c_device.go | 25 +- system/i2c_device_test.go | 2 + system/pwmpin_sysfs.go | 7 +- system/pwmpin_sysfs_test.go | 1 + system/spi_access.go | 10 +- system/spi_gpio.go | 1 + system/spi_mock.go | 5 +- system/syscall.go | 2 + system/syscall_mock.go | 2 + system/system.go | 2 +- system/system_test.go | 1 + utils.go | 7 +- 338 files changed, 2814 insertions(+), 2377 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 465ecde60..cced8fe17 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -34,10 +34,11 @@ run: linters: # currently active linters: # - #INFO [lintersdb] Active 49 linters: [asasalint asciicheck bidichk contextcheck decorder depguard dupword durationcheck errcheck exportloopref - # gocheckcompilerdirectives gochecknoinits gochecksumtype gofmt gofumpt goimports gomoddirectives gomodguard goprintffuncname gosec gosimple govet grouper - # inamedparam ineffassign makezero mirror misspell musttag nilerr nilnil nolintlint nosprintfhostport perfsprint prealloc protogetter reassign revive - # sloglint staticcheck tagalign tenv testableexamples testifylint tparallel unconvert unparam unused wastedassign] + # INFO [lintersdb] Active 64 linters: [asasalint asciicheck bidichk bodyclose containedctx contextcheck decorder depguard dogsled dupword durationcheck + # errcheck errchkjson errorlint exportloopref forcetypeassert gci gocheckcompilerdirectives gochecknoinits gochecksumtype gocritic gofmt gofumpt goimports + # gomoddirectives gomodguard goprintffuncname gosec gosimple govet grouper inamedparam ineffassign lll makezero mirror misspell musttag nakedret nilerr nilnil + # noctx nolintlint nonamedreturns nosprintfhostport perfsprint prealloc predeclared protogetter reassign revive sloglint staticcheck tagalign tenv + # testableexamples testifylint thelper tparallel unconvert unparam unused usestdlibvars wastedassign] enable-all: true @@ -75,39 +76,23 @@ linters: - testpackage # not needed, we use the same name for test package to have access to unexposed items - wrapcheck # not needed (we allow errors from interface methods) - zerologlint # not needed (related to zerolog package) - # important to have - - errorlint # useful (reduce bugs), but suppress the "Use `%w` to format errors" check - - forcetypeassert # useful (reduce bugs) - - nakedret # very useful together with "nonamedreturns" (reduce bugs) - - nonamedreturns # very useful (reduce bugs) # useful for the future - - bodyclose # maybe useful (reduce bugs), exclusions for tests needed - - containedctx # useful (structs are not for context wrapping) - cyclop # useful with some tweeks (better understandable code), see also gocyclo - - dogsled # useful with some tweeks (e.g. exclude tests) - dupl # useful with some tweeks (reduce bugs and lines of code) - - errchkjson # useful (reduce bugs) - errname # useful for common style - exhaustruct # useful with some exclusions for existing code (e.g. mavlink/common/common.go) - funlen # useful with some tweeks (reduce bugs, simplify code, better understandable code) - - gci # useful (improve readability) - gocognit # useful with some tweeks (better understandable code) - goconst # useful (reduce bugs) - - gocritic # useful with some exclusions for existing code (e.g. mavlink/common/common.go) - gocyclo # useful with some tweeks (better understandable code) - goheader # useful, if we introduce a common header (e.g. for copyright) - gomnd # useful with some exclusions for existing code (e.g. mavlink.go) - interfacebloat # useful with some exclusions at usage of external packages - - lll # useful with some exclusions for existing code (e.g. mavlink/common/common.go) - maintidx # useful with some tweeks (better understandable code), maybe use instead "gocyclo", "gocognit" , "cyclop" - nestif # useful (reduce bugs, simplify code, better understandable code) - nlreturn # more common style, but could become annoying - - noctx # maybe good (show used context explicit) - - predeclared # useful (reduce bugs) - stylecheck # useful with some tweaking (e.g. underscores in names should be allowed - we use it for constants retrieved from C/C++) - tagliatelle # maybe useful with some tweaking or excluding - - thelper # useful - - usestdlibvars # useful - varnamelen # maybe useful with some tweaking, but many findings - whitespace # more common style, but could become annoying - wsl # more common style, but could become annoying @@ -145,6 +130,36 @@ linters-settings: - "and" - "a" + errorlint: + # Default: true + # %v should be used by default over %w, see https://github.com/uber-go/guide/blob/master/style.md#error-wrapping + errorf: false + # Permit more than 1 %w verb, valid per Go 1.20 (Requires errorf:true) + # Default: true + errorf-multi: false + + gci: + # Section configuration to compare against. + # Section names are case-insensitive and may contain parameters in (). + # The default order of sections is `standard > default > custom > blank > dot`, + # If `custom-order` is `true`, it follows the order of `sections` option. + # Default: ["standard", "default"] + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(gobot.io/x/gobot/) # Custom section: groups all imports with the specified Prefix. + #- blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + #- dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + # Enable custom order of sections. + # If `true`, make the section order the same as the order of `sections`. + # Default: false + custom-order: true + + gocritic: + disabled-checks: + - assignOp # very opinionated + - appendAssign # mostly used by intention + nolintlint: # Enable to require an explanation of nonzero length after each nolint directive. # Default: false diff --git a/api/api.go b/api/api.go index 448f2f8e2..b0de3dbb4 100644 --- a/api/api.go +++ b/api/api.go @@ -2,7 +2,6 @@ package api import ( "encoding/json" - "errors" "fmt" "log" "net/http" @@ -11,6 +10,7 @@ import ( "time" "github.com/bmizerany/pat" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api/robeaux" ) @@ -178,12 +178,14 @@ func (a *API) robeaux(res http.ResponseWriter, req *http.Request) { http.Error(res, err.Error(), http.StatusNotFound) return } - t := strings.Split(path, ".") - if t[len(t)-1] == "js" { + split := strings.Split(path, ".") + ext := split[len(split)-1] + switch ext { + case "js": res.Header().Set("Content-Type", "text/javascript; charset=utf-8") - } else if t[len(t)-1] == "css" { + case "css": res.Header().Set("Content-Type", "text/css; charset=utf-8") - } else if t[len(t)-1] == "html" { + case "html": res.Header().Set("Content-Type", "text/html; charset=utf-8") } if _, err := res.Write(buf); err != nil { @@ -269,9 +271,11 @@ func (a *API) robotDeviceEvent(res http.ResponseWriter, req *http.Request) { device := a.master.Robot(req.URL.Query().Get(":robot")). Device(req.URL.Query().Get(":device")) + //nolint:forcetypeassert // no error return value, so there is no better way if event := a.master.Robot(req.URL.Query().Get(":robot")). Device(req.URL.Query().Get(":device")).(gobot.Eventer). Event(req.URL.Query().Get(":event")); len(event) > 0 { + //nolint:forcetypeassert // no error return value, so there is no better way if err := device.(gobot.Eventer).On(event, func(data interface{}) { d, _ := json.Marshal(data) dataChan <- string(d) @@ -345,6 +349,7 @@ func (a *API) executeRobotDeviceCommand(res http.ResponseWriter, req *http.Reque a.writeJSON(map[string]interface{}{"error": err.Error()}, res) } else { a.executeCommand( + //nolint:forcetypeassert // no error return value, so there is no better way a.master.Robot(req.URL.Query().Get(":robot")). Device(req.URL.Query().Get(":device")).(gobot.Commander). Command(req.URL.Query().Get(":command")), @@ -387,7 +392,10 @@ func (a *API) executeCommand(f func(map[string]interface{}) interface{}, // writeJSON writes `j` as JSON in response func (a *API) writeJSON(j interface{}, res http.ResponseWriter) { - data, _ := json.Marshal(j) + data, err := json.Marshal(j) + if err != nil { + panic(err) + } res.Header().Set("Content-Type", "application/json; charset=utf-8") if _, err := res.Write(data); err != nil { panic(err) @@ -401,29 +409,25 @@ func (a *API) Debug() { }) } -func (a *API) jsonRobotFor(name string) (jrobot *gobot.JSONRobot, err error) { +func (a *API) jsonRobotFor(name string) (*gobot.JSONRobot, error) { if robot := a.master.Robot(name); robot != nil { - jrobot = gobot.NewJSONRobot(robot) - } else { - err = errors.New("No Robot found with the name " + name) + return gobot.NewJSONRobot(robot), nil } - return + return nil, fmt.Errorf("No Robot found with the name %s", name) } -func (a *API) jsonDeviceFor(robot string, name string) (jdevice *gobot.JSONDevice, err error) { +func (a *API) jsonDeviceFor(robot string, name string) (*gobot.JSONDevice, error) { if device := a.master.Robot(robot).Device(name); device != nil { - jdevice = gobot.NewJSONDevice(device) - } else { - err = errors.New("No Device found with the name " + name) + return gobot.NewJSONDevice(device), nil } - return + + return nil, fmt.Errorf("No Device found with the name %s", name) } -func (a *API) jsonConnectionFor(robot string, name string) (jconnection *gobot.JSONConnection, err error) { +func (a *API) jsonConnectionFor(robot string, name string) (*gobot.JSONConnection, error) { if connection := a.master.Robot(robot).Connection(name); connection != nil { - jconnection = gobot.NewJSONConnection(connection) - } else { - err = errors.New("No Connection found with the name " + name) + return gobot.NewJSONConnection(connection), nil } - return + + return nil, fmt.Errorf("No Connection found with the name %s", name) } diff --git a/api/api_test.go b/api/api_test.go index 267b11cc4..895f9416c 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert,usestdlibvars,bodyclose,noctx // ok here package api import ( @@ -12,6 +13,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) @@ -413,7 +415,7 @@ func TestRobotDeviceEvent(t *testing.T) { data, _ := reader.ReadString('\n') assert.Equal(t, "data: \"event-data\"\n", data) done = true - case <-time.After(100 * time.Millisecond): + case <-time.After(200 * time.Millisecond): t.Error("Not receiving data") done = true } diff --git a/api/basic_auth_test.go b/api/basic_auth_test.go index f00033f0c..4640b03ae 100644 --- a/api/basic_auth_test.go +++ b/api/basic_auth_test.go @@ -1,3 +1,4 @@ +//nolint:usestdlibvars,noctx // ok here package api import ( diff --git a/api/cors.go b/api/cors.go index 1f982ca8a..4b23c79ce 100644 --- a/api/cors.go +++ b/api/cors.go @@ -38,14 +38,13 @@ func AllowRequestsFrom(allowedOrigins ...string) http.HandlerFunc { } // isOriginAllowed returns true if origin matches an allowed origin pattern. -func (c *CORS) isOriginAllowed(origin string) (allowed bool) { +func (c *CORS) isOriginAllowed(origin string) bool { for _, allowedOriginPattern := range c.allowOriginPatterns { - allowed, _ = regexp.MatchString(allowedOriginPattern, origin) - if allowed { - return + if allowed, _ := regexp.MatchString(allowedOriginPattern, origin); allowed { + return true } } - return + return false } // generatePatterns generates regex expression for AllowOrigins @@ -53,8 +52,8 @@ func (c *CORS) generatePatterns() { if c.AllowOrigins != nil { for _, origin := range c.AllowOrigins { pattern := regexp.QuoteMeta(origin) - pattern = strings.Replace(pattern, "\\*", ".*", -1) - pattern = strings.Replace(pattern, "\\?", ".", -1) + pattern = strings.ReplaceAll(pattern, "\\*", ".*") + pattern = strings.ReplaceAll(pattern, "\\?", ".") c.allowOriginPatterns = append(c.allowOriginPatterns, "^"+pattern+"$") } } diff --git a/api/cors_test.go b/api/cors_test.go index cfd60eeb7..86f2dd01a 100644 --- a/api/cors_test.go +++ b/api/cors_test.go @@ -1,3 +1,4 @@ +//nolint:usestdlibvars,noctx // ok here package api import ( diff --git a/api/helpers_test.go b/api/helpers_test.go index 7e77d10f6..e821c8687 100644 --- a/api/helpers_test.go +++ b/api/helpers_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package api import ( @@ -28,8 +29,8 @@ type testDriver struct { gobot.Eventer } -func (t *testDriver) Start() (err error) { return } -func (t *testDriver) Halt() (err error) { return } +func (t *testDriver) Start() error { return nil } +func (t *testDriver) Halt() error { return nil } func (t *testDriver) Name() string { return t.name } func (t *testDriver) SetName(n string) { t.name = n } func (t *testDriver) Pin() string { return t.pin } @@ -65,15 +66,15 @@ type testAdaptor struct { } var ( - testAdaptorConnect = func() (err error) { return } - testAdaptorFinalize = func() (err error) { return } + testAdaptorConnect = func() error { return nil } + testAdaptorFinalize = func() error { return nil } ) -func (t *testAdaptor) Finalize() (err error) { return testAdaptorFinalize() } -func (t *testAdaptor) Connect() (err error) { return testAdaptorConnect() } -func (t *testAdaptor) Name() string { return t.name } -func (t *testAdaptor) SetName(n string) { t.name = n } -func (t *testAdaptor) Port() string { return t.port } +func (t *testAdaptor) Finalize() error { return testAdaptorFinalize() } +func (t *testAdaptor) Connect() error { return testAdaptorConnect() } +func (t *testAdaptor) Name() string { return t.name } +func (t *testAdaptor) SetName(n string) { t.name = n } +func (t *testAdaptor) Port() string { return t.port } func newTestAdaptor(name string, port string) *testAdaptor { return &testAdaptor{ diff --git a/connection.go b/connection.go index 75c8c037a..1e8a9bfe4 100644 --- a/connection.go +++ b/connection.go @@ -40,8 +40,9 @@ func (c *Connections) Each(f func(Connection)) { } // Start calls Connect on each Connection in c -func (c *Connections) Start() (err error) { +func (c *Connections) Start() error { log.Println("Starting connections...") + var err error for _, connection := range *c { info := "Starting connection " + connection.Name() @@ -59,7 +60,8 @@ func (c *Connections) Start() (err error) { } // Finalize calls Finalize on each Connection in c -func (c *Connections) Finalize() (err error) { +func (c *Connections) Finalize() error { + var err error for _, connection := range *c { if cerr := connection.Finalize(); cerr != nil { err = multierror.Append(err, cerr) diff --git a/device.go b/device.go index 924a1f7de..b45b0129e 100644 --- a/device.go +++ b/device.go @@ -53,8 +53,9 @@ func (d *Devices) Each(f func(Device)) { } // Start calls Start on each Device in d -func (d *Devices) Start() (err error) { +func (d *Devices) Start() error { log.Println("Starting devices...") + var err error for _, device := range *d { info := "Starting device " + device.Name() @@ -71,7 +72,8 @@ func (d *Devices) Start() (err error) { } // Halt calls Halt on each Device in d -func (d *Devices) Halt() (err error) { +func (d *Devices) Halt() error { + var err error for _, device := range *d { if derr := device.Halt(); derr != nil { err = multierror.Append(err, derr) diff --git a/doc.go b/doc.go index ada79dd42..acd5e0d58 100644 --- a/doc.go +++ b/doc.go @@ -1,9 +1,11 @@ // Copyright 2014-2018 The Hybrid Group. All rights reserved. /* -Package gobot is the primary entrypoint for Gobot (http://gobot.io), a framework for robotics, physical computing, and the Internet of Things written using the Go programming language . +Package gobot is the primary entrypoint for Gobot (http://gobot.io), a framework for robotics, physical computing, and +the Internet of Things written using the Go programming language . -It provides a simple, yet powerful way to create solutions that incorporate multiple, different hardware devices at the same time. +It provides a simple, yet powerful way to create solutions that incorporate multiple, different hardware devices at the +same time. # Classic Gobot @@ -40,7 +42,8 @@ Here is a "Classic Gobot" program that blinks an LED using an Arduino: # Metal Gobot -You can also use Metal Gobot and pick and choose from the various Gobot packages to control hardware with nothing but pure idiomatic Golang code. For example: +You can also use Metal Gobot and pick and choose from the various Gobot packages to control hardware with nothing but +pure idiomatic Golang code. For example: package main diff --git a/drivers/aio/aio.go b/drivers/aio/aio.go index a8d5b339a..3915ec65b 100644 --- a/drivers/aio/aio.go +++ b/drivers/aio/aio.go @@ -28,5 +28,5 @@ type AnalogReader interface { // AnalogWriter interface represents an Adaptor which has AnalogWrite capabilities type AnalogWriter interface { // gobot.Adaptor - AnalogWrite(pin string, val int) (err error) + AnalogWrite(pin string, val int) error } diff --git a/drivers/aio/analog_actuator_driver.go b/drivers/aio/analog_actuator_driver.go index 41b666bfc..bc6a3eb88 100644 --- a/drivers/aio/analog_actuator_driver.go +++ b/drivers/aio/analog_actuator_driver.go @@ -1,6 +1,7 @@ package aio import ( + "log" "strconv" "gobot.io/x/gobot/v2" @@ -32,7 +33,7 @@ func NewAnalogActuatorDriver(a AnalogWriter, pin string) *AnalogActuatorDriver { connection: a, pin: pin, Commander: gobot.NewCommander(), - scale: func(input float64) (value int) { return int(input) }, + scale: func(input float64) int { return int(input) }, } d.AddCommand("Write", func(params map[string]interface{}) interface{} { @@ -52,10 +53,10 @@ func NewAnalogActuatorDriver(a AnalogWriter, pin string) *AnalogActuatorDriver { } // Start starts driver -func (a *AnalogActuatorDriver) Start() (err error) { return } +func (a *AnalogActuatorDriver) Start() error { return nil } // Halt is for halt -func (a *AnalogActuatorDriver) Halt() (err error) { return } +func (a *AnalogActuatorDriver) Halt() error { return nil } // Name returns the drivers name func (a *AnalogActuatorDriver) Name() string { return a.name } @@ -67,10 +68,17 @@ func (a *AnalogActuatorDriver) SetName(n string) { a.name = n } func (a *AnalogActuatorDriver) Pin() string { return a.pin } // Connection returns the drivers Connection -func (a *AnalogActuatorDriver) Connection() gobot.Connection { return a.connection.(gobot.Connection) } +func (a *AnalogActuatorDriver) Connection() gobot.Connection { + if conn, ok := a.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", a.name) + return nil +} // RawWrite write the given raw value to the actuator -func (a *AnalogActuatorDriver) RawWrite(val int) (err error) { +func (a *AnalogActuatorDriver) RawWrite(val int) error { a.lastRawValue = val return a.connection.AnalogWrite(a.Pin(), val) } @@ -81,19 +89,19 @@ func (a *AnalogActuatorDriver) SetScaler(scaler func(float64) int) { } // Write writes the given value to the actuator -func (a *AnalogActuatorDriver) Write(val float64) (err error) { +func (a *AnalogActuatorDriver) Write(val float64) error { a.lastValue = val rawValue := a.scale(val) return a.RawWrite(rawValue) } // RawValue returns the last written raw value -func (a *AnalogActuatorDriver) RawValue() (val int) { +func (a *AnalogActuatorDriver) RawValue() int { return a.lastRawValue } // Value returns the last written value -func (a *AnalogActuatorDriver) Value() (val float64) { +func (a *AnalogActuatorDriver) Value() float64 { return a.lastValue } @@ -101,7 +109,7 @@ func (a *AnalogActuatorDriver) Value() (val float64) { func AnalogActuatorLinearScaler(fromMin, fromMax float64, toMin, toMax int) func(input float64) (value int) { m := float64(toMax-toMin) / (fromMax - fromMin) n := float64(toMin) - m*fromMin - return func(input float64) (value int) { + return func(input float64) int { if input <= fromMin { return toMin } diff --git a/drivers/aio/analog_sensor_driver.go b/drivers/aio/analog_sensor_driver.go index 81abba4af..7e9059ad3 100644 --- a/drivers/aio/analog_sensor_driver.go +++ b/drivers/aio/analog_sensor_driver.go @@ -1,6 +1,7 @@ package aio import ( + "log" "sync" "time" @@ -44,7 +45,7 @@ func NewAnalogSensorDriver(a AnalogReader, pin string, v ...time.Duration) *Anal Commander: gobot.NewCommander(), interval: 10 * time.Millisecond, halt: make(chan bool), - scale: func(input int) (value float64) { return float64(input) }, + scale: func(input int) float64 { return float64(input) }, mutex: &sync.Mutex{}, } @@ -75,10 +76,10 @@ func NewAnalogSensorDriver(a AnalogReader, pin string, v ...time.Duration) *Anal // Data int - Event is emitted on change and represents the current raw reading from the sensor. // Value float64 - Event is emitted on change and represents the current reading from the sensor. // Error error - Event is emitted on error reading from the sensor. -func (a *AnalogSensorDriver) Start() (err error) { +func (a *AnalogSensorDriver) Start() error { if a.interval == 0 { // cyclic reading deactivated - return + return nil } oldRawValue := 0 oldValue := 0.0 @@ -109,17 +110,17 @@ func (a *AnalogSensorDriver) Start() (err error) { } } }() - return + return nil } // Halt stops polling the analog sensor for new information -func (a *AnalogSensorDriver) Halt() (err error) { +func (a *AnalogSensorDriver) Halt() error { if a.interval == 0 { // cyclic reading deactivated - return + return nil } a.halt <- true - return + return nil } // Name returns the AnalogSensorDrivers name @@ -132,7 +133,14 @@ func (a *AnalogSensorDriver) SetName(n string) { a.name = n } func (a *AnalogSensorDriver) Pin() string { return a.pin } // Connection returns the AnalogSensorDrivers Connection -func (a *AnalogSensorDriver) Connection() gobot.Connection { return a.connection.(gobot.Connection) } +func (a *AnalogSensorDriver) Connection() gobot.Connection { + if conn, ok := a.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", a.name) + return nil +} // Read returns the current reading from the sensor, scaled by the current scaler func (a *AnalogSensorDriver) Read() (float64, error) { diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index 3e4bff255..3f782e3b9 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package aio import ( @@ -8,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -28,9 +30,8 @@ func TestAnalogSensorDriver(t *testing.T) { assert.Equal(t, "42", d.Pin()) assert.Equal(t, 30*time.Second, d.interval) - a.analogReadFunc = func() (val int, err error) { - val = 100 - return + a.analogReadFunc = func() (int, error) { + return 100, nil } ret := d.Command("ReadRaw")(nil).(map[string]interface{}) @@ -44,9 +45,8 @@ func TestAnalogSensorDriver(t *testing.T) { // refresh value on read a = newAioTestAdaptor() d = NewAnalogSensorDriver(a, "3") - a.analogReadFunc = func() (val int, err error) { - val = 150 - return + a.analogReadFunc = func() (int, error) { + return 150, nil } assert.InDelta(t, 0.0, d.Value(), 0.0) val, err := d.Read() @@ -80,7 +80,7 @@ func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange d.SetScaler(AnalogSensorLinearScaler(0, 255, tt.toMin, tt.toMax)) - a.analogReadFunc = func() (val int, err error) { + a.analogReadFunc = func() (int, error) { return tt.input, nil } // act @@ -110,9 +110,8 @@ func TestAnalogSensorDriverStart(t *testing.T) { }) // send data - a.analogReadFunc = func() (val int, err error) { - val = 100 - return + a.analogReadFunc = func() (int, error) { + return 100, nil } require.NoError(t, d.Start()) @@ -130,9 +129,8 @@ func TestAnalogSensorDriverStart(t *testing.T) { }) // send error - a.analogReadFunc = func() (val int, err error) { - err = errors.New("read error") - return + a.analogReadFunc = func() (int, error) { + return 0, errors.New("read error") } select { @@ -150,9 +148,8 @@ func TestAnalogSensorDriverStart(t *testing.T) { sem <- true }) - a.analogReadFunc = func() (val int, err error) { - val = 200 - return + a.analogReadFunc = func() (int, error) { + return 200, nil } d.halt <- true diff --git a/drivers/aio/grove_drivers.go b/drivers/aio/grove_drivers.go index df6c776dc..8d4783420 100644 --- a/drivers/aio/grove_drivers.go +++ b/drivers/aio/grove_drivers.go @@ -63,7 +63,11 @@ type GrovePiezoVibrationSensorDriver struct { // Adds the following API Commands: // // "Read" - See AnalogSensor.Read -func NewGrovePiezoVibrationSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GrovePiezoVibrationSensorDriver { +func NewGrovePiezoVibrationSensorDriver( + a AnalogReader, + pin string, + v ...time.Duration, +) *GrovePiezoVibrationSensorDriver { sensor := &GrovePiezoVibrationSensorDriver{ AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), } @@ -71,7 +75,7 @@ func NewGrovePiezoVibrationSensorDriver(a AnalogReader, pin string, v ...time.Du sensor.AddEvent(Vibration) if err := sensor.On(sensor.Event(Data), func(data interface{}) { - if data.(int) > 1000 { + if data.(int) > 1000 { //nolint:forcetypeassert // no error return value, so there is no better way sensor.Publish(sensor.Event(Vibration), data) } }); err != nil { diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go index df88e2cb7..a58502fd1 100644 --- a/drivers/aio/grove_drivers_test.go +++ b/drivers/aio/grove_drivers_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package aio import ( @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -85,9 +87,8 @@ func TestDriverPublishesError(t *testing.T) { for _, driver := range drivers { sem := make(chan struct{}, 1) // send error - testAdaptor.analogReadFunc = func() (val int, err error) { - err = errors.New("read error") - return + testAdaptor.analogReadFunc = func() (int, error) { + return 0, errors.New("read error") } require.NoError(t, driver.Start()) diff --git a/drivers/aio/grove_temperature_sensor_driver.go b/drivers/aio/grove_temperature_sensor_driver.go index 78304a110..f12e5132d 100644 --- a/drivers/aio/grove_temperature_sensor_driver.go +++ b/drivers/aio/grove_temperature_sensor_driver.go @@ -39,6 +39,6 @@ func NewGroveTemperatureSensorDriver(a AnalogReader, pin string, v ...time.Durat } // Temperature returns the last read temperature from the sensor. -func (t *TemperatureSensorDriver) Temperature() (val float64) { +func (t *TemperatureSensorDriver) Temperature() float64 { return t.Value() } diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index a7b303e58..ebe27a278 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package aio import ( @@ -8,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -41,9 +43,8 @@ func TestGroveTemperatureSensorDriverScaling(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { // arrange - a.analogReadFunc = func() (val int, err error) { - val = tt.input - return + a.analogReadFunc = func() (int, error) { + return tt.input, nil } // act got, err := d.Read() @@ -59,9 +60,8 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { a := newAioTestAdaptor() d := NewGroveTemperatureSensorDriver(a, "1") - a.analogReadFunc = func() (val int, err error) { - val = 585 - return + a.analogReadFunc = func() (int, error) { + return 585, nil } _ = d.Once(d.Event(Value), func(data interface{}) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) diff --git a/drivers/aio/helpers_test.go b/drivers/aio/helpers_test.go index 38ab5c2db..af7013332 100644 --- a/drivers/aio/helpers_test.go +++ b/drivers/aio/helpers_test.go @@ -7,7 +7,7 @@ type aioTestAdaptor struct { port string mtx sync.Mutex analogReadFunc func() (val int, err error) - analogWriteFunc func(val int) (err error) + analogWriteFunc func(val int) error written []int } @@ -15,10 +15,10 @@ func newAioTestAdaptor() *aioTestAdaptor { t := aioTestAdaptor{ name: "aio_test_adaptor", port: "/dev/null", - analogReadFunc: func() (val int, err error) { + analogReadFunc: func() (int, error) { return 99, nil }, - analogWriteFunc: func(val int) (err error) { + analogWriteFunc: func(val int) error { return nil }, } @@ -27,22 +27,22 @@ func newAioTestAdaptor() *aioTestAdaptor { } // AnalogRead capabilities (interface AnalogReader) -func (t *aioTestAdaptor) AnalogRead(pin string) (val int, err error) { +func (t *aioTestAdaptor) AnalogRead(pin string) (int, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.analogReadFunc() } // AnalogWrite capabilities (interface AnalogWriter) -func (t *aioTestAdaptor) AnalogWrite(pin string, val int) (err error) { +func (t *aioTestAdaptor) AnalogWrite(pin string, val int) error { t.mtx.Lock() defer t.mtx.Unlock() t.written = append(t.written, val) return t.analogWriteFunc(val) } -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 (t *aioTestAdaptor) Connect() error { return nil } +func (t *aioTestAdaptor) Finalize() error { return nil } +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 } diff --git a/drivers/aio/temperature_sensor_driver.go b/drivers/aio/temperature_sensor_driver.go index 55c5484c0..15953a04e 100644 --- a/drivers/aio/temperature_sensor_driver.go +++ b/drivers/aio/temperature_sensor_driver.go @@ -68,9 +68,14 @@ func (t *TemperatureSensorDriver) SetLinearScaler(fromMin, fromMax int, toMin, t // If the thermistor is connected to ground, the reverse flag must be set to true. // This means the voltage decreases when temperature gets higher. // Currently no negative values for voltage are supported. -func TemperatureSensorNtcScaler(vRef uint, rOhm uint, reverse bool, ntc TemperatureSensorNtcConf) func(input int) (value float64) { +func TemperatureSensorNtcScaler( + vRef uint, + rOhm uint, + reverse bool, + ntc TemperatureSensorNtcConf, +) func(input int) (value float64) { ntc.initialize() - return (func(input int) (value float64) { + return (func(input int) float64 { if input < 0 { input = 0 } diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index 21c16711b..f0977562a 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package aio import ( @@ -42,9 +43,8 @@ func TestTemperatureSensorDriverNtcScaling(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { // arrange - a.analogReadFunc = func() (val int, err error) { - val = tt.input - return + a.analogReadFunc = func() (int, error) { + return tt.input, nil } // act got, err := d.Read() @@ -77,9 +77,8 @@ func TestTemperatureSensorDriverLinearScaling(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { // arrange - a.analogReadFunc = func() (val int, err error) { - val = tt.input - return + a.analogReadFunc = func() (int, error) { + return tt.input, nil } // act got, err := d.Read() @@ -97,9 +96,8 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.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 - a.analogReadFunc = func() (val int, err error) { - val = 585 - return + a.analogReadFunc = func() (int, error) { + return 585, nil } _ = d.Once(d.Event(Value), func(data interface{}) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) @@ -122,9 +120,8 @@ func TestTempSensorPublishesError(t *testing.T) { d := NewTemperatureSensorDriver(a, "1") // send error - a.analogReadFunc = func() (val int, err error) { - err = errors.New("read error") - return + a.analogReadFunc = func() (int, error) { + return 0, errors.New("read error") } require.NoError(t, d.Start()) @@ -195,11 +192,15 @@ func TestTempDriver_initialize(t *testing.T) { }, "T1_low": { input: TemperatureSensorNtcConf{TC0: 25, R0: 2500.0, TC1: -13, R1: 10000}, - want: TemperatureSensorNtcConf{TC0: 25, R0: 2500.0, TC1: -13, R1: 10000, B: 2829.6355560320544, t0: 298.15, r: 9.490644159087891}, + want: TemperatureSensorNtcConf{ + TC0: 25, R0: 2500.0, TC1: -13, R1: 10000, B: 2829.6355560320544, t0: 298.15, r: 9.490644159087891, + }, }, "T1_high": { input: TemperatureSensorNtcConf{TC0: 25, R0: 2500.0, TC1: 100, R1: 371}, - want: TemperatureSensorNtcConf{TC0: 25, R0: 2500.0, TC1: 100, R1: 371, B: 2830.087381913779, t0: 298.15, r: 9.49215959052081}, + want: TemperatureSensorNtcConf{ + TC0: 25, R0: 2500.0, TC1: 100, R1: 371, B: 2830.087381913779, t0: 298.15, r: 9.49215959052081, + }, }, } for name, tt := range tests { diff --git a/drivers/common/mfrc522/mfrc522_pcd_register.go b/drivers/common/mfrc522/mfrc522_pcd_register.go index 042e145aa..ea5cec8e6 100644 --- a/drivers/common/mfrc522/mfrc522_pcd_register.go +++ b/drivers/common/mfrc522/mfrc522_pcd_register.go @@ -1,3 +1,4 @@ +//nolint:lll // ok here package mfrc522 // Page 0: Command and status diff --git a/drivers/common/mfrc522/mfrc522_pcd_test.go b/drivers/common/mfrc522/mfrc522_pcd_test.go index 435a2ee81..19c14bf16 100644 --- a/drivers/common/mfrc522/mfrc522_pcd_test.go +++ b/drivers/common/mfrc522/mfrc522_pcd_test.go @@ -56,7 +56,9 @@ func TestNewMFRC522Common(t *testing.T) { func TestInitialize(t *testing.T) { // arrange wantSoftReset := []byte{0x01, 0x0F, 0x01} - wantInit := []byte{0x12, 0x00, 0x13, 0x00, 0x24, 0x26, 0x2A, 0x8F, 0x2B, 0xFF, 0x2D, 0xE8, 0x2C, 0x03, 0x15, 0x40, 0x11, 0x29} + wantInit := []byte{ + 0x12, 0x00, 0x13, 0x00, 0x24, 0x26, 0x2A, 0x8F, 0x2B, 0xFF, 0x2D, 0xE8, 0x2C, 0x03, 0x15, 0x40, 0x11, 0x29, + } wantAntennaOn := []byte{0x14, 0x14, 0x03} wantGain := []byte{0x26, 0x50} c := &busConnMock{} diff --git a/drivers/common/mfrc522/mfrc522_picc.go b/drivers/common/mfrc522/mfrc522_picc.go index 32d2bae2f..1776daa25 100644 --- a/drivers/common/mfrc522/mfrc522_picc.go +++ b/drivers/common/mfrc522/mfrc522_picc.go @@ -1,3 +1,4 @@ +//nolint:lll // ok here package mfrc522 import ( @@ -117,14 +118,14 @@ func (d *MFRC522Common) ReadText() (string, error) { content = append(content, blockData...) } if piccDebug { - fmt.Println("content:", string(content[:]), content) + fmt.Println("content:", string(content), content) } if err := d.piccHalt(); err != nil { return "", err } - return string(content[:]), d.stopCrypto1() + return string(content), d.stopCrypto1() } // WriteText writes the given string to the card. All old values will be overwritten. diff --git a/drivers/gpio/aip1640_driver_test.go b/drivers/gpio/aip1640_driver_test.go index b4870e18c..a820dd00e 100644 --- a/drivers/gpio/aip1640_driver_test.go +++ b/drivers/gpio/aip1640_driver_test.go @@ -6,15 +6,16 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) var _ gobot.Driver = (*AIP1640Driver)(nil) // --------- HELPERS -func initTestAIP1640Driver() (driver *AIP1640Driver) { - driver, _ = initTestAIP1640DriverWithStubbedAdaptor() - return +func initTestAIP1640Driver() *AIP1640Driver { + d, _ := initTestAIP1640DriverWithStubbedAdaptor() + return d } func initTestAIP1640DriverWithStubbedAdaptor() (*AIP1640Driver, *gpioTestAdaptor) { diff --git a/drivers/gpio/button_driver.go b/drivers/gpio/button_driver.go index 72c62d320..509156983 100644 --- a/drivers/gpio/button_driver.go +++ b/drivers/gpio/button_driver.go @@ -24,7 +24,8 @@ type ButtonDriver struct { // // time.Duration: Interval at which the ButtonDriver is polled for new information func NewButtonDriver(a DigitalReader, pin string, v ...time.Duration) *ButtonDriver { - b := &ButtonDriver{ + //nolint:forcetypeassert // no error return value, so there is no better way + d := &ButtonDriver{ Driver: NewDriver(a.(gobot.Connection), "Button"), Eventer: gobot.NewEventer(), pin: pin, @@ -33,39 +34,39 @@ func NewButtonDriver(a DigitalReader, pin string, v ...time.Duration) *ButtonDri interval: 10 * time.Millisecond, halt: make(chan bool), } - b.afterStart = b.initialize - b.beforeHalt = b.shutdown + d.afterStart = d.initialize + d.beforeHalt = d.shutdown if len(v) > 0 { - b.interval = v[0] + d.interval = v[0] } - b.AddEvent(ButtonPush) - b.AddEvent(ButtonRelease) - b.AddEvent(Error) + d.AddEvent(ButtonPush) + d.AddEvent(ButtonRelease) + d.AddEvent(Error) - return b + return d } // Pin returns the ButtonDrivers pin -func (b *ButtonDriver) Pin() string { return b.pin } +func (d *ButtonDriver) Pin() string { return d.pin } // Active gets the current state -func (b *ButtonDriver) Active() bool { +func (d *ButtonDriver) Active() bool { // ensure that read and write can not interfere - b.mutex.Lock() - defer b.mutex.Unlock() + d.mutex.Lock() + defer d.mutex.Unlock() - return b.active + return d.active } // SetDefaultState for the next start. -func (b *ButtonDriver) SetDefaultState(s int) { +func (d *ButtonDriver) SetDefaultState(s int) { // ensure that read and write can not interfere - b.mutex.Lock() - defer b.mutex.Unlock() + d.mutex.Lock() + defer d.mutex.Unlock() - b.defaultState = s + d.defaultState = s } // initialize the ButtonDriver and polls the state of the button at the given interval. @@ -75,20 +76,20 @@ func (b *ButtonDriver) SetDefaultState(s int) { // Push int - On button push // Release int - On button release // Error error - On button error -func (b *ButtonDriver) initialize() error { - state := b.defaultState +func (d *ButtonDriver) initialize() error { + state := d.defaultState go func() { for { - newValue, err := b.connection.(DigitalReader).DigitalRead(b.Pin()) + newValue, err := d.connection.(DigitalReader).DigitalRead(d.Pin()) if err != nil { - b.Publish(Error, err) + d.Publish(Error, err) } else if newValue != state && newValue != -1 { state = newValue - b.update(newValue) + d.update(newValue) } select { - case <-time.After(b.interval): - case <-b.halt: + case <-time.After(d.interval): + case <-d.halt: return } } @@ -96,21 +97,21 @@ func (b *ButtonDriver) initialize() error { return nil } -func (b *ButtonDriver) shutdown() error { - b.halt <- true +func (d *ButtonDriver) shutdown() error { + d.halt <- true return nil } -func (b *ButtonDriver) update(newValue int) { +func (d *ButtonDriver) update(newValue int) { // ensure that read and write can not interfere - b.mutex.Lock() - defer b.mutex.Unlock() + d.mutex.Lock() + defer d.mutex.Unlock() - if newValue != b.defaultState { - b.active = true - b.Publish(ButtonPush, newValue) + if newValue != d.defaultState { + d.active = true + d.Publish(ButtonPush, newValue) } else { - b.active = false - b.Publish(ButtonRelease, newValue) + d.active = false + d.Publish(ButtonRelease, newValue) } } diff --git a/drivers/gpio/button_driver_test.go b/drivers/gpio/button_driver_test.go index a71dcd371..9503b48e2 100644 --- a/drivers/gpio/button_driver_test.go +++ b/drivers/gpio/button_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/gpio/buzzer_driver.go b/drivers/gpio/buzzer_driver.go index 5d1073d46..333985678 100644 --- a/drivers/gpio/buzzer_driver.go +++ b/drivers/gpio/buzzer_driver.go @@ -1,6 +1,7 @@ package gpio import ( + "log" "time" "gobot.io/x/gobot/v2" @@ -152,76 +153,79 @@ func NewBuzzerDriver(a DigitalWriter, pin string) *BuzzerDriver { } // Start implements the Driver interface -func (l *BuzzerDriver) Start() (err error) { return } +func (d *BuzzerDriver) Start() error { return nil } // Halt implements the Driver interface -func (l *BuzzerDriver) Halt() (err error) { return } +func (d *BuzzerDriver) Halt() error { return nil } // Name returns the BuzzerDrivers name -func (l *BuzzerDriver) Name() string { return l.name } +func (d *BuzzerDriver) Name() string { return d.name } // SetName sets the BuzzerDrivers name -func (l *BuzzerDriver) SetName(n string) { l.name = n } +func (d *BuzzerDriver) SetName(n string) { d.name = n } // Pin returns the BuzzerDrivers name -func (l *BuzzerDriver) Pin() string { return l.pin } +func (d *BuzzerDriver) Pin() string { return d.pin } // Connection returns the BuzzerDrivers Connection -func (l *BuzzerDriver) Connection() gobot.Connection { - return l.connection.(gobot.Connection) +func (d *BuzzerDriver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil } // State return true if the buzzer is On and false if the led is Off -func (l *BuzzerDriver) State() bool { - return l.high +func (d *BuzzerDriver) State() bool { + return d.high } // On sets the buzzer to a high state. -func (l *BuzzerDriver) On() (err error) { - if err = l.connection.DigitalWrite(l.Pin(), 1); err != nil { - return +func (d *BuzzerDriver) On() error { + if err := d.connection.DigitalWrite(d.Pin(), 1); err != nil { + return err } - l.high = true - return + d.high = true + return nil } // Off sets the buzzer to a low state. -func (l *BuzzerDriver) Off() (err error) { - if err = l.connection.DigitalWrite(l.Pin(), 0); err != nil { - return +func (d *BuzzerDriver) Off() error { + if err := d.connection.DigitalWrite(d.Pin(), 0); err != nil { + return err } - l.high = false - return + d.high = false + return nil } // Toggle sets the buzzer to the opposite of it's current state -func (l *BuzzerDriver) Toggle() (err error) { - if l.State() { - err = l.Off() - } else { - err = l.On() +func (d *BuzzerDriver) Toggle() error { + if d.State() { + return d.Off() } - return + return d.On() } // Tone is to make a sound with the given frequency -func (l *BuzzerDriver) Tone(hz, duration float64) (err error) { +func (d *BuzzerDriver) Tone(hz, duration float64) error { // calculation based off https://www.arduino.cc/en/Tutorial/Melody tone := (1.0 / (2.0 * hz)) * 1000000.0 - tempo := ((60 / l.BPM) * (duration * 1000)) + tempo := ((60 / d.BPM) * (duration * 1000)) for i := 0.0; i < tempo*1000; i += tone * 2.0 { - if err = l.On(); err != nil { - return + if err := d.On(); err != nil { + return err } time.Sleep(time.Duration(tone) * time.Microsecond) - if err = l.Off(); err != nil { - return + if err := d.Off(); err != nil { + return err } time.Sleep(time.Duration(tone) * time.Microsecond) } - return + return nil } diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index 7f3d34040..f3626a185 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -54,7 +55,7 @@ func TestBuzzerDriverTone(t *testing.T) { func TestBuzzerDriverOnError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } @@ -64,7 +65,7 @@ func TestBuzzerDriverOnError(t *testing.T) { func TestBuzzerDriverOffError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } @@ -74,7 +75,7 @@ func TestBuzzerDriverOffError(t *testing.T) { func TestBuzzerDriverToneError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } diff --git a/drivers/gpio/direct_pin_driver.go b/drivers/gpio/direct_pin_driver.go index ebec0ca2b..65afdcf26 100644 --- a/drivers/gpio/direct_pin_driver.go +++ b/drivers/gpio/direct_pin_driver.go @@ -63,61 +63,61 @@ func (d *DirectPinDriver) Pin() string { return d.pin } func (d *DirectPinDriver) Connection() gobot.Connection { return d.connection } // Start implements the Driver interface -func (d *DirectPinDriver) Start() (err error) { return } +func (d *DirectPinDriver) Start() error { return nil } // Halt implements the Driver interface -func (d *DirectPinDriver) Halt() (err error) { return } +func (d *DirectPinDriver) Halt() error { return nil } // Off turn off pin -func (d *DirectPinDriver) Off() (err error) { +func (d *DirectPinDriver) Off() error { if writer, ok := d.Connection().(DigitalWriter); ok { return writer.DigitalWrite(d.Pin(), byte(0)) } - err = ErrDigitalWriteUnsupported - return + + return ErrDigitalWriteUnsupported } // On turn on pin -func (d *DirectPinDriver) On() (err error) { +func (d *DirectPinDriver) On() error { if writer, ok := d.Connection().(DigitalWriter); ok { return writer.DigitalWrite(d.Pin(), byte(1)) } - err = ErrDigitalWriteUnsupported - return + + return ErrDigitalWriteUnsupported } // DigitalRead returns the current digital state of the pin -func (d *DirectPinDriver) DigitalRead() (val int, err error) { +func (d *DirectPinDriver) DigitalRead() (int, error) { if reader, ok := d.Connection().(DigitalReader); ok { return reader.DigitalRead(d.Pin()) } - err = ErrDigitalReadUnsupported - return + + return 0, ErrDigitalReadUnsupported } // DigitalWrite writes to the pin. Acceptable values are 1 or 0 -func (d *DirectPinDriver) DigitalWrite(level byte) (err error) { +func (d *DirectPinDriver) DigitalWrite(level byte) error { if writer, ok := d.Connection().(DigitalWriter); ok { return writer.DigitalWrite(d.Pin(), level) } - err = ErrDigitalWriteUnsupported - return + + return ErrDigitalWriteUnsupported } // PwmWrite writes the 0-254 value to the specified pin -func (d *DirectPinDriver) PwmWrite(level byte) (err error) { +func (d *DirectPinDriver) PwmWrite(level byte) error { if writer, ok := d.Connection().(PwmWriter); ok { return writer.PwmWrite(d.Pin(), level) } - err = ErrPwmWriteUnsupported - return + + return ErrPwmWriteUnsupported } // ServoWrite writes value to the specified pin -func (d *DirectPinDriver) ServoWrite(level byte) (err error) { +func (d *DirectPinDriver) ServoWrite(level byte) error { if writer, ok := d.Connection().(ServoWriter); ok { return writer.ServoWrite(d.Pin(), level) } - err = ErrServoWriteUnsupported - return + + return ErrServoWriteUnsupported } diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index f9eaa96e6..1dccd9224 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package gpio import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -14,17 +16,16 @@ var _ gobot.Driver = (*DirectPinDriver)(nil) func initTestDirectPinDriver() *DirectPinDriver { a := newGpioTestAdaptor() - a.digitalReadFunc = func(string) (val int, err error) { - val = 1 - return + a.digitalReadFunc = func(string) (int, error) { + return 1, nil } - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } - a.pwmWriteFunc = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) error { return errors.New("write error") } - a.servoWriteFunc = func(string, byte) (err error) { + a.servoWriteFunc = func(string, byte) error { return errors.New("write error") } return NewDirectPinDriver(a, "1") diff --git a/drivers/gpio/easy_driver.go b/drivers/gpio/easy_driver.go index c7c01a8ed..4bf22cf0e 100644 --- a/drivers/gpio/easy_driver.go +++ b/drivers/gpio/easy_driver.go @@ -91,6 +91,7 @@ func (d *EasyDriver) SetDirection(direction string) error { writeVal = 1 // high is backward } + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(d.dirPin, writeVal); err != nil { return err } @@ -111,6 +112,7 @@ func (d *EasyDriver) Enable() error { } // enPin is active low + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(d.enPin, 0); err != nil { return err } @@ -128,6 +130,7 @@ func (d *EasyDriver) Disable() error { _ = d.stopIfRunning() // drop step errors // enPin is active low + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(d.enPin, 1); err != nil { return err } @@ -148,6 +151,7 @@ func (d *EasyDriver) Wake() error { } // sleepPin is active low + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(d.sleepPin, 1); err != nil { return err } @@ -171,11 +175,13 @@ func (d *EasyDriver) onePinStepping() error { defer d.valueMutex.Unlock() // a valid steps occurs for a low to high transition + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(d.stepPin, 0); err != nil { return err } time.Sleep(d.getDelayPerStep()) + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(d.stepPin, 1); err != nil { return err } @@ -198,6 +204,7 @@ func (d *EasyDriver) sleepWithSleepPin() error { _ = d.stopIfRunning() // drop step errors // sleepPin is active low + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(d.sleepPin, 0); err != nil { return err } diff --git a/drivers/gpio/gpio_driver.go b/drivers/gpio/gpio_driver.go index 896897dcc..52d11a919 100644 --- a/drivers/gpio/gpio_driver.go +++ b/drivers/gpio/gpio_driver.go @@ -2,6 +2,7 @@ package gpio import ( "errors" + "log" "sync" "gobot.io/x/gobot/v2" @@ -47,17 +48,17 @@ const ( // PwmWriter interface represents an Adaptor which has Pwm capabilities type PwmWriter interface { - PwmWrite(pin string, val byte) (err error) + PwmWrite(pin string, val byte) error } // ServoWriter interface represents an Adaptor which has Servo capabilities type ServoWriter interface { - ServoWrite(pin string, val byte) (err error) + ServoWrite(pin string, val byte) error } // DigitalWriter interface represents an Adaptor which has DigitalWrite capabilities type DigitalWriter interface { - DigitalWrite(pin string, val byte) (err error) + DigitalWrite(pin string, val byte) error } // DigitalReader interface represents an Adaptor which has DigitalRead capabilities @@ -101,7 +102,12 @@ func (d *Driver) SetName(name string) { // Connection returns the connection of the gpio device. func (d *Driver) Connection() gobot.Connection { - return d.connection.(gobot.Connection) + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil } // Start initializes the gpio device. diff --git a/drivers/gpio/gpio_driver_test.go b/drivers/gpio/gpio_driver_test.go index 0ea6021ca..7511a3caf 100644 --- a/drivers/gpio/gpio_driver_test.go +++ b/drivers/gpio/gpio_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/gpio/grove_drivers_test.go b/drivers/gpio/grove_drivers_test.go index e614432f8..1606808e2 100644 --- a/drivers/gpio/grove_drivers_test.go +++ b/drivers/gpio/grove_drivers_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package gpio import ( @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -86,9 +88,8 @@ func TestDriverPublishesError(t *testing.T) { for _, driver := range drivers { sem := make(chan struct{}, 1) // send error - returnErr := func(string) (val int, err error) { - err = errors.New("read error") - return + returnErr := func(string) (int, error) { + return 0, errors.New("read error") } testAdaptor.digitalReadFunc = returnErr diff --git a/drivers/gpio/hcsr04_driver_test.go b/drivers/gpio/hcsr04_driver_test.go index da65fc901..0d49b5fe7 100644 --- a/drivers/gpio/hcsr04_driver_test.go +++ b/drivers/gpio/hcsr04_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2/system" ) diff --git a/drivers/gpio/hd44780_driver.go b/drivers/gpio/hd44780_driver.go index 1f23d9101..0c24ca707 100644 --- a/drivers/gpio/hd44780_driver.go +++ b/drivers/gpio/hd44780_driver.go @@ -95,7 +95,15 @@ type HD44780Driver struct { // pinRS: register select pin // pinEN: clock enable pin // pinDataBits: databit pins -func NewHD44780Driver(a gobot.Connection, cols int, rows int, busMode HD44780BusMode, pinRS string, pinEN string, pinDataBits HD44780DataPin) *HD44780Driver { +func NewHD44780Driver( + a gobot.Connection, + cols int, + rows int, + busMode HD44780BusMode, + pinRS string, + pinEN string, + pinDataBits HD44780DataPin, +) *HD44780Driver { h := &HD44780Driver{ name: "HD44780Driver", cols: cols, @@ -157,7 +165,7 @@ func (h *HD44780Driver) Connection() gobot.Connection { // Start initializes the HD44780 LCD controller // refer to page 45/46 of Hitachi HD44780 datasheet -func (h *HD44780Driver) Start() (err error) { +func (h *HD44780Driver) Start() error { h.mutex.Lock() defer h.mutex.Unlock() @@ -252,7 +260,7 @@ func (h *HD44780Driver) Halt() error { } // Write output text to the display -func (h *HD44780Driver) Write(message string) (err error) { +func (h *HD44780Driver) Write(message string) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -279,7 +287,7 @@ func (h *HD44780Driver) Write(message string) (err error) { } // Clear clear the display -func (h *HD44780Driver) Clear() (err error) { +func (h *HD44780Driver) Clear() error { h.mutex.Lock() defer h.mutex.Unlock() @@ -287,7 +295,7 @@ func (h *HD44780Driver) Clear() (err error) { } // Home return cursor to home -func (h *HD44780Driver) Home() (err error) { +func (h *HD44780Driver) Home() error { h.mutex.Lock() defer h.mutex.Unlock() @@ -300,7 +308,7 @@ func (h *HD44780Driver) Home() (err error) { } // SetCursor move the cursor to the specified position -func (h *HD44780Driver) SetCursor(col int, row int) (err error) { +func (h *HD44780Driver) SetCursor(col int, row int) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -308,7 +316,7 @@ func (h *HD44780Driver) SetCursor(col int, row int) (err error) { } // Display turn the display on and off -func (h *HD44780Driver) Display(on bool) (err error) { +func (h *HD44780Driver) Display(on bool) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -322,7 +330,7 @@ func (h *HD44780Driver) Display(on bool) (err error) { } // Cursor turn the cursor on and off -func (h *HD44780Driver) Cursor(on bool) (err error) { +func (h *HD44780Driver) Cursor(on bool) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -336,7 +344,7 @@ func (h *HD44780Driver) Cursor(on bool) (err error) { } // Blink turn the blink on and off -func (h *HD44780Driver) Blink(on bool) (err error) { +func (h *HD44780Driver) Blink(on bool) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -350,7 +358,7 @@ func (h *HD44780Driver) Blink(on bool) (err error) { } // ScrollLeft scroll text left -func (h *HD44780Driver) ScrollLeft() (err error) { +func (h *HD44780Driver) ScrollLeft() error { h.mutex.Lock() defer h.mutex.Unlock() @@ -358,7 +366,7 @@ func (h *HD44780Driver) ScrollLeft() (err error) { } // ScrollRight scroll text right -func (h *HD44780Driver) ScrollRight() (err error) { +func (h *HD44780Driver) ScrollRight() error { h.mutex.Lock() defer h.mutex.Unlock() @@ -366,7 +374,7 @@ func (h *HD44780Driver) ScrollRight() (err error) { } // LeftToRight display text from left to right -func (h *HD44780Driver) LeftToRight() (err error) { +func (h *HD44780Driver) LeftToRight() error { h.mutex.Lock() defer h.mutex.Unlock() @@ -375,7 +383,7 @@ func (h *HD44780Driver) LeftToRight() (err error) { } // RightToLeft display text from right to left -func (h *HD44780Driver) RightToLeft() (err error) { +func (h *HD44780Driver) RightToLeft() error { h.mutex.Lock() defer h.mutex.Unlock() @@ -384,7 +392,7 @@ func (h *HD44780Driver) RightToLeft() (err error) { } // SendCommand send control command -func (h *HD44780Driver) SendCommand(data int) (err error) { +func (h *HD44780Driver) SendCommand(data int) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -392,7 +400,7 @@ func (h *HD44780Driver) SendCommand(data int) (err error) { } // WriteChar output a character to the display -func (h *HD44780Driver) WriteChar(data int) (err error) { +func (h *HD44780Driver) WriteChar(data int) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -400,7 +408,7 @@ func (h *HD44780Driver) WriteChar(data int) (err error) { } // CreateChar create custom character -func (h *HD44780Driver) CreateChar(pos int, charMap [8]byte) (err error) { +func (h *HD44780Driver) CreateChar(pos int, charMap [8]byte) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -421,7 +429,7 @@ func (h *HD44780Driver) CreateChar(pos int, charMap [8]byte) (err error) { return nil } -func (h *HD44780Driver) sendCommand(data int) (err error) { +func (h *HD44780Driver) sendCommand(data int) error { if err := h.activateWriteMode(); err != nil { return err } @@ -437,7 +445,7 @@ func (h *HD44780Driver) sendCommand(data int) (err error) { return h.writeDataPins(data) } -func (h *HD44780Driver) writeChar(data int) (err error) { +func (h *HD44780Driver) writeChar(data int) error { if err := h.activateWriteMode(); err != nil { return err } @@ -454,7 +462,7 @@ func (h *HD44780Driver) writeChar(data int) (err error) { return h.writeDataPins(data) } -func (h *HD44780Driver) clear() (err error) { +func (h *HD44780Driver) clear() error { if err := h.sendCommand(HD44780_CLEARDISPLAY); err != nil { return err } @@ -466,7 +474,7 @@ func (h *HD44780Driver) clear() (err error) { return nil } -func (h *HD44780Driver) setCursor(col int, row int) (err error) { +func (h *HD44780Driver) setCursor(col int, row int) error { if col < 0 || row < 0 || col >= h.cols || row >= h.rows { return fmt.Errorf("Invalid position value (%d, %d), range (%d, %d)", col, row, h.cols-1, h.rows-1) } @@ -474,7 +482,7 @@ func (h *HD44780Driver) setCursor(col int, row int) (err error) { return h.sendCommand(HD44780_SETDDRAMADDR | col + h.rowOffsets[row]) } -func (h *HD44780Driver) writeDataPins(data int) (err error) { +func (h *HD44780Driver) writeDataPins(data int) error { for i, pin := range h.pinDataBits { if ((data >> i) & 0x01) == 0x01 { if err := pin.On(); err != nil { @@ -490,7 +498,7 @@ func (h *HD44780Driver) writeDataPins(data int) (err error) { } // fallingEdge creates falling edge to trigger data transmission -func (h *HD44780Driver) fallingEdge() (err error) { +func (h *HD44780Driver) fallingEdge() error { if err := h.pinEN.On(); err != nil { return err } @@ -505,9 +513,9 @@ func (h *HD44780Driver) fallingEdge() (err error) { return nil } -func (h *HD44780Driver) activateWriteMode() (err error) { +func (h *HD44780Driver) activateWriteMode() error { if h.pinRW == nil { - return + return nil } return h.pinRW.Off() } diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index a69f9f775..a43778118 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -127,14 +127,14 @@ func TestHD44780DriverWriteError(t *testing.T) { var a *gpioTestAdaptor d, a = initTestHD44780Driver4BitModeWithStubbedAdaptor() - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } _ = d.Start() require.ErrorContains(t, d.Write("hello gobot"), "write error") d, a = initTestHD44780Driver8BitModeWithStubbedAdaptor() - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } _ = d.Start() diff --git a/drivers/gpio/helpers_test.go b/drivers/gpio/helpers_test.go index a12fa3983..845389dec 100644 --- a/drivers/gpio/helpers_test.go +++ b/drivers/gpio/helpers_test.go @@ -9,13 +9,13 @@ import ( type gpioTestBareAdaptor struct{} -func (t *gpioTestBareAdaptor) Connect() (err error) { return } -func (t *gpioTestBareAdaptor) Finalize() (err error) { return } -func (t *gpioTestBareAdaptor) Name() string { return "" } -func (t *gpioTestBareAdaptor) SetName(n string) {} +func (t *gpioTestBareAdaptor) Connect() error { return nil } +func (t *gpioTestBareAdaptor) Finalize() error { return nil } +func (t *gpioTestBareAdaptor) Name() string { return "" } +func (t *gpioTestBareAdaptor) SetName(n string) {} type digitalPinMock struct { - writeFunc func(val int) (err error) + writeFunc func(val int) error } type gpioTestWritten struct { @@ -31,9 +31,9 @@ type gpioTestAdaptor struct { simulateWriteError bool mtx sync.Mutex digitalReadFunc func(ping string) (val int, err error) - digitalWriteFunc func(pin string, val byte) (err error) - pwmWriteFunc func(pin string, val byte) (err error) - servoWriteFunc func(pin string, val byte) (err error) + digitalWriteFunc func(pin string, val byte) error + pwmWriteFunc func(pin string, val byte) error + servoWriteFunc func(pin string, val byte) error } func newGpioTestAdaptor() *gpioTestAdaptor { @@ -41,16 +41,16 @@ func newGpioTestAdaptor() *gpioTestAdaptor { name: "gpio_test_adaptor", pinMap: make(map[string]gobot.DigitalPinner), port: "/dev/null", - digitalWriteFunc: func(pin string, val byte) (err error) { + digitalWriteFunc: func(pin string, val byte) error { return nil }, - servoWriteFunc: func(pin string, val byte) (err error) { + servoWriteFunc: func(pin string, val byte) error { return nil }, - pwmWriteFunc: func(pin string, val byte) (err error) { + pwmWriteFunc: func(pin string, val byte) error { return nil }, - digitalReadFunc: func(pin string) (val int, err error) { + digitalReadFunc: func(pin string) (int, error) { return 1, nil }, } @@ -59,14 +59,14 @@ func newGpioTestAdaptor() *gpioTestAdaptor { } // DigitalRead capabilities (interface DigitalReader) -func (t *gpioTestAdaptor) DigitalRead(pin string) (val int, err error) { +func (t *gpioTestAdaptor) DigitalRead(pin string) (int, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.digitalReadFunc(pin) } // DigitalWrite capabilities (interface DigitalWriter) -func (t *gpioTestAdaptor) DigitalWrite(pin string, val byte) (err error) { +func (t *gpioTestAdaptor) DigitalWrite(pin string, val byte) error { t.mtx.Lock() defer t.mtx.Unlock() if t.simulateWriteError { @@ -78,24 +78,24 @@ func (t *gpioTestAdaptor) DigitalWrite(pin string, val byte) (err error) { } // PwmWrite capabilities (interface PwmWriter) -func (t *gpioTestAdaptor) PwmWrite(pin string, val byte) (err error) { +func (t *gpioTestAdaptor) PwmWrite(pin string, val byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.pwmWriteFunc(pin, val) } // ServoWrite capabilities (interface ServoWriter) -func (t *gpioTestAdaptor) ServoWrite(pin string, val byte) (err error) { +func (t *gpioTestAdaptor) ServoWrite(pin string, val byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.servoWriteFunc(pin, val) } -func (t *gpioTestAdaptor) Connect() (err error) { return } -func (t *gpioTestAdaptor) Finalize() (err error) { return } -func (t *gpioTestAdaptor) Name() string { return t.name } -func (t *gpioTestAdaptor) SetName(n string) { t.name = n } -func (t *gpioTestAdaptor) Port() string { return t.port } +func (t *gpioTestAdaptor) Connect() error { return nil } +func (t *gpioTestAdaptor) Finalize() error { return nil } +func (t *gpioTestAdaptor) Name() string { return t.name } +func (t *gpioTestAdaptor) SetName(n string) { t.name = n } +func (t *gpioTestAdaptor) Port() string { return t.port } // DigitalPin (interface DigitalPinnerProvider) return a pin object func (t *gpioTestAdaptor) DigitalPin(id string) (gobot.DigitalPinner, error) { @@ -121,8 +121,8 @@ func (d *digitalPinMock) Unexport() error { } // Read (interface DigitalPinner) reads the current value of the pin -func (d *digitalPinMock) Read() (n int, err error) { - return 0, err +func (d *digitalPinMock) Read() (int, error) { + return 0, nil } // Write (interface DigitalPinner) writes to the pin @@ -132,7 +132,7 @@ func (d *digitalPinMock) Write(b int) error { func (t *gpioTestAdaptor) addDigitalPin(id string) *digitalPinMock { dpm := &digitalPinMock{ - writeFunc: func(val int) (err error) { return nil }, + writeFunc: func(val int) error { return nil }, } t.pinMap[id] = dpm return dpm diff --git a/drivers/gpio/led_driver.go b/drivers/gpio/led_driver.go index fd5f4197d..c69121424 100644 --- a/drivers/gpio/led_driver.go +++ b/drivers/gpio/led_driver.go @@ -1,6 +1,10 @@ package gpio -import "gobot.io/x/gobot/v2" +import ( + "log" + + "gobot.io/x/gobot/v2" +) // LedDriver represents a digital Led type LedDriver struct { @@ -20,7 +24,7 @@ type LedDriver struct { // "On" - See LedDriver.On // "Off" - See LedDriver.Off func NewLedDriver(a DigitalWriter, pin string) *LedDriver { - l := &LedDriver{ + d := &LedDriver{ name: gobot.DefaultName("LED"), pin: pin, connection: a, @@ -28,83 +32,86 @@ func NewLedDriver(a DigitalWriter, pin string) *LedDriver { Commander: gobot.NewCommander(), } - l.AddCommand("Brightness", func(params map[string]interface{}) interface{} { - level := byte(params["level"].(float64)) - return l.Brightness(level) + d.AddCommand("Brightness", func(params map[string]interface{}) interface{} { + level := byte(params["level"].(float64)) //nolint:forcetypeassert // ok here + return d.Brightness(level) }) - l.AddCommand("Toggle", func(params map[string]interface{}) interface{} { - return l.Toggle() + d.AddCommand("Toggle", func(params map[string]interface{}) interface{} { + return d.Toggle() }) - l.AddCommand("On", func(params map[string]interface{}) interface{} { - return l.On() + d.AddCommand("On", func(params map[string]interface{}) interface{} { + return d.On() }) - l.AddCommand("Off", func(params map[string]interface{}) interface{} { - return l.Off() + d.AddCommand("Off", func(params map[string]interface{}) interface{} { + return d.Off() }) - return l + return d } // Start implements the Driver interface -func (l *LedDriver) Start() (err error) { return } +func (d *LedDriver) Start() error { return nil } // Halt implements the Driver interface -func (l *LedDriver) Halt() (err error) { return } +func (d *LedDriver) Halt() error { return nil } // Name returns the LedDrivers name -func (l *LedDriver) Name() string { return l.name } +func (d *LedDriver) Name() string { return d.name } // SetName sets the LedDrivers name -func (l *LedDriver) SetName(n string) { l.name = n } +func (d *LedDriver) SetName(n string) { d.name = n } // Pin returns the LedDrivers name -func (l *LedDriver) Pin() string { return l.pin } +func (d *LedDriver) Pin() string { return d.pin } // Connection returns the LedDrivers Connection -func (l *LedDriver) Connection() gobot.Connection { - return l.connection.(gobot.Connection) +func (d *LedDriver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil } // State return true if the led is On and false if the led is Off -func (l *LedDriver) State() bool { - return l.high +func (d *LedDriver) State() bool { + return d.high } // On sets the led to a high state. -func (l *LedDriver) On() (err error) { - if err = l.connection.DigitalWrite(l.Pin(), 1); err != nil { - return +func (d *LedDriver) On() error { + if err := d.connection.DigitalWrite(d.Pin(), 1); err != nil { + return err } - l.high = true - return + d.high = true + return nil } // Off sets the led to a low state. -func (l *LedDriver) Off() (err error) { - if err = l.connection.DigitalWrite(l.Pin(), 0); err != nil { - return +func (d *LedDriver) Off() error { + if err := d.connection.DigitalWrite(d.Pin(), 0); err != nil { + return err } - l.high = false - return + d.high = false + return nil } // Toggle sets the led to the opposite of it's current state -func (l *LedDriver) Toggle() (err error) { - if l.State() { - err = l.Off() - } else { - err = l.On() +func (d *LedDriver) Toggle() error { + if d.State() { + return d.Off() } - return + return d.On() } // Brightness sets the led to the specified level of brightness -func (l *LedDriver) Brightness(level byte) (err error) { - if writer, ok := l.connection.(PwmWriter); ok { - return writer.PwmWrite(l.Pin(), level) +func (d *LedDriver) Brightness(level byte) error { + if writer, ok := d.connection.(PwmWriter); ok { + return writer.PwmWrite(d.Pin(), level) } return ErrPwmWriteUnsupported } diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index b5c74f629..0fef94b11 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package gpio import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -14,10 +16,10 @@ var _ gobot.Driver = (*LedDriver)(nil) func initTestLedDriver() *LedDriver { a := newGpioTestAdaptor() - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return nil } - a.pwmWriteFunc = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) error { return nil } return NewLedDriver(a, "1") @@ -31,10 +33,10 @@ func TestLedDriver(t *testing.T) { assert.Equal(t, "1", d.Pin()) assert.NotNil(t, d.Connection()) - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } - a.pwmWriteFunc = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) error { return errors.New("pwm error") } @@ -73,9 +75,8 @@ func TestLedDriverToggle(t *testing.T) { func TestLedDriverBrightness(t *testing.T) { a := newGpioTestAdaptor() d := NewLedDriver(a, "1") - a.pwmWriteFunc = func(string, byte) (err error) { - err = errors.New("pwm error") - return + a.pwmWriteFunc = func(string, byte) error { + return errors.New("pwm error") } require.ErrorContains(t, d.Brightness(150), "pwm error") } diff --git a/drivers/gpio/max7219_driver.go b/drivers/gpio/max7219_driver.go index 216d7e26d..c4bb713c6 100644 --- a/drivers/gpio/max7219_driver.go +++ b/drivers/gpio/max7219_driver.go @@ -2,6 +2,7 @@ package gpio import ( "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/gpio/max7219_driver_test.go b/drivers/gpio/max7219_driver_test.go index 8515b6bab..e668c8952 100644 --- a/drivers/gpio/max7219_driver_test.go +++ b/drivers/gpio/max7219_driver_test.go @@ -6,15 +6,16 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) var _ gobot.Driver = (*MAX7219Driver)(nil) // --------- HELPERS -func initTestMAX7219Driver() (driver *MAX7219Driver) { - driver, _ = initTestMAX7219DriverWithStubbedAdaptor() - return +func initTestMAX7219Driver() *MAX7219Driver { + d, _ := initTestMAX7219DriverWithStubbedAdaptor() + return d } func initTestMAX7219DriverWithStubbedAdaptor() (*MAX7219Driver, *gpioTestAdaptor) { diff --git a/drivers/gpio/motor_driver.go b/drivers/gpio/motor_driver.go index f14dc9707..9f6dcfa97 100644 --- a/drivers/gpio/motor_driver.go +++ b/drivers/gpio/motor_driver.go @@ -1,6 +1,8 @@ package gpio import ( + "log" + "gobot.io/x/gobot/v2" ) @@ -33,177 +35,175 @@ func NewMotorDriver(a DigitalWriter, speedPin string) *MotorDriver { } // Name returns the MotorDrivers name -func (m *MotorDriver) Name() string { return m.name } +func (d *MotorDriver) Name() string { return d.name } // SetName sets the MotorDrivers name -func (m *MotorDriver) SetName(n string) { m.name = n } +func (d *MotorDriver) SetName(n string) { d.name = n } // Connection returns the MotorDrivers Connection -func (m *MotorDriver) Connection() gobot.Connection { return m.connection.(gobot.Connection) } +func (d *MotorDriver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil +} // Start implements the Driver interface -func (m *MotorDriver) Start() (err error) { return } +func (d *MotorDriver) Start() error { return nil } // Halt implements the Driver interface -func (m *MotorDriver) Halt() (err error) { return } +func (d *MotorDriver) Halt() error { return nil } // Off turns the motor off or sets the motor to a 0 speed -func (m *MotorDriver) Off() (err error) { - if m.isDigital() { - err = m.changeState(0) - } else { - err = m.Speed(0) +func (d *MotorDriver) Off() error { + if d.isDigital() { + return d.changeState(0) } - return + + return d.Speed(0) } // On turns the motor on or sets the motor to a maximum speed -func (m *MotorDriver) On() (err error) { - if m.isDigital() { - err = m.changeState(1) - } else { - if m.CurrentSpeed == 0 { - m.CurrentSpeed = 255 - } - err = m.Speed(m.CurrentSpeed) +func (d *MotorDriver) On() error { + if d.isDigital() { + return d.changeState(1) } - return + if d.CurrentSpeed == 0 { + d.CurrentSpeed = 255 + } + + return d.Speed(d.CurrentSpeed) } // Min sets the motor to the minimum speed -func (m *MotorDriver) Min() (err error) { - return m.Off() +func (d *MotorDriver) Min() error { + return d.Off() } // Max sets the motor to the maximum speed -func (m *MotorDriver) Max() (err error) { - return m.Speed(255) +func (d *MotorDriver) Max() error { + return d.Speed(255) } // IsOn returns true if the motor is on -func (m *MotorDriver) IsOn() bool { - if m.isDigital() { - return m.CurrentState == 1 +func (d *MotorDriver) IsOn() bool { + if d.isDigital() { + return d.CurrentState == 1 } - return m.CurrentSpeed > 0 + return d.CurrentSpeed > 0 } // IsOff returns true if the motor is off -func (m *MotorDriver) IsOff() bool { - return !m.IsOn() +func (d *MotorDriver) IsOff() bool { + return !d.IsOn() } // Toggle sets the motor to the opposite of it's current state -func (m *MotorDriver) Toggle() (err error) { - if m.IsOn() { - err = m.Off() - } else { - err = m.On() +func (d *MotorDriver) Toggle() error { + if d.IsOn() { + return d.Off() } - return + + return d.On() } // Speed sets the speed of the motor -func (m *MotorDriver) Speed(value byte) (err error) { - if writer, ok := m.connection.(PwmWriter); ok { - m.CurrentMode = "analog" - m.CurrentSpeed = value - return writer.PwmWrite(m.SpeedPin, value) +func (d *MotorDriver) Speed(value byte) error { + if writer, ok := d.connection.(PwmWriter); ok { + d.CurrentMode = "analog" + d.CurrentSpeed = value + return writer.PwmWrite(d.SpeedPin, value) } return ErrPwmWriteUnsupported } // Forward sets the forward pin to the specified speed -func (m *MotorDriver) Forward(speed byte) (err error) { - err = m.Direction("forward") - if err != nil { - return +func (d *MotorDriver) Forward(speed byte) error { + if err := d.Direction("forward"); err != nil { + return err } - err = m.Speed(speed) - if err != nil { - return + if err := d.Speed(speed); err != nil { + return err } - return + + return nil } // Backward sets the backward pin to the specified speed -func (m *MotorDriver) Backward(speed byte) (err error) { - err = m.Direction("backward") - if err != nil { - return +func (d *MotorDriver) Backward(speed byte) error { + if err := d.Direction("backward"); err != nil { + return err } - err = m.Speed(speed) - if err != nil { - return + if err := d.Speed(speed); err != nil { + return err } - return + + return nil } // Direction sets the direction pin to the specified speed -func (m *MotorDriver) Direction(direction string) (err error) { - m.CurrentDirection = direction - if m.DirectionPin != "" { +func (d *MotorDriver) Direction(direction string) error { + d.CurrentDirection = direction + if d.DirectionPin != "" { var level byte if direction == "forward" { level = 1 } else { level = 0 } - err = m.connection.DigitalWrite(m.DirectionPin, level) - } else { - var forwardLevel, backwardLevel byte - switch direction { - case "forward": - forwardLevel = 1 - backwardLevel = 0 - case "backward": - forwardLevel = 0 - backwardLevel = 1 - case "none": - forwardLevel = 0 - backwardLevel = 0 - } - err = m.connection.DigitalWrite(m.ForwardPin, forwardLevel) - if err != nil { - return - } - err = m.connection.DigitalWrite(m.BackwardPin, backwardLevel) - if err != nil { - return - } + return d.connection.DigitalWrite(d.DirectionPin, level) + } + + var forwardLevel, backwardLevel byte + switch direction { + case "forward": + forwardLevel = 1 + backwardLevel = 0 + case "backward": + forwardLevel = 0 + backwardLevel = 1 + case "none": + forwardLevel = 0 + backwardLevel = 0 } - return + + if err := d.connection.DigitalWrite(d.ForwardPin, forwardLevel); err != nil { + return err + } + + return d.connection.DigitalWrite(d.BackwardPin, backwardLevel) } -func (m *MotorDriver) isDigital() bool { - return m.CurrentMode == "digital" +func (d *MotorDriver) isDigital() bool { + return d.CurrentMode == "digital" } -func (m *MotorDriver) changeState(state byte) (err error) { - m.CurrentState = state +func (d *MotorDriver) changeState(state byte) error { + d.CurrentState = state if state == 1 { - m.CurrentSpeed = 255 + d.CurrentSpeed = 255 } else { - m.CurrentSpeed = 0 - } - if m.ForwardPin != "" { - if state == 1 { - err = m.Direction(m.CurrentDirection) - if err != nil { - return - } - if m.SpeedPin != "" { - err = m.Speed(m.CurrentSpeed) - if err != nil { - return - } - } - } else { - err = m.Direction("none") + d.CurrentSpeed = 0 + } + + if d.ForwardPin == "" { + return d.connection.DigitalWrite(d.SpeedPin, state) + } + + if state != 1 { + return d.Direction("none") + } + + if err := d.Direction(d.CurrentDirection); err != nil { + return err + } + if d.SpeedPin != "" { + if err := d.Speed(d.CurrentSpeed); err != nil { + return err } - } else { - err = m.connection.DigitalWrite(m.SpeedPin, state) } - return + return nil } diff --git a/drivers/gpio/motor_driver_test.go b/drivers/gpio/motor_driver_test.go index 5864b791c..f8610fb32 100644 --- a/drivers/gpio/motor_driver_test.go +++ b/drivers/gpio/motor_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/gpio/pir_motion_driver.go b/drivers/gpio/pir_motion_driver.go index aa32b50e5..e75ef2b0d 100644 --- a/drivers/gpio/pir_motion_driver.go +++ b/drivers/gpio/pir_motion_driver.go @@ -23,7 +23,8 @@ type PIRMotionDriver struct { // // time.Duration: Interval at which the PIRMotionDriver is polled for new information func NewPIRMotionDriver(a DigitalReader, pin string, v ...time.Duration) *PIRMotionDriver { - b := &PIRMotionDriver{ + //nolint:forcetypeassert // no error return value, so there is no better way + d := &PIRMotionDriver{ Driver: NewDriver(a.(gobot.Connection), "PIRMotion"), Eventer: gobot.NewEventer(), pin: pin, @@ -31,30 +32,30 @@ func NewPIRMotionDriver(a DigitalReader, pin string, v ...time.Duration) *PIRMot interval: 10 * time.Millisecond, halt: make(chan bool), } - b.afterStart = b.initialize - b.beforeHalt = b.shutdown + d.afterStart = d.initialize + d.beforeHalt = d.shutdown if len(v) > 0 { - b.interval = v[0] + d.interval = v[0] } - b.AddEvent(MotionDetected) - b.AddEvent(MotionStopped) - b.AddEvent(Error) + d.AddEvent(MotionDetected) + d.AddEvent(MotionStopped) + d.AddEvent(Error) - return b + return d } // Pin returns the PIRMotionDriver pin -func (p *PIRMotionDriver) Pin() string { return p.pin } +func (d *PIRMotionDriver) Pin() string { return d.pin } // Active gets the current state -func (p *PIRMotionDriver) Active() bool { +func (d *PIRMotionDriver) Active() bool { // ensure that read and write can not interfere - p.mutex.Lock() - defer p.mutex.Unlock() + d.mutex.Lock() + defer d.mutex.Unlock() - return p.active + return d.active } // initialize the PIRMotionDriver and polls the state of the sensor at the given interval. @@ -69,17 +70,17 @@ func (p *PIRMotionDriver) Active() bool { // just as long as motion is still being detected. // It will only send the MotionStopped event once, however, until // motion starts being detected again -func (p *PIRMotionDriver) initialize() error { +func (d *PIRMotionDriver) initialize() error { go func() { for { - newValue, err := p.connection.(DigitalReader).DigitalRead(p.Pin()) + newValue, err := d.connection.(DigitalReader).DigitalRead(d.Pin()) if err != nil { - p.Publish(Error, err) + d.Publish(Error, err) } - p.update(newValue) + d.update(newValue) select { - case <-time.After(p.interval): - case <-p.halt: + case <-time.After(d.interval): + case <-d.halt: return } } @@ -88,26 +89,26 @@ func (p *PIRMotionDriver) initialize() error { } // shutdown stops polling -func (p *PIRMotionDriver) shutdown() error { - p.halt <- true +func (d *PIRMotionDriver) shutdown() error { + d.halt <- true return nil } -func (p *PIRMotionDriver) update(newValue int) { +func (d *PIRMotionDriver) update(newValue int) { // ensure that read and write can not interfere - p.mutex.Lock() - defer p.mutex.Unlock() + d.mutex.Lock() + defer d.mutex.Unlock() switch newValue { case 1: - if !p.active { - p.active = true - p.Publish(MotionDetected, newValue) + if !d.active { + d.active = true + d.Publish(MotionDetected, newValue) } case 0: - if p.active { - p.active = false - p.Publish(MotionStopped, newValue) + if d.active { + d.active = false + d.Publish(MotionStopped, newValue) } } } diff --git a/drivers/gpio/pir_motion_driver_test.go b/drivers/gpio/pir_motion_driver_test.go index 709f07b61..04e4c3f79 100644 --- a/drivers/gpio/pir_motion_driver_test.go +++ b/drivers/gpio/pir_motion_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/gpio/relay_driver.go b/drivers/gpio/relay_driver.go index 5a4861ef1..0516e5f91 100644 --- a/drivers/gpio/relay_driver.go +++ b/drivers/gpio/relay_driver.go @@ -1,6 +1,10 @@ package gpio -import "gobot.io/x/gobot/v2" +import ( + "log" + + "gobot.io/x/gobot/v2" +) // RelayDriver represents a digital relay type RelayDriver struct { @@ -20,7 +24,7 @@ type RelayDriver struct { // "On" - See RelayDriver.On // "Off" - See RelayDriver.Off func NewRelayDriver(a DigitalWriter, pin string) *RelayDriver { - l := &RelayDriver{ + d := &RelayDriver{ name: gobot.DefaultName("Relay"), pin: pin, connection: a, @@ -29,93 +33,89 @@ func NewRelayDriver(a DigitalWriter, pin string) *RelayDriver { Commander: gobot.NewCommander(), } - l.AddCommand("Toggle", func(params map[string]interface{}) interface{} { - return l.Toggle() + d.AddCommand("Toggle", func(params map[string]interface{}) interface{} { + return d.Toggle() }) - l.AddCommand("On", func(params map[string]interface{}) interface{} { - return l.On() + d.AddCommand("On", func(params map[string]interface{}) interface{} { + return d.On() }) - l.AddCommand("Off", func(params map[string]interface{}) interface{} { - return l.Off() + d.AddCommand("Off", func(params map[string]interface{}) interface{} { + return d.Off() }) - return l + return d } // Start implements the Driver interface -func (l *RelayDriver) Start() (err error) { return } +func (d *RelayDriver) Start() error { return nil } // Halt implements the Driver interface -func (l *RelayDriver) Halt() (err error) { return } +func (d *RelayDriver) Halt() error { return nil } // Name returns the RelayDrivers name -func (l *RelayDriver) Name() string { return l.name } +func (d *RelayDriver) Name() string { return d.name } // SetName sets the RelayDrivers name -func (l *RelayDriver) SetName(n string) { l.name = n } +func (d *RelayDriver) SetName(n string) { d.name = n } // Pin returns the RelayDrivers name -func (l *RelayDriver) Pin() string { return l.pin } +func (d *RelayDriver) Pin() string { return d.pin } // Connection returns the RelayDrivers Connection -func (l *RelayDriver) Connection() gobot.Connection { - return l.connection.(gobot.Connection) +func (d *RelayDriver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil } // State return true if the relay is On and false if the relay is Off -func (l *RelayDriver) State() bool { - if l.Inverted { - return !l.high +func (d *RelayDriver) State() bool { + if d.Inverted { + return !d.high } - return l.high + return d.high } // On sets the relay to a high state. -func (l *RelayDriver) On() (err error) { +func (d *RelayDriver) On() error { newValue := byte(1) - if l.Inverted { + if d.Inverted { newValue = 0 } - if err = l.connection.DigitalWrite(l.Pin(), newValue); err != nil { - return + if err := d.connection.DigitalWrite(d.Pin(), newValue); err != nil { + return err } - if l.Inverted { - l.high = false - } else { - l.high = true - } + d.high = !d.Inverted - return + return nil } // Off sets the relay to a low state. -func (l *RelayDriver) Off() (err error) { +func (d *RelayDriver) Off() error { newValue := byte(0) - if l.Inverted { + if d.Inverted { newValue = 1 } - if err = l.connection.DigitalWrite(l.Pin(), newValue); err != nil { - return + if err := d.connection.DigitalWrite(d.Pin(), newValue); err != nil { + return err } - if l.Inverted { - l.high = true - } else { - l.high = false - } + d.high = d.Inverted - return + return nil } // Toggle sets the relay to the opposite of it's current state -func (l *RelayDriver) Toggle() (err error) { - if l.State() { - err = l.Off() - } else { - err = l.On() +func (d *RelayDriver) Toggle() error { + if d.State() { + return d.Off() } - return + + return d.On() } diff --git a/drivers/gpio/relay_driver_test.go b/drivers/gpio/relay_driver_test.go index 320034403..6cf319c60 100644 --- a/drivers/gpio/relay_driver_test.go +++ b/drivers/gpio/relay_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -16,10 +17,10 @@ func (l *RelayDriver) High() bool { return l.high } func initTestRelayDriver() (*RelayDriver, *gpioTestAdaptor) { a := newGpioTestAdaptor() - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return nil } - a.pwmWriteFunc = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) error { return nil } return NewRelayDriver(a, "1"), a diff --git a/drivers/gpio/rgb_led_driver.go b/drivers/gpio/rgb_led_driver.go index 22116a155..c67b90080 100644 --- a/drivers/gpio/rgb_led_driver.go +++ b/drivers/gpio/rgb_led_driver.go @@ -1,6 +1,10 @@ package gpio -import "gobot.io/x/gobot/v2" +import ( + "log" + + "gobot.io/x/gobot/v2" +) // RgbLedDriver represents a digital RGB Led type RgbLedDriver struct { @@ -26,7 +30,7 @@ type RgbLedDriver struct { // "On" - See RgbLedDriver.On // "Off" - See RgbLedDriver.Off func NewRgbLedDriver(a DigitalWriter, redPin string, greenPin string, bluePin string) *RgbLedDriver { - l := &RgbLedDriver{ + d := &RgbLedDriver{ name: gobot.DefaultName("RGBLED"), pinRed: redPin, pinGreen: greenPin, @@ -36,123 +40,128 @@ func NewRgbLedDriver(a DigitalWriter, redPin string, greenPin string, bluePin st Commander: gobot.NewCommander(), } - l.AddCommand("SetRGB", func(params map[string]interface{}) interface{} { + //nolint:forcetypeassert // ok here + d.AddCommand("SetRGB", func(params map[string]interface{}) interface{} { r := byte(params["r"].(int)) g := byte(params["g"].(int)) b := byte(params["b"].(int)) - return l.SetRGB(r, g, b) + return d.SetRGB(r, g, b) }) - l.AddCommand("Toggle", func(params map[string]interface{}) interface{} { - return l.Toggle() + d.AddCommand("Toggle", func(params map[string]interface{}) interface{} { + return d.Toggle() }) - l.AddCommand("On", func(params map[string]interface{}) interface{} { - return l.On() + d.AddCommand("On", func(params map[string]interface{}) interface{} { + return d.On() }) - l.AddCommand("Off", func(params map[string]interface{}) interface{} { - return l.Off() + d.AddCommand("Off", func(params map[string]interface{}) interface{} { + return d.Off() }) - return l + return d } // Start implements the Driver interface -func (l *RgbLedDriver) Start() (err error) { return } +func (d *RgbLedDriver) Start() error { return nil } // Halt implements the Driver interface -func (l *RgbLedDriver) Halt() (err error) { return } +func (d *RgbLedDriver) Halt() error { return nil } // Name returns the RGBLEDDrivers name -func (l *RgbLedDriver) Name() string { return l.name } +func (d *RgbLedDriver) Name() string { return d.name } // SetName sets the RGBLEDDrivers name -func (l *RgbLedDriver) SetName(n string) { l.name = n } +func (d *RgbLedDriver) SetName(n string) { d.name = n } // Pin returns the RgbLedDrivers pins -func (l *RgbLedDriver) Pin() string { - return "r=" + l.pinRed + ", g=" + l.pinGreen + ", b=" + l.pinBlue +func (d *RgbLedDriver) Pin() string { + return "r=" + d.pinRed + ", g=" + d.pinGreen + ", b=" + d.pinBlue } // RedPin returns the RgbLedDrivers redPin -func (l *RgbLedDriver) RedPin() string { return l.pinRed } +func (d *RgbLedDriver) RedPin() string { return d.pinRed } // GreenPin returns the RgbLedDrivers redPin -func (l *RgbLedDriver) GreenPin() string { return l.pinGreen } +func (d *RgbLedDriver) GreenPin() string { return d.pinGreen } // BluePin returns the RgbLedDrivers bluePin -func (l *RgbLedDriver) BluePin() string { return l.pinBlue } +func (d *RgbLedDriver) BluePin() string { return d.pinBlue } // Connection returns the RgbLedDriver Connection -func (l *RgbLedDriver) Connection() gobot.Connection { - return l.connection.(gobot.Connection) +func (d *RgbLedDriver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil } // State return true if the led is On and false if the led is Off -func (l *RgbLedDriver) State() bool { - return l.high +func (d *RgbLedDriver) State() bool { + return d.high } // On sets the led's pins to their various states -func (l *RgbLedDriver) On() (err error) { - if err = l.SetLevel(l.pinRed, l.redColor); err != nil { - return +func (d *RgbLedDriver) On() error { + if err := d.SetLevel(d.pinRed, d.redColor); err != nil { + return err } - if err = l.SetLevel(l.pinGreen, l.greenColor); err != nil { - return + if err := d.SetLevel(d.pinGreen, d.greenColor); err != nil { + return err } - if err = l.SetLevel(l.pinBlue, l.blueColor); err != nil { - return + if err := d.SetLevel(d.pinBlue, d.blueColor); err != nil { + return err } - l.high = true - return + d.high = true + return nil } // Off sets the led to black. -func (l *RgbLedDriver) Off() (err error) { - if err = l.SetLevel(l.pinRed, 0); err != nil { - return +func (d *RgbLedDriver) Off() error { + if err := d.SetLevel(d.pinRed, 0); err != nil { + return err } - if err = l.SetLevel(l.pinGreen, 0); err != nil { - return + if err := d.SetLevel(d.pinGreen, 0); err != nil { + return err } - if err = l.SetLevel(l.pinBlue, 0); err != nil { - return + if err := d.SetLevel(d.pinBlue, 0); err != nil { + return err } - l.high = false - return + d.high = false + return nil } // Toggle sets the led to the opposite of it's current state -func (l *RgbLedDriver) Toggle() (err error) { - if l.State() { - err = l.Off() - } else { - err = l.On() +func (d *RgbLedDriver) Toggle() error { + if d.State() { + return d.Off() } - return + + return d.On() } // SetLevel sets the led to the specified color level -func (l *RgbLedDriver) SetLevel(pin string, level byte) (err error) { - if writer, ok := l.connection.(PwmWriter); ok { +func (d *RgbLedDriver) SetLevel(pin string, level byte) error { + if writer, ok := d.connection.(PwmWriter); ok { return writer.PwmWrite(pin, level) } return ErrPwmWriteUnsupported } // SetRGB sets the Red Green Blue value of the LED. -func (l *RgbLedDriver) SetRGB(r, g, b byte) error { - l.redColor = r - l.greenColor = g - l.blueColor = b +func (d *RgbLedDriver) SetRGB(r, g, b byte) error { + d.redColor = r + d.greenColor = g + d.blueColor = b - return l.On() + return d.On() } diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index 46121ca33..b4b057986 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package gpio import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -14,10 +16,10 @@ var _ gobot.Driver = (*RgbLedDriver)(nil) func initTestRgbLedDriver() *RgbLedDriver { a := newGpioTestAdaptor() - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return nil } - a.pwmWriteFunc = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) error { return nil } return NewRgbLedDriver(a, "1", "2", "3") @@ -35,10 +37,10 @@ func TestRgbLedDriver(t *testing.T) { assert.Equal(t, "3", d.BluePin()) assert.NotNil(t, d.Connection()) - a.digitalWriteFunc = func(string, byte) (err error) { + a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } - a.pwmWriteFunc = func(string, byte) (err error) { + a.pwmWriteFunc = func(string, byte) error { return errors.New("pwm error") } @@ -80,9 +82,8 @@ func TestRgbLedDriverSetLevel(t *testing.T) { require.NoError(t, d.SetLevel("1", 150)) d = NewRgbLedDriver(a, "1", "2", "3") - a.pwmWriteFunc = func(string, byte) (err error) { - err = errors.New("pwm error") - return + a.pwmWriteFunc = func(string, byte) error { + return errors.New("pwm error") } require.ErrorContains(t, d.SetLevel("1", 150), "pwm error") } diff --git a/drivers/gpio/servo_driver.go b/drivers/gpio/servo_driver.go index 461b842f7..57a4ffea8 100644 --- a/drivers/gpio/servo_driver.go +++ b/drivers/gpio/servo_driver.go @@ -1,6 +1,10 @@ package gpio -import "gobot.io/x/gobot/v2" +import ( + "log" + + "gobot.io/x/gobot/v2" +) // ServoDriver Represents a Servo type ServoDriver struct { @@ -20,7 +24,7 @@ type ServoDriver struct { // "Center" - See ServoDriver.Center // "Max" - See ServoDriver.Max func NewServoDriver(a ServoWriter, pin string) *ServoDriver { - s := &ServoDriver{ + d := &ServoDriver{ name: gobot.DefaultName("Servo"), connection: a, pin: pin, @@ -28,61 +32,68 @@ func NewServoDriver(a ServoWriter, pin string) *ServoDriver { CurrentAngle: 0, } - s.AddCommand("Move", func(params map[string]interface{}) interface{} { - angle := byte(params["angle"].(float64)) - return s.Move(angle) + d.AddCommand("Move", func(params map[string]interface{}) interface{} { + angle := byte(params["angle"].(float64)) //nolint:forcetypeassert // ok here + return d.Move(angle) }) - s.AddCommand("Min", func(params map[string]interface{}) interface{} { - return s.Min() + d.AddCommand("Min", func(params map[string]interface{}) interface{} { + return d.Min() }) - s.AddCommand("Center", func(params map[string]interface{}) interface{} { - return s.Center() + d.AddCommand("Center", func(params map[string]interface{}) interface{} { + return d.Center() }) - s.AddCommand("Max", func(params map[string]interface{}) interface{} { - return s.Max() + d.AddCommand("Max", func(params map[string]interface{}) interface{} { + return d.Max() }) - return s + return d } // Name returns the ServoDrivers name -func (s *ServoDriver) Name() string { return s.name } +func (d *ServoDriver) Name() string { return d.name } // SetName sets the ServoDrivers name -func (s *ServoDriver) SetName(n string) { s.name = n } +func (d *ServoDriver) SetName(n string) { d.name = n } // Pin returns the ServoDrivers pin -func (s *ServoDriver) Pin() string { return s.pin } +func (d *ServoDriver) Pin() string { return d.pin } // Connection returns the ServoDrivers connection -func (s *ServoDriver) Connection() gobot.Connection { return s.connection.(gobot.Connection) } +func (d *ServoDriver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil +} // Start implements the Driver interface -func (s *ServoDriver) Start() (err error) { return } +func (d *ServoDriver) Start() error { return nil } // Halt implements the Driver interface -func (s *ServoDriver) Halt() (err error) { return } +func (d *ServoDriver) Halt() error { return nil } // Move sets the servo to the specified angle. Acceptable angles are 0-180 -func (s *ServoDriver) Move(angle uint8) (err error) { +func (d *ServoDriver) Move(angle uint8) error { if angle > 180 { return ErrServoOutOfRange } - s.CurrentAngle = angle - return s.connection.ServoWrite(s.Pin(), angle) + d.CurrentAngle = angle + return d.connection.ServoWrite(d.Pin(), angle) } // Min sets the servo to it's minimum position -func (s *ServoDriver) Min() (err error) { - return s.Move(0) +func (d *ServoDriver) Min() error { + return d.Move(0) } // Center sets the servo to it's center position -func (s *ServoDriver) Center() (err error) { - return s.Move(90) +func (d *ServoDriver) Center() error { + return d.Move(90) } // Max sets the servo to its maximum position -func (s *ServoDriver) Max() (err error) { - return s.Move(180) +func (d *ServoDriver) Max() error { + return d.Move(180) } diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index a0db6d242..ee05e932f 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package gpio import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -25,7 +27,7 @@ func TestServoDriver(t *testing.T) { assert.Equal(t, "1", d.Pin()) assert.NotNil(t, d.Connection()) - a.servoWriteFunc = func(string, byte) (err error) { + a.servoWriteFunc = func(string, byte) error { return errors.New("pwm error") } diff --git a/drivers/gpio/stepper_driver.go b/drivers/gpio/stepper_driver.go index 626302f8e..f3ae3bdc6 100644 --- a/drivers/gpio/stepper_driver.go +++ b/drivers/gpio/stepper_driver.go @@ -89,6 +89,7 @@ func NewStepperDriver(a DigitalWriter, pins [4]string, phase phase, stepsPerRev if stepsPerRev <= 0 { panic("steps per revolution needs to be greater than zero") } + //nolint:forcetypeassert // no error return value, so there is no better way d := &StepperDriver{ Driver: NewDriver(a.(gobot.Connection), "Stepper"), pins: pins, @@ -150,7 +151,7 @@ func (d *StepperDriver) Move(stepsToMove int) error { return err } -// MoveDeg moves the motor given number of degrees at current speed. Negative values cause to move in backward direction. +// MoveDeg moves the motor given number of degrees at current speed. Negative values cause to move backward. func (d *StepperDriver) MoveDeg(degs int) error { d.mutex.Lock() defer d.mutex.Unlock() @@ -421,8 +422,8 @@ func (d *StepperDriver) getDelayPerStep() time.Duration { return time.Duration(60*1000*1000/(d.stepsPerRev*float32(d.speedRpm))) * time.Microsecond } -// phasedStepping moves the motor one step with the configured speed and direction. The speed can be adjusted by SetSpeed() -// and the direction can be changed by SetDirection() asynchronously. +// phasedStepping moves the motor one step with the configured speed and direction. The speed can be adjusted +// by SetSpeed() and the direction can be changed by SetDirection() asynchronously. func (d *StepperDriver) phasedStepping() error { // ensure that read and write of variables (direction, stepNum) can not interfere d.valueMutex.Lock() @@ -445,6 +446,7 @@ func (d *StepperDriver) phasedStepping() error { r := int(math.Abs(float64(d.stepNum))) % len(d.phase) for i, v := range d.phase[r] { + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(d.pins[i], v); err != nil { d.stepNum = oldStepNum return err @@ -459,6 +461,7 @@ func (d *StepperDriver) phasedStepping() error { func (d *StepperDriver) sleepOuputs() error { for _, pin := range d.pins { + //nolint:forcetypeassert // type safe by constructor if err := d.connection.(DigitalWriter).DigitalWrite(pin, 0); err != nil { return err } diff --git a/drivers/gpio/tm1638_driver.go b/drivers/gpio/tm1638_driver.go index 588671433..8b89ccff7 100644 --- a/drivers/gpio/tm1638_driver.go +++ b/drivers/gpio/tm1638_driver.go @@ -25,7 +25,7 @@ const ( TM1638FixedAddr = 0x04 ) -// TM1638Driver is the gobot driver for modules based on the TM1638, which has 8 7-segment displays, 8 LEDs and 8 buttons +// TM1638Driver is the driver for modules based on the TM1638, which has 8 7-segment displays, 8 LEDs and 8 buttons. // Buttons are not supported // // Datasheet EN: https://retrocip.cz/files/tm1638.pdf diff --git a/drivers/gpio/tm1638_driver_test.go b/drivers/gpio/tm1638_driver_test.go index dc916d9ba..ba60fa8d8 100644 --- a/drivers/gpio/tm1638_driver_test.go +++ b/drivers/gpio/tm1638_driver_test.go @@ -6,15 +6,16 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) var _ gobot.Driver = (*TM1638Driver)(nil) // --------- HELPERS -func initTestTM1638Driver() (driver *TM1638Driver) { - driver, _ = initTestTM1638DriverWithStubbedAdaptor() - return +func initTestTM1638Driver() *TM1638Driver { + d, _ := initTestTM1638DriverWithStubbedAdaptor() + return d } func initTestTM1638DriverWithStubbedAdaptor() (*TM1638Driver, *gpioTestAdaptor) { diff --git a/drivers/i2c/adafruit1109_driver.go b/drivers/i2c/adafruit1109_driver.go index feae2530f..c8eabeca9 100644 --- a/drivers/i2c/adafruit1109_driver.go +++ b/drivers/i2c/adafruit1109_driver.go @@ -45,7 +45,7 @@ type Adafruit1109Driver struct { // NewAdafruit1109Driver creates is a new driver for the 2x16 LCD display with RGB backlit and 5 keys. // -// Because HD44780 and MCP23017 are already implemented in gobot, we creates a wrapper for using existing implementation. +// Because HD44780 and MCP23017 are already implemented in gobot, this is a wrapper for using existing implementation. // So, for the documentation of the parameters, have a look at this drivers. // // Tests are done with a Tinkerboard. diff --git a/drivers/i2c/adafruit1109_driver_test.go b/drivers/i2c/adafruit1109_driver_test.go index 838f57592..6b1a61b62 100644 --- a/drivers/i2c/adafruit1109_driver_test.go +++ b/drivers/i2c/adafruit1109_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/adafruit2327_driver_test.go b/drivers/i2c/adafruit2327_driver_test.go index b070c3f4b..e8558ab57 100644 --- a/drivers/i2c/adafruit2327_driver_test.go +++ b/drivers/i2c/adafruit2327_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/adafruit2348_driver.go b/drivers/i2c/adafruit2348_driver.go index f6014b2b6..2fdf86a47 100644 --- a/drivers/i2c/adafruit2348_driver.go +++ b/drivers/i2c/adafruit2348_driver.go @@ -260,16 +260,17 @@ func (a *Adafruit2348Driver) oneStep(motor int, dir Adafruit2348Direction, style pwmA = 0 pwmB = 0 currStep := a.stepperMotors[motor].currentStep - if currStep >= 0 && currStep < adafruit2348StepperMicrosteps { + switch { + case currStep >= 0 && currStep < adafruit2348StepperMicrosteps: pwmA = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps-currStep] pwmB = a.stepperMicrostepCurve[currStep] - } else if currStep >= adafruit2348StepperMicrosteps && currStep < adafruit2348StepperMicrosteps*2 { + case currStep >= adafruit2348StepperMicrosteps && currStep < adafruit2348StepperMicrosteps*2: pwmA = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps] pwmB = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*2-currStep] - } else if currStep >= adafruit2348StepperMicrosteps*2 && currStep < adafruit2348StepperMicrosteps*3 { + case currStep >= adafruit2348StepperMicrosteps*2 && currStep < adafruit2348StepperMicrosteps*3: pwmA = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*3-currStep] pwmB = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps*2] - } else if currStep >= adafruit2348StepperMicrosteps*3 && currStep < adafruit2348StepperMicrosteps*4 { + case currStep >= adafruit2348StepperMicrosteps*3 && currStep < adafruit2348StepperMicrosteps*4: pwmA = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps*3] pwmB = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*4-currStep] } diff --git a/drivers/i2c/adafruit2348_driver_test.go b/drivers/i2c/adafruit2348_driver_test.go index a791f646f..104f1df21 100644 --- a/drivers/i2c/adafruit2348_driver_test.go +++ b/drivers/i2c/adafruit2348_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/ads1x15_driver.go b/drivers/i2c/ads1x15_driver.go index 487dcb16e..1e3fbb30a 100644 --- a/drivers/i2c/ads1x15_driver.go +++ b/drivers/i2c/ads1x15_driver.go @@ -113,11 +113,12 @@ func newADS1x15Driver(c Connector, name string, drs map[int]uint16, ddr int, opt } d.AddCommand("ReadDifferenceWithDefaults", func(params map[string]interface{}) interface{} { - channel := params["channel"].(int) + channel := params["channel"].(int) //nolint:forcetypeassert // ok here val, err := d.ReadDifferenceWithDefaults(channel) return map[string]interface{}{"val": val, "err": err} }) + //nolint:forcetypeassert // ok here d.AddCommand("ReadDifference", func(params map[string]interface{}) interface{} { channel := params["channel"].(int) gain := params["gain"].(int) @@ -127,11 +128,12 @@ func newADS1x15Driver(c Connector, name string, drs map[int]uint16, ddr int, opt }) d.AddCommand("ReadWithDefaults", func(params map[string]interface{}) interface{} { - channel := params["channel"].(int) + channel := params["channel"].(int) //nolint:forcetypeassert // ok here val, err := d.ReadWithDefaults(channel) return map[string]interface{}{"val": val, "err": err} }) + //nolint:forcetypeassert // ok here d.AddCommand("Read", func(params map[string]interface{}) interface{} { channel := params["channel"].(int) gain := params["gain"].(int) @@ -141,7 +143,7 @@ func newADS1x15Driver(c Connector, name string, drs map[int]uint16, ddr int, opt }) d.AddCommand("AnalogRead", func(params map[string]interface{}) interface{} { - pin := params["pin"].(string) + pin := params["pin"].(string) //nolint:forcetypeassert // ok here val, err := d.AnalogRead(pin) return map[string]interface{}{"val": val, "err": err} }) @@ -281,12 +283,12 @@ func WithADS1x15WaitSingleCycle() func(Config) { // * 1: Channel 0 - channel 3 // * 2: Channel 1 - channel 3 // * 3: Channel 2 - channel 3 -func (d *ADS1x15Driver) ReadDifferenceWithDefaults(diff int) (value float64, err error) { +func (d *ADS1x15Driver) ReadDifferenceWithDefaults(diff int) (float64, error) { d.mutex.Lock() defer d.mutex.Unlock() - if err = d.checkChannel(diff); err != nil { - return + if err := d.checkChannel(diff); err != nil { + return 0, err } return d.readVoltage(diff, 0, d.channelCfgs[diff].gain, d.channelCfgs[diff].dataRate) } @@ -297,41 +299,41 @@ func (d *ADS1x15Driver) ReadDifferenceWithDefaults(diff int) (value float64, err // * 1: Channel 0 - channel 3 // * 2: Channel 1 - channel 3 // * 3: Channel 2 - channel 3 -func (d *ADS1x15Driver) ReadDifference(diff int, gain int, dataRate int) (value float64, err error) { +func (d *ADS1x15Driver) ReadDifference(diff int, gain int, dataRate int) (float64, error) { d.mutex.Lock() defer d.mutex.Unlock() - if err = d.checkChannel(diff); err != nil { - return + if err := d.checkChannel(diff); err != nil { + return 0, err } return d.readVoltage(diff, 0, gain, dataRate) } // ReadWithDefaults reads the voltage at the specified channel (between 0 and 3). // Default values are used for the gain and data rate. The result is in V. -func (d *ADS1x15Driver) ReadWithDefaults(channel int) (value float64, err error) { +func (d *ADS1x15Driver) ReadWithDefaults(channel int) (float64, error) { d.mutex.Lock() defer d.mutex.Unlock() - if err = d.checkChannel(channel); err != nil { - return + if err := d.checkChannel(channel); err != nil { + return 0, err } return d.readVoltage(channel, 0x04, d.channelCfgs[channel].gain, d.channelCfgs[channel].dataRate) } // Read reads the voltage at the specified channel (between 0 and 3). The result is in V. -func (d *ADS1x15Driver) Read(channel int, gain int, dataRate int) (value float64, err error) { +func (d *ADS1x15Driver) Read(channel int, gain int, dataRate int) (float64, error) { d.mutex.Lock() defer d.mutex.Unlock() - if err = d.checkChannel(channel); err != nil { - return + if err := d.checkChannel(channel); err != nil { + return 0, err } return d.readVoltage(channel, 0x04, gain, dataRate) } // AnalogRead returns value from analog reading of specified pin using the default values. -func (d *ADS1x15Driver) AnalogRead(pin string) (value int, err error) { +func (d *ADS1x15Driver) AnalogRead(pin string) (int, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -350,41 +352,40 @@ func (d *ADS1x15Driver) AnalogRead(pin string) (value int, err error) { channel = 3 default: // read the voltage at a specific pin, compared to the ground + var err error channel, err = strconv.Atoi(pin) if err != nil { - return + return 0, err } channelOffset = 0x04 } - if err = d.checkChannel(channel); err != nil { - return + if err := d.checkChannel(channel); err != nil { + return 0, err } - value, err = d.rawRead(channel, channelOffset, d.channelCfgs[channel].gain, d.channelCfgs[channel].dataRate) - - return + return d.rawRead(channel, channelOffset, d.channelCfgs[channel].gain, d.channelCfgs[channel].dataRate) } -func (d *ADS1x15Driver) readVoltage(channel int, channelOffset int, gain int, dataRate int) (value float64, err error) { +func (d *ADS1x15Driver) readVoltage(channel int, channelOffset int, gain int, dataRate int) (float64, error) { fsr, err := ads1x15GetFullScaleRange(gain) if err != nil { - return + return 0, err } rawValue, err := d.rawRead(channel, channelOffset, gain, dataRate) // Calculate return value in V - value = float64(rawValue) / float64(1<<15) * fsr + value := float64(rawValue) / float64(1<<15) * fsr - return + return value, err } -func (d *ADS1x15Driver) rawRead(channel int, channelOffset int, gain int, dataRate int) (data int, err error) { +func (d *ADS1x15Driver) rawRead(channel int, channelOffset int, gain int, dataRate int) (int, error) { // Validate the passed in data rate (differs between ADS1015 and ADS1115). dataRateBits, err := ads1x15GetDataRateBits(d.dataRates, dataRate) if err != nil { - return + return 0, err } var config uint16 @@ -408,35 +409,35 @@ func (d *ADS1x15Driver) rawRead(channel int, channelOffset int, gain int, dataRa config |= ads1x15ConfigCompQueDisable // Send the config value to start the ADC conversion. - if err = d.writeWordBigEndian(ads1x15PointerConfig, config); err != nil { - return + if err := d.writeWordBigEndian(ads1x15PointerConfig, config); err != nil { + return 0, err } // Wait for the ADC sample to finish based on the sample rate plus a // small offset to be sure (0.1 millisecond). delay := time.Duration(1000000/dataRate+100) * time.Microsecond - if err = d.waitForConversionFinished(delay); err != nil { - return + if err := d.waitForConversionFinished(delay); err != nil { + return 0, err } // Retrieve the result. udata, err := d.readWordBigEndian(ads1x15PointerConversion) if err != nil { - return + return 0, err } // Handle negative values as two's complement return int(twosComplement16Bit(udata)), nil } -func (d *ADS1x15Driver) checkChannel(channel int) (err error) { +func (d *ADS1x15Driver) checkChannel(channel int) error { if channel < 0 || channel > 3 { - err = fmt.Errorf("Invalid channel (%d), must be between 0 and 3", channel) + return fmt.Errorf("Invalid channel (%d), must be between 0 and 3", channel) } - return + return nil } -func (d *ADS1x15Driver) waitForConversionFinished(delay time.Duration) (err error) { +func (d *ADS1x15Driver) waitForConversionFinished(delay time.Duration) error { start := time.Now() for i := 0; i < ads1x15WaitMaxCount; i++ { @@ -444,9 +445,10 @@ func (d *ADS1x15Driver) waitForConversionFinished(delay time.Duration) (err erro // most likely the last try will also not finish, so we stop with an error return fmt.Errorf("The conversion is not finished within %s", time.Since(start)) } - var data uint16 - if data, err = d.readWordBigEndian(ads1x15PointerConfig); err != nil { - return + + data, err := d.readWordBigEndian(ads1x15PointerConfig) + if err != nil { + return err } if ads1x15Debug { log.Printf("ADS1x15Driver: config register state: 0x%X\n", data) @@ -466,16 +468,17 @@ func (d *ADS1x15Driver) waitForConversionFinished(delay time.Duration) (err erro log.Printf("conversion takes %s", elapsed) } - return + return nil } func (d *ADS1x15Driver) writeWordBigEndian(reg uint8, val uint16) error { return d.connection.WriteWordData(reg, swapBytes(val)) } -func (d *ADS1x15Driver) readWordBigEndian(reg uint8) (data uint16, err error) { - if data, err = d.connection.ReadWordData(reg); err != nil { - return +func (d *ADS1x15Driver) readWordBigEndian(reg uint8) (uint16, error) { + data, err := d.connection.ReadWordData(reg) + if err != nil { + return 0, err } return swapBytes(data), err } @@ -492,10 +495,9 @@ func (d *ADS1x15Driver) setChannelGains(gain int) { } } -func ads1x15GetFullScaleRange(gain int) (fsr float64, err error) { - fsr, ok := ads1x15FullScaleRange[gain] - if ok { - return +func ads1x15GetFullScaleRange(gain int) (float64, error) { + if fsr, ok := ads1x15FullScaleRange[gain]; ok { + return fsr, nil } keys := []int{} @@ -503,14 +505,13 @@ func ads1x15GetFullScaleRange(gain int) (fsr float64, err error) { keys = append(keys, k) } sort.Ints(keys) - err = fmt.Errorf("Gain (%d) must be one of: %d", gain, keys) - return + + return 0, fmt.Errorf("Gain (%d) must be one of: %d", gain, keys) } -func ads1x15GetDataRateBits(dataRates map[int]uint16, dataRate int) (bits uint16, err error) { - bits, ok := dataRates[dataRate] - if ok { - return +func ads1x15GetDataRateBits(dataRates map[int]uint16, dataRate int) (uint16, error) { + if bits, ok := dataRates[dataRate]; ok { + return bits, nil } keys := []int{} @@ -518,12 +519,12 @@ func ads1x15GetDataRateBits(dataRates map[int]uint16, dataRate int) (bits uint16 keys = append(keys, k) } sort.Ints(keys) - err = fmt.Errorf("Invalid data rate (%d). Accepted values: %d", dataRate, keys) - return + + return 0, fmt.Errorf("Invalid data rate (%d). Accepted values: %d", dataRate, keys) } // ads1x15BestGainForVoltage returns the gain the most adapted to read up to the specified difference of potential. -func ads1x15BestGainForVoltage(voltage float64) (bestGain int, err error) { +func ads1x15BestGainForVoltage(voltage float64) (int, error) { var max float64 difference := math.MaxFloat64 currentBestGain := -1 @@ -538,10 +539,8 @@ func ads1x15BestGainForVoltage(voltage float64) (bestGain int, err error) { } if currentBestGain < 0 { - err = fmt.Errorf("The maximum voltage which can be read is %f", max) - return + return 0, fmt.Errorf("The maximum voltage which can be read is %f", max) } - bestGain = currentBestGain - return + return currentBestGain, nil } diff --git a/drivers/i2c/ads1x15_driver_test.go b/drivers/i2c/ads1x15_driver_test.go index 3bbe77688..ba524af5b 100644 --- a/drivers/i2c/ads1x15_driver_test.go +++ b/drivers/i2c/ads1x15_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package i2c import ( @@ -5,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) diff --git a/drivers/i2c/adxl345_driver.go b/drivers/i2c/adxl345_driver.go index 5084bd2a6..42d577d36 100644 --- a/drivers/i2c/adxl345_driver.go +++ b/drivers/i2c/adxl345_driver.go @@ -186,39 +186,30 @@ func WithADXL345FullScaleRange(val ADXL345FsRangeConfig) func(Config) { } // UseLowPower change the current rate of the sensor -func (d *ADXL345Driver) UseLowPower(lowPower bool) (err error) { +func (d *ADXL345Driver) UseLowPower(lowPower bool) error { d.mutex.Lock() defer d.mutex.Unlock() d.bwRate.lowPower = lowPower - if err := d.connection.WriteByteData(adxl345Reg_BW_RATE, d.bwRate.toByte()); err != nil { - return err - } - return + return d.connection.WriteByteData(adxl345Reg_BW_RATE, d.bwRate.toByte()) } // SetRate change the current rate of the sensor immediately -func (d *ADXL345Driver) SetRate(rate ADXL345RateConfig) (err error) { +func (d *ADXL345Driver) SetRate(rate ADXL345RateConfig) error { d.mutex.Lock() defer d.mutex.Unlock() d.bwRate.rate = rate - if err := d.connection.WriteByteData(adxl345Reg_BW_RATE, d.bwRate.toByte()); err != nil { - return err - } - return + return d.connection.WriteByteData(adxl345Reg_BW_RATE, d.bwRate.toByte()) } // SetRange change the current range of the sensor immediately -func (d *ADXL345Driver) SetRange(fullScaleRange ADXL345FsRangeConfig) (err error) { +func (d *ADXL345Driver) SetRange(fullScaleRange ADXL345FsRangeConfig) error { d.mutex.Lock() defer d.mutex.Unlock() d.dataFormat.fullScaleRange = fullScaleRange - if err := d.connection.WriteByteData(adxl345Reg_DATA_FORMAT, d.dataFormat.toByte()); err != nil { - return err - } - return + return d.connection.WriteByteData(adxl345Reg_DATA_FORMAT, d.dataFormat.toByte()) } // XYZ returns the adjusted x, y and z axis, unit [g] diff --git a/drivers/i2c/adxl345_driver_test.go b/drivers/i2c/adxl345_driver_test.go index 2888160dd..4fc14d959 100644 --- a/drivers/i2c/adxl345_driver_test.go +++ b/drivers/i2c/adxl345_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -204,9 +205,12 @@ func TestADXL345RawXYZError(t *testing.T) { return 0, errors.New("read error") } // act - _, _, _, err := d.RawXYZ() + x, y, z, err := d.RawXYZ() // assert require.ErrorContains(t, err, "read error") + assert.Equal(t, int16(0), x) + assert.Equal(t, int16(0), y) + assert.Equal(t, int16(0), z) } func TestADXL345XYZ(t *testing.T) { @@ -268,9 +272,12 @@ func TestADXL345XYZError(t *testing.T) { return 0, errors.New("read error") } // act - _, _, _, err := d.XYZ() + x, y, z, err := d.XYZ() // assert require.ErrorContains(t, err, "read error") + assert.InDelta(t, 0.0, x, 0.0) + assert.InDelta(t, 0.0, y, 0.0) + assert.InDelta(t, 0.0, z, 0.0) } func TestADXL345_initialize(t *testing.T) { diff --git a/drivers/i2c/bh1750_driver.go b/drivers/i2c/bh1750_driver.go index a2bbe9c2b..4e470ed14 100644 --- a/drivers/i2c/bh1750_driver.go +++ b/drivers/i2c/bh1750_driver.go @@ -50,27 +50,27 @@ func NewBH1750Driver(c Connector, options ...func(Config)) *BH1750Driver { } // RawSensorData returns the raw value from the bh1750 -func (h *BH1750Driver) RawSensorData() (level int, err error) { +func (h *BH1750Driver) RawSensorData() (int, error) { buf := []byte{0, 0} bytesRead, err := h.connection.Read(buf) - if bytesRead != 2 { - err = errors.New("wrong number of bytes read") - return - } if err != nil { - return + return 0, err } - level = int(buf[0])<<8 | int(buf[1]) + if bytesRead != 2 { + return 0, errors.New("wrong number of bytes read") + } + + level := int(buf[0])<<8 | int(buf[1]) - return + return level, nil } // Lux returns the adjusted value from the bh1750 -func (h *BH1750Driver) Lux() (lux int, err error) { - lux, err = h.RawSensorData() - lux = int(float64(lux) / 1.2) +func (h *BH1750Driver) Lux() (int, error) { + rawLux, err := h.RawSensorData() + lux := int(float64(rawLux) / 1.2) - return + return lux, err } func (h *BH1750Driver) initialize() error { diff --git a/drivers/i2c/bh1750_driver_test.go b/drivers/i2c/bh1750_driver_test.go index ffa75ee6a..9a8e5cbd5 100644 --- a/drivers/i2c/bh1750_driver_test.go +++ b/drivers/i2c/bh1750_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/blinkm_driver.go b/drivers/i2c/blinkm_driver.go index ef8711639..072bbc242 100644 --- a/drivers/i2c/blinkm_driver.go +++ b/drivers/i2c/blinkm_driver.go @@ -31,6 +31,7 @@ func NewBlinkMDriver(c Connector, options ...func(Config)) *BlinkMDriver { option(b) } + //nolint:forcetypeassert // ok here b.AddCommand("Rgb", func(params map[string]interface{}) interface{} { red := byte(params["red"].(float64)) green := byte(params["green"].(float64)) @@ -38,6 +39,7 @@ func NewBlinkMDriver(c Connector, options ...func(Config)) *BlinkMDriver { return b.Rgb(red, green, blue) }) + //nolint:forcetypeassert // ok here b.AddCommand("Fade", func(params map[string]interface{}) interface{} { red := byte(params["red"].(float64)) green := byte(params["green"].(float64)) @@ -59,40 +61,40 @@ func NewBlinkMDriver(c Connector, options ...func(Config)) *BlinkMDriver { } // Rgb sets color using r,g,b params -func (b *BlinkMDriver) Rgb(red byte, green byte, blue byte) (err error) { - if _, err = b.connection.Write([]byte("n")); err != nil { - return +func (b *BlinkMDriver) Rgb(red byte, green byte, blue byte) error { + if _, err := b.connection.Write([]byte("n")); err != nil { + return err } - _, err = b.connection.Write([]byte{red, green, blue}) - return + _, err := b.connection.Write([]byte{red, green, blue}) + return err } // Fade removes color using r,g,b params -func (b *BlinkMDriver) Fade(red byte, green byte, blue byte) (err error) { - if _, err = b.connection.Write([]byte("c")); err != nil { - return +func (b *BlinkMDriver) Fade(red byte, green byte, blue byte) error { + if _, err := b.connection.Write([]byte("c")); err != nil { + return err } - _, err = b.connection.Write([]byte{red, green, blue}) - return + _, err := b.connection.Write([]byte{red, green, blue}) + return err } // FirmwareVersion returns version with MAYOR.minor format -func (b *BlinkMDriver) FirmwareVersion() (version string, err error) { - if _, err = b.connection.Write([]byte("Z")); err != nil { - return +func (b *BlinkMDriver) FirmwareVersion() (string, error) { + if _, err := b.connection.Write([]byte("Z")); err != nil { + return "", err } data := []byte{0, 0} read, err := b.connection.Read(data) if read != 2 || err != nil { - return + return "", err } return fmt.Sprintf("%v.%v", data[0], data[1]), nil } // Color returns an array with current rgb color -func (b *BlinkMDriver) Color() (color []byte, err error) { - if _, err = b.connection.Write([]byte("g")); err != nil { - return +func (b *BlinkMDriver) Color() ([]byte, error) { + if _, err := b.connection.Write([]byte("g")); err != nil { + return []byte{}, err } data := []byte{0, 0, 0} read, err := b.connection.Read(data) diff --git a/drivers/i2c/blinkm_driver_test.go b/drivers/i2c/blinkm_driver_test.go index 1818fbbbb..e10cebdfb 100644 --- a/drivers/i2c/blinkm_driver_test.go +++ b/drivers/i2c/blinkm_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package i2c import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/bme280_driver.go b/drivers/i2c/bme280_driver.go index d3767cdc1..11d658ce8 100644 --- a/drivers/i2c/bme280_driver.go +++ b/drivers/i2c/bme280_driver.go @@ -123,16 +123,16 @@ func WithBME280HumidityOversampling(val BME280HumidityOversampling) func(Config) } // Humidity returns the current humidity in percentage of relative humidity -func (d *BME280Driver) Humidity() (humidity float32, err error) { +func (d *BME280Driver) Humidity() (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - var rawH uint32 - if rawH, err = d.rawHumidity(); err != nil { + rawH, err := d.rawHumidity() + if err != nil { return 0.0, err } - humidity = d.calculateHumidity(rawH) - return + humidity := d.calculateHumidity(rawH) + return humidity, nil } func (d *BME280Driver) initializationBME280() error { diff --git a/drivers/i2c/bme280_driver_test.go b/drivers/i2c/bme280_driver_test.go index daf393528..f89e45be2 100644 --- a/drivers/i2c/bme280_driver_test.go +++ b/drivers/i2c/bme280_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -57,15 +58,18 @@ func TestBME280Measurements(t *testing.T) { adaptor.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) // Values produced by dumping data from actual sensor - if adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00 { - buf.Write([]byte{126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH1 { + switch { + case adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00: + buf.Write([]byte{ + 126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16, + }) + case adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH1: buf.Write([]byte{75}) - } else if adaptor.written[len(adaptor.written)-1] == bmp280RegTempData { + case adaptor.written[len(adaptor.written)-1] == bmp280RegTempData: buf.Write([]byte{129, 0, 0}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH2LSB { + case adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH2LSB: buf.Write([]byte{112, 1, 0, 19, 1, 0, 30}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegHumidityMSB { + case adaptor.written[len(adaptor.written)-1] == bme280RegHumidityMSB: buf.Write([]byte{111, 83}) } copy(b, buf.Bytes()) @@ -82,11 +86,14 @@ func TestBME280InitH1Error(t *testing.T) { adaptor.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) // Values produced by dumping data from actual sensor - if adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00 { - buf.Write([]byte{126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH1 { + switch { + case adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00: + buf.Write([]byte{ + 126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16, + }) + case adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH1: return 0, errors.New("h1 read error") - } else if adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH2LSB { + case adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH2LSB: buf.Write([]byte{112, 1, 0, 19, 1, 0, 30}) } copy(b, buf.Bytes()) @@ -101,11 +108,14 @@ func TestBME280InitH2Error(t *testing.T) { adaptor.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) // Values produced by dumping data from actual sensor - if adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00 { - buf.Write([]byte{126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH1 { + switch { + case adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00: + buf.Write([]byte{ + 126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16, + }) + case adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH1: buf.Write([]byte{75}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH2LSB { + case adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH2LSB: return 0, errors.New("h2 read error") } copy(b, buf.Bytes()) @@ -144,15 +154,18 @@ func TestBME280HumidityNotEnabled(t *testing.T) { adaptor.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) // Values produced by dumping data from actual sensor - if adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00 { - buf.Write([]byte{126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH1 { + switch { + case adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00: + buf.Write([]byte{ + 126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16, + }) + case adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH1: buf.Write([]byte{75}) - } else if adaptor.written[len(adaptor.written)-1] == bmp280RegTempData { + case adaptor.written[len(adaptor.written)-1] == bmp280RegTempData: buf.Write([]byte{129, 0, 0}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH2LSB { + case adaptor.written[len(adaptor.written)-1] == bme280RegCalibDigH2LSB: buf.Write([]byte{112, 1, 0, 19, 1, 0, 30}) - } else if adaptor.written[len(adaptor.written)-1] == bme280RegHumidityMSB { + case adaptor.written[len(adaptor.written)-1] == bme280RegHumidityMSB: buf.Write([]byte{0x80, 0x00}) } copy(b, buf.Bytes()) diff --git a/drivers/i2c/bmp180_driver.go b/drivers/i2c/bmp180_driver.go index a4cd1c085..176945605 100644 --- a/drivers/i2c/bmp180_driver.go +++ b/drivers/i2c/bmp180_driver.go @@ -95,28 +95,28 @@ func WithBMP180OversamplingMode(val BMP180OversamplingMode) func(Config) { } // Temperature returns the current temperature, in celsius degrees. -func (d *BMP180Driver) Temperature() (temp float32, err error) { +func (d *BMP180Driver) Temperature() (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - var rawTemp int16 - if rawTemp, err = d.rawTemp(); err != nil { + rawTemp, err := d.rawTemp() + if err != nil { return 0, err } return d.calculateTemp(rawTemp), nil } // Pressure returns the current pressure, in pascals. -func (d *BMP180Driver) Pressure() (pressure float32, err error) { +func (d *BMP180Driver) Pressure() (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - var rawTemp int16 - var rawPressure int32 - if rawTemp, err = d.rawTemp(); err != nil { + rawTemp, err := d.rawTemp() + if err != nil { return 0, err } - if rawPressure, err = d.rawPressure(d.oversampling); err != nil { + rawPressure, err := d.rawPressure(d.oversampling) + if err != nil { return 0, err } return d.calculatePressure(rawTemp, rawPressure, d.oversampling), nil @@ -192,20 +192,24 @@ func (d *BMP180Driver) calculateB5(rawTemp int16) int32 { return x1 + x2 } -func (d *BMP180Driver) rawPressure(oversampling BMP180OversamplingMode) (rawPressure int32, err error) { - if _, err = d.connection.Write([]byte{bmp180RegisterCtl, bmp180CtlPressure + byte(oversampling<<6)}); err != nil { +func (d *BMP180Driver) rawPressure(oversampling BMP180OversamplingMode) (int32, error) { + if _, err := d.connection.Write([]byte{bmp180RegisterCtl, bmp180CtlPressure + byte(oversampling<<6)}); err != nil { return 0, err } time.Sleep(bmp180PauseForReading(oversampling)) ret := make([]byte, 3) - if err = d.connection.ReadBlockData(bmp180RegisterDataMSB, ret); err != nil { + if err := d.connection.ReadBlockData(bmp180RegisterDataMSB, ret); err != nil { return 0, err } - rawPressure = (int32(ret[0])<<16 + int32(ret[1])<<8 + int32(ret[2])) >> (8 - uint(oversampling)) + rawPressure := (int32(ret[0])<<16 + int32(ret[1])<<8 + int32(ret[2])) >> (8 - uint(oversampling)) return rawPressure, nil } -func (d *BMP180Driver) calculatePressure(rawTemp int16, rawPressure int32, oversampling BMP180OversamplingMode) float32 { +func (d *BMP180Driver) calculatePressure( + rawTemp int16, + rawPressure int32, + oversampling BMP180OversamplingMode, +) float32 { b5 := d.calculateB5(rawTemp) b6 := b5 - 4000 x1 := (int32(d.calCoeffs.b2) * (b6 * b6 >> 12)) >> 11 diff --git a/drivers/i2c/bmp180_driver_test.go b/drivers/i2c/bmp180_driver_test.go index e70393718..374e42fd1 100644 --- a/drivers/i2c/bmp180_driver_test.go +++ b/drivers/i2c/bmp180_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -49,7 +50,8 @@ func TestBMP180Measurements(t *testing.T) { adaptor.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) // Values from the datasheet example. - if adaptor.written[len(adaptor.written)-1] == bmp180RegisterAC1MSB { + switch { + case adaptor.written[len(adaptor.written)-1] == bmp180RegisterAC1MSB: _ = binary.Write(buf, binary.BigEndian, int16(408)) _ = binary.Write(buf, binary.BigEndian, int16(-72)) _ = binary.Write(buf, binary.BigEndian, int16(-14383)) @@ -61,9 +63,11 @@ func TestBMP180Measurements(t *testing.T) { _ = binary.Write(buf, binary.BigEndian, int16(-32768)) _ = binary.Write(buf, binary.BigEndian, int16(-8711)) _ = binary.Write(buf, binary.BigEndian, int16(2868)) - } else if adaptor.written[len(adaptor.written)-2] == bmp180CtlTemp && adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB { + case adaptor.written[len(adaptor.written)-2] == bmp180CtlTemp && + adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB: _ = binary.Write(buf, binary.BigEndian, int16(27898)) - } else if adaptor.written[len(adaptor.written)-2] == bmp180CtlPressure && adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB { + case adaptor.written[len(adaptor.written)-2] == bmp180CtlPressure && + adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB: _ = binary.Write(buf, binary.BigEndian, int16(23843)) // XLSB, not used in this test. buf.WriteByte(0) @@ -85,7 +89,8 @@ func TestBMP180TemperatureError(t *testing.T) { adaptor.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) // Values from the datasheet example. - if adaptor.written[len(adaptor.written)-1] == bmp180RegisterAC1MSB { + switch { + case adaptor.written[len(adaptor.written)-1] == bmp180RegisterAC1MSB: _ = binary.Write(buf, binary.BigEndian, int16(408)) _ = binary.Write(buf, binary.BigEndian, int16(-72)) _ = binary.Write(buf, binary.BigEndian, int16(-14383)) @@ -97,9 +102,11 @@ func TestBMP180TemperatureError(t *testing.T) { _ = binary.Write(buf, binary.BigEndian, int16(-32768)) _ = binary.Write(buf, binary.BigEndian, int16(-8711)) _ = binary.Write(buf, binary.BigEndian, int16(2868)) - } else if adaptor.written[len(adaptor.written)-2] == bmp180CtlTemp && adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB { + case adaptor.written[len(adaptor.written)-2] == bmp180CtlTemp && + adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB: return 0, errors.New("temp error") - } else if adaptor.written[len(adaptor.written)-2] == bmp180CtlPressure && adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB { + case adaptor.written[len(adaptor.written)-2] == bmp180CtlPressure && + adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB: _ = binary.Write(buf, binary.BigEndian, int16(23843)) // XLSB, not used in this test. buf.WriteByte(0) @@ -117,7 +124,8 @@ func TestBMP180PressureError(t *testing.T) { adaptor.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) // Values from the datasheet example. - if adaptor.written[len(adaptor.written)-1] == bmp180RegisterAC1MSB { + switch { + case adaptor.written[len(adaptor.written)-1] == bmp180RegisterAC1MSB: _ = binary.Write(buf, binary.BigEndian, int16(408)) _ = binary.Write(buf, binary.BigEndian, int16(-72)) _ = binary.Write(buf, binary.BigEndian, int16(-14383)) @@ -129,9 +137,11 @@ func TestBMP180PressureError(t *testing.T) { _ = binary.Write(buf, binary.BigEndian, int16(-32768)) _ = binary.Write(buf, binary.BigEndian, int16(-8711)) _ = binary.Write(buf, binary.BigEndian, int16(2868)) - } else if adaptor.written[len(adaptor.written)-2] == bmp180CtlTemp && adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB { + case adaptor.written[len(adaptor.written)-2] == bmp180CtlTemp && + adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB: _ = binary.Write(buf, binary.BigEndian, int16(27898)) - } else if adaptor.written[len(adaptor.written)-2] == bmp180CtlPressure && adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB { + case adaptor.written[len(adaptor.written)-2] == bmp180CtlPressure && + adaptor.written[len(adaptor.written)-1] == bmp180RegisterDataMSB: return 0, errors.New("press error") } copy(b, buf.Bytes()) diff --git a/drivers/i2c/bmp280_driver.go b/drivers/i2c/bmp280_driver.go index ebf5207d0..a57c97674 100644 --- a/drivers/i2c/bmp280_driver.go +++ b/drivers/i2c/bmp280_driver.go @@ -161,29 +161,30 @@ func WithBMP280IIRFilter(val BMP280IIRFilter) func(Config) { } // Temperature returns the current temperature, in celsius degrees. -func (d *BMP280Driver) Temperature() (temp float32, err error) { +func (d *BMP280Driver) Temperature() (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - var rawT int32 - if rawT, err = d.rawTemp(); err != nil { + rawT, err := d.rawTemp() + if err != nil { return 0.0, err } - temp, _ = d.calculateTemp(rawT) - return + temp, _ := d.calculateTemp(rawT) + return temp, nil } // Pressure returns the current barometric pressure, in Pa -func (d *BMP280Driver) Pressure() (press float32, err error) { +func (d *BMP280Driver) Pressure() (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - var rawT, rawP int32 - if rawT, err = d.rawTemp(); err != nil { + rawT, err := d.rawTemp() + if err != nil { return 0.0, err } - if rawP, err = d.rawPressure(); err != nil { + rawP, err := d.rawPressure() + if err != nil { return 0.0, err } _, tFine := d.calculateTemp(rawT) @@ -195,12 +196,15 @@ func (d *BMP280Driver) Pressure() (press float32, err error) { // Calculation is based on code from Adafruit BME280 library // // https://github.com/adafruit/Adafruit_BME280_Library -func (d *BMP280Driver) Altitude() (alt float32, err error) { - atmP, _ := d.Pressure() +func (d *BMP280Driver) Altitude() (float32, error) { + atmP, err := d.Pressure() + if err != nil { + return 0, err + } atmP /= 100.0 - alt = float32(44330.0 * (1.0 - math.Pow(float64(atmP/bmp280SeaLevelPressure), 0.1903))) + alt := float32(44330.0 * (1.0 - math.Pow(float64(atmP/bmp280SeaLevelPressure), 0.1903))) - return + return alt, nil } // initialization reads the calibration coefficients. @@ -300,7 +304,8 @@ func (d *BMP280Driver) rawPressure() (int32, error) { func (d *BMP280Driver) calculateTemp(rawTemp int32) (float32, int32) { tcvar1 := ((float32(rawTemp) / 16384.0) - (float32(d.calCoeffs.t1) / 1024.0)) * float32(d.calCoeffs.t2) - tcvar2 := (((float32(rawTemp) / 131072.0) - (float32(d.calCoeffs.t1) / 8192.0)) * ((float32(rawTemp) / 131072.0) - float32(d.calCoeffs.t1)/8192.0)) * float32(d.calCoeffs.t3) + tcvar2 := (((float32(rawTemp) / 131072.0) - (float32(d.calCoeffs.t1) / 8192.0)) * ((float32(rawTemp) / 131072.0) - + float32(d.calCoeffs.t1)/8192.0)) * float32(d.calCoeffs.t3) temperatureComp := (tcvar1 + tcvar2) / 5120.0 tFine := int32(tcvar1 + tcvar2) diff --git a/drivers/i2c/bmp280_driver_test.go b/drivers/i2c/bmp280_driver_test.go index 04ae5e4d2..17bdec308 100644 --- a/drivers/i2c/bmp280_driver_test.go +++ b/drivers/i2c/bmp280_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -77,11 +78,14 @@ func TestBMP280Measurements(t *testing.T) { adaptor.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) // Values produced by dumping data from actual sensor - if adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00 { - buf.Write([]byte{126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16}) - } else if adaptor.written[len(adaptor.written)-1] == bmp280RegTempData { + switch { + case adaptor.written[len(adaptor.written)-1] == bmp280RegCalib00: + buf.Write([]byte{ + 126, 109, 214, 102, 50, 0, 54, 149, 220, 213, 208, 11, 64, 30, 166, 255, 249, 255, 172, 38, 10, 216, 189, 16, + }) + case adaptor.written[len(adaptor.written)-1] == bmp280RegTempData: buf.Write([]byte{128, 243, 0}) - } else if adaptor.written[len(adaptor.written)-1] == bmp280RegPressureData { + case adaptor.written[len(adaptor.written)-1] == bmp280RegPressureData: buf.Write([]byte{77, 23, 48}) } copy(b, buf.Bytes()) diff --git a/drivers/i2c/bmp388_driver.go b/drivers/i2c/bmp388_driver.go index a5dda145a..90e1fc9bc 100644 --- a/drivers/i2c/bmp388_driver.go +++ b/drivers/i2c/bmp388_driver.go @@ -63,7 +63,7 @@ const ( bmp388CMDReserved = 0x00 // reserved, no command bmp388CMDExtModeEnMiddle = 0x34 bmp388CMDFifoFlush = 0xB0 // clears all data in the FIFO, does not change FIFO_CONFIG registers - bmp388CMDSoftReset = 0xB6 // triggers a reset, all user configuration settings are overwritten with their default state + bmp388CMDSoftReset = 0xB6 // triggers a reset, all user configuration settings are overwritten with defaults bmp388SeaLevelPressure = 1013.25 ) @@ -132,66 +132,71 @@ func WithBMP388IIRFilter(val BMP388IIRFilter) func(Config) { } // Temperature returns the current temperature, in celsius degrees. -func (d *BMP388Driver) Temperature(accuracy BMP388Accuracy) (temp float32, err error) { +func (d *BMP388Driver) Temperature(accuracy BMP388Accuracy) (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - var rawT int32 - mode := d.ctrlPwrMode<<4 | bmp388PWRCTRLPressEnableBit | bmp388PWRCTRLTempEnableBit - if err = d.connection.WriteByteData(bmp388RegPWRCTRL, mode); err != nil { + if err := d.connection.WriteByteData(bmp388RegPWRCTRL, mode); err != nil { return 0, err } // Set Accuracy for temperature - if err = d.connection.WriteByteData(bmp388RegOSR, uint8(accuracy<<3)); err != nil { + if err := d.connection.WriteByteData(bmp388RegOSR, uint8(accuracy<<3)); err != nil { return 0, err } - if rawT, err = d.rawTemp(); err != nil { + rawT, err := d.rawTemp() + if err != nil { return 0.0, err } - temp = d.calculateTemp(rawT) - return + + temp := d.calculateTemp(rawT) + + return temp, nil } // Pressure returns the current barometric pressure, in Pa -func (d *BMP388Driver) Pressure(accuracy BMP388Accuracy) (press float32, err error) { +func (d *BMP388Driver) Pressure(accuracy BMP388Accuracy) (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - var rawT, rawP int32 - mode := d.ctrlPwrMode<<4 | bmp388PWRCTRLPressEnableBit | bmp388PWRCTRLTempEnableBit - if err = d.connection.WriteByteData(bmp388RegPWRCTRL, mode); err != nil { + if err := d.connection.WriteByteData(bmp388RegPWRCTRL, mode); err != nil { return 0, err } // Set Standard Accuracy for pressure - if err = d.connection.WriteByteData(bmp388RegOSR, uint8(accuracy)); err != nil { + if err := d.connection.WriteByteData(bmp388RegOSR, uint8(accuracy)); err != nil { return 0, err } - if rawT, err = d.rawTemp(); err != nil { + rawT, err := d.rawTemp() + if err != nil { return 0.0, err } - if rawP, err = d.rawPressure(); err != nil { + rawP, err := d.rawPressure() + if err != nil { return 0.0, err } tLin := d.calculateTemp(rawT) + return d.calculatePress(rawP, float64(tLin)), nil } // Altitude returns the current altitude in meters based on the // current barometric pressure and estimated pressure at sea level. // https://www.weather.gov/media/epz/wxcalc/pressureAltitude.pdf -func (d *BMP388Driver) Altitude(accuracy BMP388Accuracy) (alt float32, err error) { - atmP, _ := d.Pressure(accuracy) +func (d *BMP388Driver) Altitude(accuracy BMP388Accuracy) (float32, error) { + atmP, err := d.Pressure(accuracy) + if err != nil { + return 0, err + } atmP /= 100.0 - alt = float32(44307.0 * (1.0 - math.Pow(float64(atmP/bmp388SeaLevelPressure), 0.190284))) + alt := float32(44307.0 * (1.0 - math.Pow(float64(atmP/bmp388SeaLevelPressure), 0.190284))) - return + return alt, nil } // initialization reads the calibration coefficients. diff --git a/drivers/i2c/bmp388_driver_test.go b/drivers/i2c/bmp388_driver_test.go index ea2b25a14..41fb6cb79 100644 --- a/drivers/i2c/bmp388_driver_test.go +++ b/drivers/i2c/bmp388_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -73,7 +74,9 @@ func TestBMP388Measurements(t *testing.T) { _ = binary.Write(buf, binary.LittleEndian, uint8(0x50)) case bmp388RegCalib00: // Values produced by dumping data from actual sensor - buf.Write([]byte{36, 107, 156, 73, 246, 104, 255, 189, 245, 35, 0, 151, 101, 184, 122, 243, 246, 211, 64, 14, 196, 0, 0, 0}) + buf.Write([]byte{ + 36, 107, 156, 73, 246, 104, 255, 189, 245, 35, 0, 151, 101, 184, 122, 243, 246, 211, 64, 14, 196, 0, 0, 0, + }) case bmp388RegTempData: buf.Write([]byte{0, 28, 127}) case bmp388RegPressureData: @@ -163,7 +166,9 @@ func TestBMP388_initialization(t *testing.T) { wantConfRegVal = uint8(0x00) // no filter ) // Values produced by dumping data from actual sensor - returnRead := []byte{36, 107, 156, 73, 246, 104, 255, 189, 245, 35, 0, 151, 101, 184, 122, 243, 246, 211, 64, 14, 196, 0, 0, 0} + returnRead := []byte{ + 36, 107, 156, 73, 246, 104, 255, 189, 245, 35, 0, 151, 101, 184, 122, 243, 246, 211, 64, 14, 196, 0, 0, 0, + } numCallsRead := 0 a.i2cReadImpl = func(b []byte) (int, error) { numCallsRead++ diff --git a/drivers/i2c/ccs811_driver.go b/drivers/i2c/ccs811_driver.go index 8434d770d..c55c8e3d5 100644 --- a/drivers/i2c/ccs811_driver.go +++ b/drivers/i2c/ccs811_driver.go @@ -9,7 +9,8 @@ import ( // CCS811DriveMode type type CCS811DriveMode uint8 -// Operating modes which dictate how often measurements are being made. If 0x00 is used as an operating mode, measurements will be disabled +// Operating modes which dictate how often measurements are being made. If 0x00 is used as an operating mode, +// measurements will be disabled const ( CCS811DriveModeIdle CCS811DriveMode = 0x00 CCS811DriveMode1Sec CCS811DriveMode = 0x01 @@ -24,11 +25,13 @@ const ( ccs811DefaultAddress = 0x5A // Registers, all definitions have been taken from the datasheet - // Single byte read only register which indicates if a device is active, if new data is available or if an error occurred. + // Single byte read only register which indicates if a device is active, if new data is available or if an error + // occurred. ccs811RegStatus = 0x00 // This is Single byte register, which is used to enable sensor drive mode and interrupts. ccs811RegMeasMode = 0x01 - // This multi-byte read only register contains the calculated eCO2 (ppm) and eTVOC (ppb) values followed by the STATUS register, ERROR_ID register and the RAW_DATA register. + // This multi-byte read only register contains the calculated eCO2 (ppm) and eTVOC (ppb) values followed by the + // STATUS register, ERROR_ID register and the RAW_DATA register. ccs811RegAlgResultData = 0x02 // Two byte read only register which contains the latest readings from the sensor. // ccs811RegRawData = 0x03 @@ -42,11 +45,14 @@ const ( ccs811RegHwID = 0x20 // Single byte read only register that contains the hardware version. The value is 0x1X ccs811RegHwVersion = 0x21 - // Two byte read only register which contain the version of the firmware bootloader stored in the CCS811 in the format Major.Minor.Trivial + // Two byte read only register which contain the version of the firmware bootloader stored in the CCS811 in the + // format Major.Minor.Trivial ccs811RegFwBootVersion = 0x23 - // Two byte read only register which contain the version of the firmware application stored in the CCS811 in the format Major.Minor.Trivial + // Two byte read only register which contain the version of the firmware application stored in the CCS811 in the + // format Major.Minor.Trivial ccs811RegFwAppVersion = 0x24 - // To change the mode of the CCS811 from Boot mode to running the application, a single byte write of 0xF4 is required. + // To change the mode of the CCS811 from Boot mode to running the application, a single byte write of 0xF4 + // is required. ccs811RegAppStart = 0xF4 // Constants @@ -58,7 +64,8 @@ const ( var ccs811SwResetSequence = []byte{0x11, 0xE5, 0x72, 0x8A} // CCS811Status represents the current status of the device defined by the ccs811RegStatus. -// The following definitions were taken from https://ams.com/documents/20143/36005/CCS811_DS000459_6-00.pdf/c7091525-c7e5-37ac-eedb-b6c6828b0dcf#page=15 +// The following definitions were taken from +// https://ams.com/documents/20143/36005/CCS811_DS000459_6-00.pdf/c7091525-c7e5-37ac-eedb-b6c6828b0dcf#page=15 type CCS811Status struct { // There is some sort of error on the i2c bus or there is an error with the internal sensor HasError byte @@ -93,7 +100,7 @@ type CCS811MeasMode struct { driveMode CCS811DriveMode } -// NewCCS811MeasMode returns a new instance of the package ccs811 measurement mode configuration. This represents the desired initial +// NewCCS811MeasMode returns a new instance of the measurement mode configuration. This represents the desired initial // state of the measurement mode register. func NewCCS811MeasMode() *CCS811MeasMode { return &CCS811MeasMode{ @@ -240,7 +247,8 @@ func (d *CCS811Driver) GetGasData() (uint16, uint16, error) { return 0, 0, err } - // Bit masks defined by https://ams.com/documents/20143/36005/CCS811_AN000369_2-00.pdf/25d0db9a-92b9-fa7f-362c-a7a4d1e292be#page=14 + // Bit masks defined by + // https://ams.com/documents/20143/36005/CCS811_AN000369_2-00.pdf/25d0db9a-92b9-fa7f-362c-a7a4d1e292be#page=14 eco2 := (uint16(data[0]) << 8) | uint16(data[1]) tvoC := (uint16(data[2]) << 8) | uint16(data[3]) diff --git a/drivers/i2c/ccs811_driver_test.go b/drivers/i2c/ccs811_driver_test.go index f8abcb746..d205a19b3 100644 --- a/drivers/i2c/ccs811_driver_test.go +++ b/drivers/i2c/ccs811_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/drv2605l_driver.go b/drivers/i2c/drv2605l_driver.go index 5adbbaf17..a29995bc6 100644 --- a/drivers/i2c/drv2605l_driver.go +++ b/drivers/i2c/drv2605l_driver.go @@ -98,7 +98,7 @@ func NewDRV2605LDriver(c Connector, options ...func(Config)) *DRV2605LDriver { // SetMode sets the device in one of the eight modes as described in the // datasheet. Defaults to mode 0, internal trig. -func (d *DRV2605LDriver) SetMode(newMode DRV2605Mode) (err error) { +func (d *DRV2605LDriver) SetMode(newMode DRV2605Mode) error { mode, err := d.connection.ReadByteData(drv2605RegMode) if err != nil { return err @@ -115,7 +115,7 @@ func (d *DRV2605LDriver) SetMode(newMode DRV2605Mode) (err error) { } // SetStandbyMode controls device low power mode -func (d *DRV2605LDriver) SetStandbyMode(standby bool) (err error) { +func (d *DRV2605LDriver) SetStandbyMode(standby bool) error { modeVal, err := d.connection.ReadByteData(drv2605RegMode) if err != nil { return err @@ -133,16 +133,15 @@ func (d *DRV2605LDriver) SetStandbyMode(standby bool) (err error) { // SelectLibrary selects which waveform library to play from, 1-7. // See datasheet for more info. -func (d *DRV2605LDriver) SelectLibrary(library uint8) (err error) { - err = d.connection.WriteByteData(drv2605RegLibrary, library&0x7) - return err +func (d *DRV2605LDriver) SelectLibrary(library uint8) error { + return d.connection.WriteByteData(drv2605RegLibrary, library&0x7) } // GetPauseWaveform returns a special waveform ID used in SetSequence() to encode // pauses between waveforms. Time is specified in tens of milliseconds // ranging from 0ms (delayTime10MS = 0) to 1270ms (delayTime10MS = 127). // Times out of range are clipped to fit. -func (d *DRV2605LDriver) GetPauseWaveform(delayTime10MS uint8) (pauseID uint8) { +func (d *DRV2605LDriver) GetPauseWaveform(delayTime10MS uint8) uint8 { if delayTime10MS > 127 { delayTime10MS = 127 } @@ -156,7 +155,7 @@ func (d *DRV2605LDriver) GetPauseWaveform(delayTime10MS uint8) (pauseID uint8) { // sequences will be truncated. // A waveform id of zero marks the end of the sequence. // Pauses can be encoded using GetPauseWaveform(). -func (d *DRV2605LDriver) SetSequence(waveforms []uint8) (err error) { +func (d *DRV2605LDriver) SetSequence(waveforms []uint8) error { if len(waveforms) < 8 { waveforms = append(waveforms, 0) } @@ -164,26 +163,26 @@ func (d *DRV2605LDriver) SetSequence(waveforms []uint8) (err error) { waveforms = waveforms[0:8] } for i, w := range waveforms { - if err = d.connection.WriteByteData(uint8(drv2605RegWaveSeq1+i), w); err != nil { + if err := d.connection.WriteByteData(uint8(drv2605RegWaveSeq1+i), w); err != nil { return err } } + return nil } // Go plays the current sequence of waveforms. -func (d *DRV2605LDriver) Go() (err error) { - err = d.connection.WriteByteData(drv2605RegGo, 1) - return err +func (d *DRV2605LDriver) Go() error { + return d.connection.WriteByteData(drv2605RegGo, 1) } -func (d *DRV2605LDriver) writeByteRegisters(regValPairs []struct{ reg, val uint8 }) (err error) { +func (d *DRV2605LDriver) writeByteRegisters(regValPairs []struct{ reg, val uint8 }) error { for _, rv := range regValPairs { - if err = d.connection.WriteByteData(rv.reg, rv.val); err != nil { - break + if err := d.connection.WriteByteData(rv.reg, rv.val); err != nil { + return err } } - return err + return nil } func (d *DRV2605LDriver) initialize() error { @@ -215,15 +214,16 @@ func (d *DRV2605LDriver) initialize() error { }) } -func (d *DRV2605LDriver) shutdown() (err error) { +func (d *DRV2605LDriver) shutdown() error { if d.connection != nil { // stop playback - if err = d.connection.WriteByteData(drv2605RegGo, 0); err != nil { + if err := d.connection.WriteByteData(drv2605RegGo, 0); err != nil { return err } // enter standby return d.SetStandbyMode(true) } - return + + return nil } diff --git a/drivers/i2c/drv2605l_driver_test.go b/drivers/i2c/drv2605l_driver_test.go index e8295db7b..0c9b6b54b 100644 --- a/drivers/i2c/drv2605l_driver_test.go +++ b/drivers/i2c/drv2605l_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -64,7 +65,8 @@ func TestDRV2605LHalt(t *testing.T) { d, a := initTestDRV2605LDriverWithStubbedAdaptor() a.written = []byte{} require.NoError(t, d.Halt()) - assert.Equal(t, append(append(writeStopPlaybackData, readCurrentStandbyModeData), writeNewStandbyModeData...), a.written) + assert.Equal(t, append(append(writeStopPlaybackData, readCurrentStandbyModeData), writeNewStandbyModeData...), + a.written) } func TestDRV2605LGetPause(t *testing.T) { diff --git a/drivers/i2c/generic_driver_test.go b/drivers/i2c/generic_driver_test.go index fdb490e69..e522b216d 100644 --- a/drivers/i2c/generic_driver_test.go +++ b/drivers/i2c/generic_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/grove_drivers_test.go b/drivers/i2c/grove_drivers_test.go index 19f755897..7da5d5872 100644 --- a/drivers/i2c/grove_drivers_test.go +++ b/drivers/i2c/grove_drivers_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) @@ -13,9 +14,9 @@ var ( _ gobot.Driver = (*GroveAccelerometerDriver)(nil) ) -func initTestGroveLcdDriver() (driver *GroveLcdDriver) { - driver, _ = initGroveLcdDriverWithStubbedAdaptor() - return +func initTestGroveLcdDriver() *GroveLcdDriver { + d, _ := initGroveLcdDriverWithStubbedAdaptor() + return d } func initGroveLcdDriverWithStubbedAdaptor() (*GroveLcdDriver, *i2cTestAdaptor) { @@ -23,9 +24,9 @@ func initGroveLcdDriverWithStubbedAdaptor() (*GroveLcdDriver, *i2cTestAdaptor) { return NewGroveLcdDriver(adaptor), adaptor } -func initTestGroveAccelerometerDriver() (driver *GroveAccelerometerDriver) { - driver, _ = initGroveAccelerometerDriverWithStubbedAdaptor() - return +func initTestGroveAccelerometerDriver() *GroveAccelerometerDriver { + d, _ := initGroveAccelerometerDriverWithStubbedAdaptor() + return d } func initGroveAccelerometerDriverWithStubbedAdaptor() (*GroveAccelerometerDriver, *i2cTestAdaptor) { diff --git a/drivers/i2c/grovepi_driver.go b/drivers/i2c/grovepi_driver.go index bc5a799a4..204ba51e0 100644 --- a/drivers/i2c/grovepi_driver.go +++ b/drivers/i2c/grovepi_driver.go @@ -70,7 +70,7 @@ func (d *GrovePiDriver) Finalize() error { } // AnalogRead returns value from analog pin implementing the AnalogReader interface. -func (d *GrovePiDriver) AnalogRead(pin string) (value int, err error) { +func (d *GrovePiDriver) AnalogRead(pin string) (int, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -171,6 +171,8 @@ func (d *GrovePiDriver) FirmwareVersionRead() (string, error) { // DHTRead performs a read temperature and humidity sensors with duration >=2 millisecond. // DHT11 (blue): sensorType=0 // DHT22 (white): sensorTyp=1 +// +//nolint:nonamedreturns // is sufficient here func (d *GrovePiDriver) DHTRead(pin string, sensorType byte, duration int) (temp float32, hum float32, err error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -186,13 +188,13 @@ func (d *GrovePiDriver) DHTRead(pin string, sensorType byte, duration int) (temp buf := []byte{commandReadDHT, byte(pinNum), sensorType, 0} if _, err = d.connection.Write(buf); err != nil { - return + return 0, 0, err } time.Sleep(time.Duration(duration) * time.Millisecond) data := make([]byte, 9) if err = d.readForCommand(commandReadDHT, data); err != nil { - return + return 0, 0, err } temp = float32Of4BytesLittleEndian(data[1:5]) @@ -211,7 +213,7 @@ func (d *GrovePiDriver) DHTRead(pin string, sensorType byte, duration int) (temp hum = 0 } - return + return temp, hum, err } // DigitalWrite writes a value to a specific digital pin implementing the DigitalWriter interface. diff --git a/drivers/i2c/grovepi_driver_test.go b/drivers/i2c/grovepi_driver_test.go index cd6ed5682..ae8a1b97b 100644 --- a/drivers/i2c/grovepi_driver_test.go +++ b/drivers/i2c/grovepi_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" @@ -142,7 +143,7 @@ func TestGrovePiSomeRead(t *testing.T) { _ = g.Start() a.written = []byte{} // reset writes of former test and start numCallsRead := 0 - a.i2cReadImpl = func(bytes []byte) (i int, e error) { + a.i2cReadImpl = func(bytes []byte) (int, error) { numCallsRead++ copy(bytes, tc.simResponse[numCallsRead-1]) return len(tc.simResponse[numCallsRead-1]), nil @@ -205,7 +206,7 @@ func TestGrovePiSomeWrite(t *testing.T) { g, a := initGrovePiDriverWithStubbedAdaptor() _ = g.Start() a.written = []byte{} // reset writes of former test and start - a.i2cReadImpl = func(bytes []byte) (i int, e error) { + a.i2cReadImpl = func(bytes []byte) (int, error) { copy(bytes, tc.simResponse) return len(bytes), nil } diff --git a/drivers/i2c/helpers_test.go b/drivers/i2c/helpers_test.go index b4378cac7..0a043d744 100644 --- a/drivers/i2c/helpers_test.go +++ b/drivers/i2c/helpers_test.go @@ -41,13 +41,13 @@ func (t *i2cTestAdaptor) Testi2cWriteImpl(f func([]byte) (int, error)) { t.i2cWriteImpl = f } -func (t *i2cTestAdaptor) Read(b []byte) (count int, err error) { +func (t *i2cTestAdaptor) Read(b []byte) (int, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.i2cReadImpl(b) } -func (t *i2cTestAdaptor) Write(b []byte) (count int, err error) { +func (t *i2cTestAdaptor) Write(b []byte) (int, error) { t.mtx.Lock() defer t.mtx.Unlock() t.written = append(t.written, b...) @@ -58,36 +58,36 @@ func (t *i2cTestAdaptor) Close() error { return nil } -func (t *i2cTestAdaptor) ReadByte() (val byte, err error) { +func (t *i2cTestAdaptor) ReadByte() (byte, error) { t.mtx.Lock() defer t.mtx.Unlock() bytes := []byte{0} - if err = t.readBytes(bytes); err != nil { - return + if err := t.readBytes(bytes); err != nil { + return 0, err } - val = bytes[0] - return + val := bytes[0] + return val, nil } -func (t *i2cTestAdaptor) ReadByteData(reg uint8) (val uint8, err error) { +func (t *i2cTestAdaptor) ReadByteData(reg uint8) (uint8, error) { t.mtx.Lock() defer t.mtx.Unlock() - if err = t.writeBytes([]byte{reg}); err != nil { - return + if err := t.writeBytes([]byte{reg}); err != nil { + return 0, err } bytes := []byte{0} - if err = t.readBytes(bytes); err != nil { - return + if err := t.readBytes(bytes); err != nil { + return 0, err } - val = bytes[0] - return + val := bytes[0] + return val, nil } -func (t *i2cTestAdaptor) ReadWordData(reg uint8) (val uint16, err error) { +func (t *i2cTestAdaptor) ReadWordData(reg uint8) (uint16, error) { t.mtx.Lock() defer t.mtx.Unlock() - if err = t.writeBytes([]byte{reg}); err != nil { - return + if err := t.writeBytes([]byte{reg}); err != nil { + return 0, err } bytes := []byte{0, 0} bytesRead, err := t.i2cReadImpl(bytes) @@ -98,14 +98,14 @@ func (t *i2cTestAdaptor) ReadWordData(reg uint8) (val uint16, err error) { return 0, fmt.Errorf("Buffer underrun") } low, high := bytes[0], bytes[1] - return (uint16(high) << 8) | uint16(low), err + return (uint16(high) << 8) | uint16(low), nil } -func (t *i2cTestAdaptor) ReadBlockData(reg uint8, b []byte) (err error) { +func (t *i2cTestAdaptor) ReadBlockData(reg uint8, b []byte) error { t.mtx.Lock() defer t.mtx.Unlock() - if err = t.writeBytes([]byte{reg}); err != nil { - return + if err := t.writeBytes([]byte{reg}); err != nil { + return err } return t.readBytes(b) } @@ -116,7 +116,7 @@ func (t *i2cTestAdaptor) WriteByte(val byte) error { return t.writeBytes([]byte{val}) } -func (t *i2cTestAdaptor) WriteByteData(reg uint8, val uint8) (err error) { +func (t *i2cTestAdaptor) WriteByteData(reg uint8, val uint8) error { t.mtx.Lock() defer t.mtx.Unlock() bytes := []byte{reg, val} @@ -156,7 +156,7 @@ func (t *i2cTestAdaptor) WriteBytes(b []byte) error { return t.writeBytes(b) } -func (t *i2cTestAdaptor) GetI2cConnection(address int, bus int) (connection Connection, err error) { +func (t *i2cTestAdaptor) GetI2cConnection(address int, bus int) (Connection, error) { if t.i2cConnectErr { return nil, errors.New("Invalid i2c connection") } @@ -169,10 +169,10 @@ func (t *i2cTestAdaptor) DefaultI2cBus() int { return 0 } -func (t *i2cTestAdaptor) Name() string { return t.name } -func (t *i2cTestAdaptor) SetName(n string) { t.name = n } -func (t *i2cTestAdaptor) Connect() (err error) { return } -func (t *i2cTestAdaptor) Finalize() (err error) { return } +func (t *i2cTestAdaptor) Name() string { return t.name } +func (t *i2cTestAdaptor) SetName(n string) { t.name = n } +func (t *i2cTestAdaptor) Connect() error { return nil } +func (t *i2cTestAdaptor) Finalize() error { return nil } func newI2cTestAdaptor() *i2cTestAdaptor { return &i2cTestAdaptor{ diff --git a/drivers/i2c/hmc5883l_driver.go b/drivers/i2c/hmc5883l_driver.go index 395ab8431..c43f212ca 100644 --- a/drivers/i2c/hmc5883l_driver.go +++ b/drivers/i2c/hmc5883l_driver.go @@ -203,6 +203,8 @@ func WithHMC5883LGain(val int) func(Config) { } // Read reads the values X, Y, Z in Gauss +// +//nolint:nonamedreturns // is sufficient here func (h *HMC5883LDriver) Read() (x float64, y float64, z float64, err error) { h.mutex.Lock() defer h.mutex.Unlock() @@ -215,26 +217,27 @@ func (h *HMC5883LDriver) Read() (x float64, y float64, z float64, err error) { } // Heading returns the current heading in radians -func (h *HMC5883LDriver) Heading() (heading float64, err error) { +func (h *HMC5883LDriver) Heading() (float64, error) { h.mutex.Lock() defer h.mutex.Unlock() - var x, y int16 - x, y, _, err = h.readRawData() + x, y, _, err := h.readRawData() if err != nil { - return + return 0, err } - heading = math.Atan2(float64(y), float64(x)) + heading := math.Atan2(float64(y), float64(x)) if heading > 2*math.Pi { heading -= 2 * math.Pi } if heading < 0 { heading += 2 * math.Pi } - return + return heading, nil } // readRawData reads the raw values from the X, Y, and Z registers +// +//nolint:nonamedreturns // sufficient here func (h *HMC5883LDriver) readRawData() (x int16, y int16, z int16, err error) { // read the data, starting from the initial register data := make([]byte, 6) @@ -249,7 +252,7 @@ func (h *HMC5883LDriver) readRawData() (x int16, y int16, z int16, err error) { return twosComplement16Bit(unsignedX), twosComplement16Bit(unsignedY), twosComplement16Bit(unsignedZ), nil } -func (h *HMC5883LDriver) initialize() (err error) { +func (h *HMC5883LDriver) initialize() error { regA := hmc5883lMeasurementFlowBits[h.applyBias] regA |= hmc5883lOutputRateBits[h.outputRate] << 2 regA |= hmc5883lSamplesAvgBits[h.samplesAvg] << 5 @@ -260,15 +263,13 @@ func (h *HMC5883LDriver) initialize() (err error) { if err := h.connection.WriteByteData(hmc5883lRegB, uint8(regB)); err != nil { return err } - if err := h.connection.WriteByteData(hmc5883lRegMode, uint8(h.measurementMode)); err != nil { - return err - } - return + + return h.connection.WriteByteData(hmc5883lRegMode, uint8(h.measurementMode)) } -func hmc5883lValidateSamplesAveraged(samplesAvg int) (err error) { +func hmc5883lValidateSamplesAveraged(samplesAvg int) error { if _, ok := hmc5883lSamplesAvgBits[uint8(samplesAvg)]; ok { - return + return nil } keys := []int{} @@ -276,13 +277,13 @@ func hmc5883lValidateSamplesAveraged(samplesAvg int) (err error) { keys = append(keys, int(k)) } sort.Ints(keys) - err = fmt.Errorf("Samples averaged must be one of: %d", keys) - return + + return fmt.Errorf("Samples averaged must be one of: %d", keys) } -func hmc5883lValidateOutputRate(outputRate int) (err error) { +func hmc5883lValidateOutputRate(outputRate int) error { if _, ok := hmc5883lOutputRateBits[uint32(outputRate)]; ok { - return + return nil } keys := []int{} @@ -290,13 +291,13 @@ func hmc5883lValidateOutputRate(outputRate int) (err error) { keys = append(keys, int(k)) } sort.Ints(keys) - err = fmt.Errorf("Data output rate must be one of: %d", keys) - return + + return fmt.Errorf("Data output rate must be one of: %d", keys) } -func hmc5883lValidateApplyBias(applyBias int) (err error) { +func hmc5883lValidateApplyBias(applyBias int) error { if _, ok := hmc5883lMeasurementFlowBits[int8(applyBias)]; ok { - return + return nil } keys := []int{} @@ -304,13 +305,13 @@ func hmc5883lValidateApplyBias(applyBias int) (err error) { keys = append(keys, int(k)) } sort.Ints(keys) - err = fmt.Errorf("Apply measurement bias must be one of: %d", keys) - return + + return fmt.Errorf("Apply measurement bias must be one of: %d", keys) } -func hmc5883lValidateGain(gain int) (err error) { +func hmc5883lValidateGain(gain int) error { if _, ok := hmc5883lGainBits[float64(gain)]; ok { - return + return nil } keys := []int{} @@ -318,6 +319,6 @@ func hmc5883lValidateGain(gain int) (err error) { keys = append(keys, int(k)) } sort.Ints(keys) - err = fmt.Errorf("Gain must be one of: %d", keys) - return + + return fmt.Errorf("Gain must be one of: %d", keys) } diff --git a/drivers/i2c/hmc5883l_driver_test.go b/drivers/i2c/hmc5883l_driver_test.go index b62ce07d8..1b512ff20 100644 --- a/drivers/i2c/hmc5883l_driver_test.go +++ b/drivers/i2c/hmc5883l_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/hmc6352_driver.go b/drivers/i2c/hmc6352_driver.go index 8dd8c43f3..d08ccc48a 100644 --- a/drivers/i2c/hmc6352_driver.go +++ b/drivers/i2c/hmc6352_driver.go @@ -30,22 +30,21 @@ func NewHMC6352Driver(c Connector, options ...func(Config)) *HMC6352Driver { } // Heading returns the current heading -func (h *HMC6352Driver) Heading() (heading uint16, err error) { - if _, err = h.connection.Write([]byte("A")); err != nil { - return +func (h *HMC6352Driver) Heading() (uint16, error) { + if _, err := h.connection.Write([]byte("A")); err != nil { + return 0, err } buf := []byte{0, 0} bytesRead, err := h.connection.Read(buf) if err != nil { - return + return 0, err } if bytesRead == 2 { - heading = (uint16(buf[1]) + uint16(buf[0])*256) / 10 - return + heading := (uint16(buf[1]) + uint16(buf[0])*256) / 10 + return heading, nil } - err = ErrNotEnoughBytes - return + return 0, ErrNotEnoughBytes } func (h *HMC6352Driver) initialize() error { diff --git a/drivers/i2c/hmc6352_driver_test.go b/drivers/i2c/hmc6352_driver_test.go index 908fb422b..770d1c446 100644 --- a/drivers/i2c/hmc6352_driver_test.go +++ b/drivers/i2c/hmc6352_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/i2c_config_test.go b/drivers/i2c/i2c_config_test.go index 7c9a2fbb2..28dc37eeb 100644 --- a/drivers/i2c/i2c_config_test.go +++ b/drivers/i2c/i2c_config_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package i2c import ( diff --git a/drivers/i2c/i2c_connection.go b/drivers/i2c/i2c_connection.go index 178b9eab2..3f402a8d3 100644 --- a/drivers/i2c/i2c_connection.go +++ b/drivers/i2c/i2c_connection.go @@ -46,17 +46,17 @@ type i2cConnection struct { } // NewConnection creates and returns a new connection to a specific i2c device on a bus and address. -func NewConnection(bus gobot.I2cSystemDevicer, address int) (connection *i2cConnection) { +func NewConnection(bus gobot.I2cSystemDevicer, address int) *i2cConnection { return &i2cConnection{bus: bus, address: address} } // Read data from an i2c device. -func (c *i2cConnection) Read(data []byte) (read int, err error) { +func (c *i2cConnection) Read(data []byte) (int, error) { return c.bus.Read(c.address, data) } // Write data to an i2c device. -func (c *i2cConnection) Write(data []byte) (written int, err error) { +func (c *i2cConnection) Write(data []byte) (int, error) { return c.bus.Write(c.address, data) } @@ -96,17 +96,17 @@ func (c *i2cConnection) WriteByteData(reg uint8, val uint8) error { } // WriteWordData writes a word value to a register on the i2c device. -func (c *i2cConnection) WriteWordData(reg uint8, val uint16) (err error) { +func (c *i2cConnection) WriteWordData(reg uint8, val uint16) error { return c.bus.WriteWordData(c.address, reg, val) } // WriteBlockData writes a block of bytes to a register on the i2c device. -func (c *i2cConnection) WriteBlockData(reg uint8, b []byte) (err error) { +func (c *i2cConnection) WriteBlockData(reg uint8, b []byte) error { return c.bus.WriteBlockData(c.address, reg, b) } // WriteBytes writes a block of bytes to the current register on the i2c device. -func (c *i2cConnection) WriteBytes(b []byte) (err error) { +func (c *i2cConnection) WriteBytes(b []byte) error { return c.bus.WriteBytes(c.address, b) } diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index d4ee56cc6..fdce313d2 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) @@ -21,6 +22,7 @@ func getSyscallFuncImpl( // bit 0: error on function query // bit 1: error on set address // bit 2: error on command + //nolint:nonamedreturns // is sufficient here return func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err system.SyscallErrno) { // function query if (trap == system.Syscall_SYS_IOCTL) && (a2 == system.I2C_FUNCS) { diff --git a/drivers/i2c/i2c_driver.go b/drivers/i2c/i2c_driver.go index 88c26ab79..296b1c0c7 100644 --- a/drivers/i2c/i2c_driver.go +++ b/drivers/i2c/i2c_driver.go @@ -3,6 +3,7 @@ package i2c import ( "encoding/binary" "fmt" + "log" "strconv" "sync" @@ -81,7 +82,12 @@ func (d *Driver) SetName(name string) { // Connection returns the connection of the i2c device. func (d *Driver) Connection() gobot.Connection { - return d.connector.(gobot.Connection) + if conn, ok := d.connector.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil } // Start initializes the i2c device. diff --git a/drivers/i2c/i2c_driver_test.go b/drivers/i2c/i2c_driver_test.go index 9dec4cecd..28abcb388 100644 --- a/drivers/i2c/i2c_driver_test.go +++ b/drivers/i2c/i2c_driver_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/ina3221_driver_test.go b/drivers/i2c/ina3221_driver_test.go index 51cee46e9..7914dc8e8 100644 --- a/drivers/i2c/ina3221_driver_test.go +++ b/drivers/i2c/ina3221_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/jhd1313m1_driver.go b/drivers/i2c/jhd1313m1_driver.go index 25649f77a..9d17818ec 100644 --- a/drivers/i2c/jhd1313m1_driver.go +++ b/drivers/i2c/jhd1313m1_driver.go @@ -2,6 +2,7 @@ package i2c import ( "fmt" + "log" "strconv" "time" @@ -93,7 +94,7 @@ type JHD1313M1Driver struct { // // i2c.WithBus(int): bus to use with this driver func NewJHD1313M1Driver(a Connector, options ...func(Config)) *JHD1313M1Driver { - j := &JHD1313M1Driver{ + d := &JHD1313M1Driver{ name: gobot.DefaultName("JHD1313M1"), connector: a, Config: NewConfig(), @@ -103,57 +104,63 @@ func NewJHD1313M1Driver(a Connector, options ...func(Config)) *JHD1313M1Driver { } for _, option := range options { - option(j) + option(d) } - j.AddCommand("SetRGB", func(params map[string]interface{}) interface{} { + d.AddCommand("SetRGB", func(params map[string]interface{}) interface{} { r, _ := strconv.Atoi(params["r"].(string)) g, _ := strconv.Atoi(params["g"].(string)) b, _ := strconv.Atoi(params["b"].(string)) - return j.SetRGB(r, g, b) + return d.SetRGB(r, g, b) }) - j.AddCommand("Clear", func(params map[string]interface{}) interface{} { - return j.Clear() + d.AddCommand("Clear", func(params map[string]interface{}) interface{} { + return d.Clear() }) - j.AddCommand("Home", func(params map[string]interface{}) interface{} { - return j.Home() + d.AddCommand("Home", func(params map[string]interface{}) interface{} { + return d.Home() }) - j.AddCommand("Write", func(params map[string]interface{}) interface{} { - msg := params["msg"].(string) - return j.Write(msg) + d.AddCommand("Write", func(params map[string]interface{}) interface{} { + msg := params["msg"].(string) //nolint:forcetypeassert // ok here + return d.Write(msg) }) - j.AddCommand("SetPosition", func(params map[string]interface{}) interface{} { + d.AddCommand("SetPosition", func(params map[string]interface{}) interface{} { pos, _ := strconv.Atoi(params["pos"].(string)) - return j.SetPosition(pos) + return d.SetPosition(pos) }) - j.AddCommand("Scroll", func(params map[string]interface{}) interface{} { + d.AddCommand("Scroll", func(params map[string]interface{}) interface{} { lr, _ := strconv.ParseBool(params["lr"].(string)) - return j.Scroll(lr) + return d.Scroll(lr) }) - return j + return d } // Name returns the name the JHD1313M1 Driver was given when created. -func (h *JHD1313M1Driver) Name() string { return h.name } +func (d *JHD1313M1Driver) Name() string { return d.name } // SetName sets the name for the JHD1313M1 Driver. -func (h *JHD1313M1Driver) SetName(n string) { h.name = n } +func (d *JHD1313M1Driver) SetName(n string) { d.name = n } // Connection returns the driver connection to the device. -func (h *JHD1313M1Driver) Connection() gobot.Connection { - return h.connector.(gobot.Connection) +func (d *JHD1313M1Driver) Connection() gobot.Connection { + if conn, ok := d.connector.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil } // Start starts the backlit and the screen and initializes the states. -func (h *JHD1313M1Driver) Start() (err error) { - bus := h.GetBusOrDefault(h.connector.DefaultI2cBus()) +func (d *JHD1313M1Driver) Start() error { + bus := d.GetBusOrDefault(d.connector.DefaultI2cBus()) - if h.lcdConnection, err = h.connector.GetI2cConnection(h.lcdAddress, bus); err != nil { + var err error + if d.lcdConnection, err = d.connector.GetI2cConnection(d.lcdAddress, bus); err != nil { return err } - if h.rgbConnection, err = h.connector.GetI2cConnection(h.rgbAddress, bus); err != nil { + if d.rgbConnection, err = d.connector.GetI2cConnection(d.rgbAddress, bus); err != nil { return err } @@ -166,90 +173,87 @@ func (h *JHD1313M1Driver) Start() (err error) { // page 45 figure 23 // Send function set command sequence init_payload := []byte{LCD_CMD, LCD_FUNCTIONSET | LCD_2LINE} - if _, err := h.lcdConnection.Write(init_payload); err != nil { + if _, err := d.lcdConnection.Write(init_payload); err != nil { return err } // wait more than 4.1ms time.Sleep(4500 * time.Microsecond) // second try - if _, err := h.lcdConnection.Write(init_payload); err != nil { + if _, err := d.lcdConnection.Write(init_payload); err != nil { return err } time.Sleep(150 * time.Microsecond) // third go - if _, err := h.lcdConnection.Write(init_payload); err != nil { + if _, err := d.lcdConnection.Write(init_payload); err != nil { return err } - if _, err := h.lcdConnection.Write([]byte{LCD_CMD, LCD_DISPLAYCONTROL | LCD_DISPLAYON}); err != nil { + if _, err := d.lcdConnection.Write([]byte{LCD_CMD, LCD_DISPLAYCONTROL | LCD_DISPLAYON}); err != nil { return err } time.Sleep(100 * time.Microsecond) - if err := h.Clear(); err != nil { + if err := d.Clear(); err != nil { return err } - if _, err := h.lcdConnection.Write([]byte{LCD_CMD, LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT}); err != nil { + if _, err := d.lcdConnection.Write([]byte{ + LCD_CMD, LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT, + }); err != nil { return err } - if err := h.setReg(0, 0); err != nil { + if err := d.setReg(0, 0); err != nil { return err } - if err := h.setReg(1, 0); err != nil { + if err := d.setReg(1, 0); err != nil { return err } - if err := h.setReg(0x08, 0xAA); err != nil { + if err := d.setReg(0x08, 0xAA); err != nil { return err } - if err := h.SetRGB(255, 255, 255); err != nil { - return err - } - - return nil + return d.SetRGB(255, 255, 255) } // SetRGB sets the Red Green Blue value of backlit. -func (h *JHD1313M1Driver) SetRGB(r, g, b int) error { - if err := h.setReg(REG_RED, r); err != nil { +func (d *JHD1313M1Driver) SetRGB(r, g, b int) error { + if err := d.setReg(REG_RED, r); err != nil { return err } - if err := h.setReg(REG_GREEN, g); err != nil { + if err := d.setReg(REG_GREEN, g); err != nil { return err } - return h.setReg(REG_BLUE, b) + return d.setReg(REG_BLUE, b) } // Clear clears the text on the lCD display. -func (h *JHD1313M1Driver) Clear() error { - err := h.command([]byte{LCD_CLEARDISPLAY}) - return err +func (d *JHD1313M1Driver) Clear() error { + return d.command([]byte{LCD_CLEARDISPLAY}) } // Home sets the cursor to the origin position on the display. -func (h *JHD1313M1Driver) Home() error { - err := h.command([]byte{LCD_RETURNHOME}) +func (d *JHD1313M1Driver) Home() error { + err := d.command([]byte{LCD_RETURNHOME}) // This wait fixes a race condition when calling home and clear back to back. time.Sleep(2 * time.Millisecond) return err } // Write displays the passed message on the screen. -func (h *JHD1313M1Driver) Write(message string) error { +func (d *JHD1313M1Driver) Write(message string) error { // This wait fixes an odd bug where the clear function doesn't always work properly. time.Sleep(1 * time.Millisecond) for _, val := range message { if val == '\n' { - if err := h.SetPosition(16); err != nil { + if err := d.SetPosition(16); err != nil { return err } continue } - if _, err := h.lcdConnection.Write([]byte{LCD_DATA, byte(val)}); err != nil { + if _, err := d.lcdConnection.Write([]byte{LCD_DATA, byte(val)}); err != nil { return err } } @@ -259,34 +263,33 @@ func (h *JHD1313M1Driver) Write(message string) error { // SetPosition sets the cursor and the data display to pos. // 0..15 are the positions in the first display line. // 16..32 are the positions in the second display line. -func (h *JHD1313M1Driver) SetPosition(pos int) (err error) { +func (d *JHD1313M1Driver) SetPosition(pos int) error { if pos < 0 || pos > 31 { - err = jhd1313m1ErrInvalidPosition - return + return jhd1313m1ErrInvalidPosition } offset := byte(pos) if pos >= 16 { offset -= 16 offset |= LCD_2NDLINEOFFSET } - err = h.command([]byte{LCD_SETDDRAMADDR | offset}) - return + + return d.command([]byte{LCD_SETDDRAMADDR | offset}) } // Scroll sets the scrolling direction for the display, either left to right, or // right to left. -func (h *JHD1313M1Driver) Scroll(lr bool) error { +func (d *JHD1313M1Driver) Scroll(lr bool) error { if lr { - _, err := h.lcdConnection.Write([]byte{LCD_CMD, LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT}) + _, err := d.lcdConnection.Write([]byte{LCD_CMD, LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT}) return err } - _, err := h.lcdConnection.Write([]byte{LCD_CMD, LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT}) + _, err := d.lcdConnection.Write([]byte{LCD_CMD, LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT}) return err } // Halt is a noop function. -func (h *JHD1313M1Driver) Halt() error { return nil } +func (d *JHD1313M1Driver) Halt() error { return nil } // SetCustomChar sets one of the 8 CGRAM locations with a custom character. // The custom character can be used by writing a byte of value 0 to 7. @@ -296,24 +299,24 @@ func (h *JHD1313M1Driver) Halt() error { return nil } // characters. // To use a custom character, write byte value of the custom character position as a string after // having setup the custom character. -func (h *JHD1313M1Driver) SetCustomChar(pos int, charMap [8]byte) error { +func (d *JHD1313M1Driver) SetCustomChar(pos int, charMap [8]byte) error { if pos > 7 { return fmt.Errorf("can't set a custom character at a position greater than 7") } location := uint8(pos) - if err := h.command([]byte{LCD_SETCGRAMADDR | (location << 3)}); err != nil { + if err := d.command([]byte{LCD_SETCGRAMADDR | (location << 3)}); err != nil { return err } - _, err := h.lcdConnection.Write(append([]byte{LCD_DATA}, charMap[:]...)) + _, err := d.lcdConnection.Write(append([]byte{LCD_DATA}, charMap[:]...)) return err } -func (h *JHD1313M1Driver) setReg(command int, data int) error { - _, err := h.rgbConnection.Write([]byte{byte(command), byte(data)}) +func (d *JHD1313M1Driver) setReg(command int, data int) error { + _, err := d.rgbConnection.Write([]byte{byte(command), byte(data)}) return err } -func (h *JHD1313M1Driver) command(buf []byte) error { - _, err := h.lcdConnection.Write(append([]byte{LCD_CMD}, buf...)) +func (d *JHD1313M1Driver) command(buf []byte) error { + _, err := d.lcdConnection.Write(append([]byte{LCD_CMD}, buf...)) return err } diff --git a/drivers/i2c/jhd1313m1_driver_test.go b/drivers/i2c/jhd1313m1_driver_test.go index 94ec4fbab..e6ffc273f 100644 --- a/drivers/i2c/jhd1313m1_driver_test.go +++ b/drivers/i2c/jhd1313m1_driver_test.go @@ -7,15 +7,16 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) var _ gobot.Driver = (*JHD1313M1Driver)(nil) // --------- HELPERS -func initTestJHD1313M1Driver() (driver *JHD1313M1Driver) { - driver, _ = initTestJHD1313M1DriverWithStubbedAdaptor() - return +func initTestJHD1313M1Driver() *JHD1313M1Driver { + d, _ := initTestJHD1313M1DriverWithStubbedAdaptor() + return d } func initTestJHD1313M1DriverWithStubbedAdaptor() (*JHD1313M1Driver, *i2cTestAdaptor) { diff --git a/drivers/i2c/l3gd20h_driver.go b/drivers/i2c/l3gd20h_driver.go index f88e91b10..c49001220 100644 --- a/drivers/i2c/l3gd20h_driver.go +++ b/drivers/i2c/l3gd20h_driver.go @@ -1,3 +1,4 @@ +//nolint:lll // ok here package i2c import ( @@ -111,6 +112,8 @@ func (d *L3GD20HDriver) FullScaleRange() (uint8, error) { } // XYZ returns the current change in degrees per second, for the 3 axis. +// +//nolint:nonamedreturns // is sufficient here func (d *L3GD20HDriver) XYZ() (x float32, y float32, z float32, err error) { d.mutex.Lock() defer d.mutex.Unlock() diff --git a/drivers/i2c/l3gd20h_driver_test.go b/drivers/i2c/l3gd20h_driver_test.go index caeccf94f..392ddb886 100644 --- a/drivers/i2c/l3gd20h_driver_test.go +++ b/drivers/i2c/l3gd20h_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -14,9 +15,9 @@ import ( // and tests all implementations, so no further tests needed here for gobot.Driver interface var _ gobot.Driver = (*HMC6352Driver)(nil) -func initL3GD20HDriver() (driver *L3GD20HDriver) { - driver, _ = initL3GD20HWithStubbedAdaptor() - return +func initL3GD20HDriver() *L3GD20HDriver { + d, _ := initL3GD20HWithStubbedAdaptor() + return d } func initL3GD20HWithStubbedAdaptor() (*L3GD20HDriver, *i2cTestAdaptor) { @@ -214,8 +215,11 @@ func TestL3GD20HMeasurementError(t *testing.T) { } _ = d.Start() - _, _, _, err := d.XYZ() + x, y, z, err := d.XYZ() require.ErrorContains(t, err, "read error") + assert.InDelta(t, 0.0, x, 0.0) + assert.InDelta(t, 0.0, y, 0.0) + assert.InDelta(t, 0.0, z, 0.0) } func TestL3GD20HMeasurementWriteError(t *testing.T) { @@ -223,8 +227,11 @@ func TestL3GD20HMeasurementWriteError(t *testing.T) { a.i2cWriteImpl = func(b []byte) (int, error) { return 0, errors.New("write error") } - _, _, _, err := d.XYZ() + x, y, z, err := d.XYZ() require.ErrorContains(t, err, "write error") + assert.InDelta(t, 0.0, x, 0.0) + assert.InDelta(t, 0.0, y, 0.0) + assert.InDelta(t, 0.0, z, 0.0) } func TestL3GD20H_initialize(t *testing.T) { diff --git a/drivers/i2c/lidarlite_driver.go b/drivers/i2c/lidarlite_driver.go index 79f7d7d40..328d666a5 100644 --- a/drivers/i2c/lidarlite_driver.go +++ b/drivers/i2c/lidarlite_driver.go @@ -35,43 +35,41 @@ func NewLIDARLiteDriver(c Connector, options ...func(Config)) *LIDARLiteDriver { } // Distance returns the current distance in cm -func (h *LIDARLiteDriver) Distance() (distance int, err error) { - if _, err = h.connection.Write([]byte{0x00, 0x04}); err != nil { - return +func (h *LIDARLiteDriver) Distance() (int, error) { + if _, err := h.connection.Write([]byte{0x00, 0x04}); err != nil { + return 0, err } time.Sleep(20 * time.Millisecond) - if _, err = h.connection.Write([]byte{0x0F}); err != nil { - return + if _, err := h.connection.Write([]byte{0x0F}); err != nil { + return 0, err } upper := []byte{0} bytesRead, err := h.connection.Read(upper) if err != nil { - return + return 0, err } if bytesRead != 1 { - err = ErrNotEnoughBytes - return + return 0, ErrNotEnoughBytes } - if _, err = h.connection.Write([]byte{0x10}); err != nil { - return + if _, err := h.connection.Write([]byte{0x10}); err != nil { + return 0, err } lower := []byte{0} bytesRead, err = h.connection.Read(lower) if err != nil { - return + return 0, err } if bytesRead != 1 { - err = ErrNotEnoughBytes - return + return 0, ErrNotEnoughBytes } - distance = ((int(upper[0]) & 0xff) << 8) | (int(lower[0]) & 0xff) + distance := ((int(upper[0]) & 0xff) << 8) | (int(lower[0]) & 0xff) - return + return distance, nil } diff --git a/drivers/i2c/lidarlite_driver_test.go b/drivers/i2c/lidarlite_driver_test.go index 6b9a12376..8354b2648 100644 --- a/drivers/i2c/lidarlite_driver_test.go +++ b/drivers/i2c/lidarlite_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -15,9 +16,9 @@ import ( // and tests all implementations, so no further tests needed here for gobot.Driver interface var _ gobot.Driver = (*LIDARLiteDriver)(nil) -func initTestLIDARLiteDriver() (driver *LIDARLiteDriver) { - driver, _ = initTestLIDARLiteDriverWithStubbedAdaptor() - return +func initTestLIDARLiteDriver() *LIDARLiteDriver { + d, _ := initTestLIDARLiteDriverWithStubbedAdaptor() + return d } func initTestLIDARLiteDriverWithStubbedAdaptor() (*LIDARLiteDriver, *i2cTestAdaptor) { diff --git a/drivers/i2c/mcp23017_driver.go b/drivers/i2c/mcp23017_driver.go index 4b8697859..d54abee76 100644 --- a/drivers/i2c/mcp23017_driver.go +++ b/drivers/i2c/mcp23017_driver.go @@ -20,13 +20,15 @@ type port struct { IPOL uint8 // input polarity register: 0=normal polarity / 1=inversed GPINTEN uint8 // interrupt on change control register: 0=disabled / 1=enabled DEFVAL uint8 // default compare register for interrupt on change - INTCON uint8 // interrupt control register: bit set to 0= use defval bit value to compare pin value/ bit set to 1= pin value compared to previous pin value - IOCON uint8 // configuration register - GPPU uint8 // pull-up resistor configuration register: 0=enabled / 1=disabled - INTF uint8 // interrupt flag register: 0=no interrupt / 1=pin caused interrupt - INTCAP uint8 // interrupt capture register, captures pin values during interrupt: 0=logic low / 1=logic high - GPIO uint8 // port register, reading from this register reads the port - OLAT uint8 // output latch register, write modifies the pins: 0=logic low / 1=logic high + // interrupt control register: bit set to 0= use defval bit value to compare pin value/ bit set to 1= pin value + // compared to previous pin value + INTCON uint8 + IOCON uint8 // configuration register + GPPU uint8 // pull-up resistor configuration register: 0=enabled / 1=disabled + INTF uint8 // interrupt flag register: 0=no interrupt / 1=pin caused interrupt + INTCAP uint8 // interrupt capture register, captures pin values during interrupt: 0=logic low / 1=logic high + GPIO uint8 // port register, reading from this register reads the port + OLAT uint8 // output latch register, write modifies the pins: 0=logic low / 1=logic high } // A bank is made up of PortA and PortB pins. @@ -89,6 +91,7 @@ func NewMCP23017Driver(c Connector, options ...func(Config)) *MCP23017Driver { option(d) } + //nolint:forcetypeassert // ok here d.AddCommand("WriteGPIO", func(params map[string]interface{}) interface{} { pin := params["pin"].(uint8) port := params["port"].(string) @@ -97,6 +100,7 @@ func NewMCP23017Driver(c Connector, options ...func(Config)) *MCP23017Driver { return map[string]interface{}{"err": err} }) + //nolint:forcetypeassert // ok here d.AddCommand("ReadGPIO", func(params map[string]interface{}) interface{} { pin := params["pin"].(uint8) port := params["port"].(string) @@ -228,16 +232,13 @@ func WithMCP23017AutoIODirOff(val uint8) func(Config) { // SetPinMode set pin mode of a given pin immediately, based on the value: // val = 0 output // val = 1 input -func (m *MCP23017Driver) SetPinMode(pin uint8, portStr string, val uint8) (err error) { +func (m *MCP23017Driver) SetPinMode(pin uint8, portStr string, val uint8) error { m.mutex.Lock() defer m.mutex.Unlock() selectedPort := m.getPort(portStr) // Set IODIR register bit for given pin to an output/input. - if err = m.write(selectedPort.IODIR, pin, bitState(val)); err != nil { - return - } - return + return m.write(selectedPort.IODIR, pin, bitState(val)) } // SetPullUp sets the pull up state of a given pin immediately, based on the value: @@ -254,7 +255,7 @@ func (m *MCP23017Driver) SetPullUp(pin uint8, portStr string, val uint8) error { // SetGPIOPolarity will change a given pin's polarity immediately, based on the value: // val = 1 opposite logic state of the input pin. // val = 0 same logic state of the input pin. -func (m *MCP23017Driver) SetGPIOPolarity(pin uint8, portStr string, val uint8) (err error) { +func (m *MCP23017Driver) SetGPIOPolarity(pin uint8, portStr string, val uint8) error { m.mutex.Lock() defer m.mutex.Unlock() @@ -263,7 +264,7 @@ func (m *MCP23017Driver) SetGPIOPolarity(pin uint8, portStr string, val uint8) ( } // WriteGPIO writes a value to a gpio pin (0-7) and a port (A or B). -func (m *MCP23017Driver) WriteGPIO(pin uint8, portStr string, val uint8) (err error) { +func (m *MCP23017Driver) WriteGPIO(pin uint8, portStr string, val uint8) error { m.mutex.Lock() defer m.mutex.Unlock() @@ -271,20 +272,16 @@ func (m *MCP23017Driver) WriteGPIO(pin uint8, portStr string, val uint8) (err er if !m.mcpBehav.autoIODirOff { // Set IODIR register bit for given pin to an output by clearing bit. // can't call SetPinMode() because mutex will cause deadlock - if err = m.write(selectedPort.IODIR, pin, clear); err != nil { + if err := m.write(selectedPort.IODIR, pin, clear); err != nil { return err } } // write value to OLAT register bit - err = m.write(selectedPort.OLAT, pin, bitState(val)) - if err != nil { - return err - } - return nil + return m.write(selectedPort.OLAT, pin, bitState(val)) } // ReadGPIO reads a value from a given gpio pin (0-7) and a port (A or B). -func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (val uint8, err error) { +func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (uint8, error) { m.mutex.Lock() defer m.mutex.Unlock() @@ -292,11 +289,11 @@ func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (val uint8, err err if !m.mcpBehav.autoIODirOff { // Set IODIR register bit for given pin to an input by set bit. // can't call SetPinMode() because mutex will cause deadlock - if err = m.write(selectedPort.IODIR, pin, set); err != nil { + if err := m.write(selectedPort.IODIR, pin, set); err != nil { return 0, err } } - val, err = m.read(selectedPort.GPIO) + val, err := m.read(selectedPort.GPIO) if err != nil { return val, err } @@ -307,19 +304,18 @@ func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (val uint8, err err return val, nil } -func (m *MCP23017Driver) initialize() (err error) { +func (m *MCP23017Driver) initialize() error { // Set IOCON register with MCP23017 configuration. ioconReg := m.getPort("A").IOCON // IOCON address is the same for Port A or B. ioconVal := m.mcpConf.getUint8Value() - if _, err := m.connection.Write([]uint8{ioconReg, ioconVal}); err != nil { - return err - } - return + + _, err := m.connection.Write([]uint8{ioconReg, ioconVal}) + return err } // write gets the value of the passed in register, and then sets the bit specified // by the pin to the given state. -func (m *MCP23017Driver) write(reg uint8, pin uint8, state bitState) (err error) { +func (m *MCP23017Driver) write(reg uint8, pin uint8, state bitState) error { valOrg, err := m.read(reg) if err != nil { return fmt.Errorf("MCP write-read: %v", err) @@ -337,22 +333,20 @@ func (m *MCP23017Driver) write(reg uint8, pin uint8, state bitState) (err error) log.Printf("write done: MCP forceRefresh: %t, address: 0x%X, register: 0x%X, name: %s, value: 0x%X\n", m.mcpBehav.forceRefresh, m.GetAddressOrDefault(mcp23017DefaultAddress), reg, m.getRegName(reg), val) } - if err = m.connection.WriteByteData(reg, val); err != nil { + if err := m.connection.WriteByteData(reg, val); err != nil { return fmt.Errorf("MCP write-WriteByteData(reg=%d,val=%d): %v", reg, val, err) } - } else { - if mcp23017Debug { - log.Printf("write skipped: MCP forceRefresh: %t, address: 0x%X, register: 0x%X, name: %s, value: 0x%X\n", - m.mcpBehav.forceRefresh, m.GetAddressOrDefault(mcp23017DefaultAddress), reg, m.getRegName(reg), val) - } + } else if mcp23017Debug { + log.Printf("write skipped: MCP forceRefresh: %t, address: 0x%X, register: 0x%X, name: %s, value: 0x%X\n", + m.mcpBehav.forceRefresh, m.GetAddressOrDefault(mcp23017DefaultAddress), reg, m.getRegName(reg), val) } return nil } // read get the data from a given register // it is mainly a wrapper to create additional debug messages, when activated -func (m *MCP23017Driver) read(reg uint8) (val uint8, err error) { - val, err = m.connection.ReadByteData(reg) +func (m *MCP23017Driver) read(reg uint8) (uint8, error) { + val, err := m.connection.ReadByteData(reg) if err != nil { return val, fmt.Errorf("MCP write-ReadByteData(reg=%d): %v", reg, err) } @@ -365,7 +359,7 @@ func (m *MCP23017Driver) read(reg uint8) (val uint8, err error) { // getPort return the port (A or B) given a string and the bank. // Port A is the default if an incorrect or no port is specified. -func (m *MCP23017Driver) getPort(portStr string) (selectedPort port) { +func (m *MCP23017Driver) getPort(portStr string) port { portStr = strings.ToUpper(portStr) switch { case portStr == "A": @@ -429,7 +423,13 @@ func (m *MCP23017Driver) getRegName(reg uint8) string { // mcp23017GetBank returns a bank's PortA and PortB registers given a bank number (0/1). func mcp23017GetBank(bnk uint8) bank { if bnk == 0 { - return bank{portA: port{0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14}, portB: port{0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15}} + return bank{ + portA: port{0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14}, + portB: port{0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15}, + } + } + return bank{ + portA: port{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}, + portB: port{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A}, } - return bank{portA: port{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}, portB: port{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A}} } diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index 544d2f897..5723c46d8 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package i2c import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -25,7 +27,7 @@ var pinPort = map[string]interface{}{ "port": "A", } -func initTestMCP23017(b uint8) (driver *MCP23017Driver) { +func initTestMCP23017(b uint8) *MCP23017Driver { // create the driver without starting it a := newI2cTestAdaptor() d := NewMCP23017Driver(a, WithMCP23017Bank(b)) diff --git a/drivers/i2c/mma7660_driver.go b/drivers/i2c/mma7660_driver.go index 8e9f5acd5..a82223adb 100644 --- a/drivers/i2c/mma7660_driver.go +++ b/drivers/i2c/mma7660_driver.go @@ -54,11 +54,15 @@ func NewMMA7660Driver(c Connector, options ...func(Config)) *MMA7660Driver { } // Acceleration returns the acceleration of the provided x, y, z +// +//nolint:nonamedreturns // is sufficient here func (d *MMA7660Driver) Acceleration(x, y, z float64) (ax, ay, az float64) { return x / 21.0, y / 21.0, z / 21.0 } // XYZ returns the raw x,y and z axis from the mma7660 +// +//nolint:nonamedreturns // is sufficient here func (d *MMA7660Driver) XYZ() (x float64, y float64, z float64, err error) { buf := []byte{0, 0, 0} bytesRead, err := d.connection.Read(buf) diff --git a/drivers/i2c/mma7660_driver_test.go b/drivers/i2c/mma7660_driver_test.go index a736f1ff8..7f2b05b6a 100644 --- a/drivers/i2c/mma7660_driver_test.go +++ b/drivers/i2c/mma7660_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -90,8 +91,11 @@ func TestMMA7660XYZError(t *testing.T) { return 0, errors.New("read error") } - _, _, _, err := d.XYZ() + x, y, z, err := d.XYZ() require.ErrorContains(t, err, "read error") + assert.InDelta(t, 0.0, x, 0.0) + assert.InDelta(t, 0.0, y, 0.0) + assert.InDelta(t, 0.0, z, 0.0) } func TestMMA7660XYZNotReady(t *testing.T) { @@ -103,6 +107,9 @@ func TestMMA7660XYZNotReady(t *testing.T) { return buf.Len(), nil } - _, _, _, err := d.XYZ() + x, y, z, err := d.XYZ() assert.Equal(t, ErrNotReady, err) + assert.InDelta(t, 0.0, x, 0.0) + assert.InDelta(t, 0.0, y, 0.0) + assert.InDelta(t, 0.0, z, 0.0) } diff --git a/drivers/i2c/mpl115a2_driver.go b/drivers/i2c/mpl115a2_driver.go index cbe32206f..2d0250564 100644 --- a/drivers/i2c/mpl115a2_driver.go +++ b/drivers/i2c/mpl115a2_driver.go @@ -72,21 +72,21 @@ func NewMPL115A2Driver(c Connector, options ...func(Config)) *MPL115A2Driver { } // Pressure fetches the latest data from the MPL115A2, and returns the pressure in kPa -func (d *MPL115A2Driver) Pressure() (p float32, err error) { +func (d *MPL115A2Driver) Pressure() (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - p, _, err = d.getData() - return + p, _, err := d.getData() + return p, err } // Temperature fetches the latest data from the MPL115A2, and returns the temperature in °C -func (d *MPL115A2Driver) Temperature() (t float32, err error) { +func (d *MPL115A2Driver) Temperature() (float32, error) { d.mutex.Lock() defer d.mutex.Unlock() - _, t, err = d.getData() - return + _, t, err := d.getData() + return t, err } func (d *MPL115A2Driver) initialization() error { @@ -125,6 +125,8 @@ func (d *MPL115A2Driver) initialization() error { } // getData fetches the latest data from the MPL115A2 +// +//nolint:nonamedreturns // is sufficient here func (d *MPL115A2Driver) getData() (p, t float32, err error) { var temperature uint16 var pressure uint16 @@ -137,7 +139,7 @@ func (d *MPL115A2Driver) getData() (p, t float32, err error) { data := []byte{0, 0, 0, 0} if err = d.connection.ReadBlockData(mpl115A2Reg_PressureMSB, data); err != nil { - return + return 0, 0, err } buf := bytes.NewBuffer(data) @@ -155,5 +157,5 @@ func (d *MPL115A2Driver) getData() (p, t float32, err error) { p = (65.0/1023.0)*pressureComp + 50.0 t = ((float32(temperature) - 498.0) / -5.35) + 25.0 - return + return p, t, err } diff --git a/drivers/i2c/mpl115a2_driver_test.go b/drivers/i2c/mpl115a2_driver_test.go index bd0ad6422..7ae72b516 100644 --- a/drivers/i2c/mpl115a2_driver_test.go +++ b/drivers/i2c/mpl115a2_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/mpu6050_driver_test.go b/drivers/i2c/mpu6050_driver_test.go index 15ba6e44a..8ba6a3668 100644 --- a/drivers/i2c/mpu6050_driver_test.go +++ b/drivers/i2c/mpu6050_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/pca9501_driver.go b/drivers/i2c/pca9501_driver.go index 05677886b..daa7da583 100644 --- a/drivers/i2c/pca9501_driver.go +++ b/drivers/i2c/pca9501_driver.go @@ -37,6 +37,7 @@ func NewPCA9501Driver(a Connector, options ...func(Config)) *PCA9501Driver { p.afterStart = p.initialize // API commands + //nolint:forcetypeassert // ok here p.AddCommand("WriteGPIO", func(params map[string]interface{}) interface{} { pin := params["pin"].(uint8) val := params["val"].(uint8) @@ -44,12 +45,14 @@ func NewPCA9501Driver(a Connector, options ...func(Config)) *PCA9501Driver { return map[string]interface{}{"err": err} }) + //nolint:forcetypeassert // ok here p.AddCommand("ReadGPIO", func(params map[string]interface{}) interface{} { pin := params["pin"].(uint8) val, err := p.ReadGPIO(pin) return map[string]interface{}{"val": val, "err": err} }) + //nolint:forcetypeassert // ok here p.AddCommand("WriteEEPROM", func(params map[string]interface{}) interface{} { address := params["address"].(uint8) val := params["val"].(uint8) @@ -57,6 +60,7 @@ func NewPCA9501Driver(a Connector, options ...func(Config)) *PCA9501Driver { return map[string]interface{}{"err": err} }) + //nolint:forcetypeassert // ok here p.AddCommand("ReadEEPROM", func(params map[string]interface{}) interface{} { address := params["address"].(uint8) val, err := p.ReadEEPROM(address) @@ -149,10 +153,11 @@ func (p *PCA9501Driver) WriteEEPROM(address uint8, val uint8) error { return p.connectionMem.WriteByteData(address, val) } -func (p *PCA9501Driver) initialize() (err error) { +func (p *PCA9501Driver) initialize() error { // initialize the EEPROM connection bus := p.GetBusOrDefault(p.connector.DefaultI2cBus()) addressMem := p.GetAddressOrDefault(pca9501DefaultAddress) | 0x40 + var err error p.connectionMem, err = p.connector.GetI2cConnection(addressMem, bus) - return + return err } diff --git a/drivers/i2c/pca9501_driver_test.go b/drivers/i2c/pca9501_driver_test.go index 8f10608fb..d214f3538 100644 --- a/drivers/i2c/pca9501_driver_test.go +++ b/drivers/i2c/pca9501_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package i2c import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/pca953x_driver_test.go b/drivers/i2c/pca953x_driver_test.go index 5bee65857..a28e950e7 100644 --- a/drivers/i2c/pca953x_driver_test.go +++ b/drivers/i2c/pca953x_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/pca9685_driver.go b/drivers/i2c/pca9685_driver.go index b8c1eddd2..24b6a7fdd 100644 --- a/drivers/i2c/pca9685_driver.go +++ b/drivers/i2c/pca9685_driver.go @@ -61,11 +61,13 @@ func NewPCA9685Driver(c Connector, options ...func(Config)) *PCA9685Driver { option(p) } + //nolint:forcetypeassert // ok here p.AddCommand("PwmWrite", func(params map[string]interface{}) interface{} { pin := params["pin"].(string) val, _ := strconv.Atoi(params["val"].(string)) return p.PwmWrite(pin, byte(val)) }) + //nolint:forcetypeassert // ok here p.AddCommand("ServoWrite", func(params map[string]interface{}) interface{} { pin := params["pin"].(string) val, _ := strconv.Atoi(params["val"].(string)) @@ -93,7 +95,7 @@ func NewPCA9685Driver(c Connector, options ...func(Config)) *PCA9685Driver { // off uint16 - the time to stop the pulse // // Most typically you set "on" to a zero value, and then set "off" to your desired duty. -func (p *PCA9685Driver) SetPWM(channel int, on uint16, off uint16) (err error) { +func (p *PCA9685Driver) SetPWM(channel int, on uint16, off uint16) error { if _, err := p.connection.Write([]byte{byte(pca9685Led0OnLReg + 4*channel), byte(on) & 0xFF}); err != nil { return err } @@ -106,11 +108,8 @@ func (p *PCA9685Driver) SetPWM(channel int, on uint16, off uint16) (err error) { return err } - if _, err := p.connection.Write([]byte{byte(pca9685Led0OffHReg + 4*channel), byte(off >> 8)}); err != nil { - return err - } - - return + _, err := p.connection.Write([]byte{byte(pca9685Led0OffHReg + 4*channel), byte(off >> 8)}) + return err } // SetAllPWM sets all channels to a pwm value from 0-4095. @@ -120,7 +119,7 @@ func (p *PCA9685Driver) SetPWM(channel int, on uint16, off uint16) (err error) { // off uint16 - the time to stop the pulse // // Most typically you set "on" to a zero value, and then set "off" to your desired duty. -func (p *PCA9685Driver) SetAllPWM(on uint16, off uint16) (err error) { +func (p *PCA9685Driver) SetAllPWM(on uint16, off uint16) error { if _, err := p.connection.Write([]byte{byte(pca9685AllLedOnLReg), byte(on) & 0xFF}); err != nil { return err } @@ -133,11 +132,8 @@ func (p *PCA9685Driver) SetAllPWM(on uint16, off uint16) (err error) { return err } - if _, err := p.connection.Write([]byte{byte(pca9685AllLedOffHReg), byte(off >> 8)}); err != nil { - return err - } - - return + _, err := p.connection.Write([]byte{byte(pca9685AllLedOffHReg), byte(off >> 8)}) + return err } // SetPWMFreq sets the PWM frequency in Hz between 24Hz and 1526Hz, the default is 200Hz. @@ -180,20 +176,17 @@ func (p *PCA9685Driver) SetPWMFreq(freq float32) error { // initiate a restart restartMode := oldmode | pca9685Mode1RegRestartBit - if _, err := p.connection.Write([]byte{byte(pca9685Mode1Reg), restartMode}); err != nil { - return err - } - - return nil + _, err = p.connection.Write([]byte{byte(pca9685Mode1Reg), restartMode}) + return err } // PwmWrite writes a PWM signal to the specified channel aka "pin". // Value values are from 0-255, to conform to the PwmWriter interface. // If you need finer control, please look at SetPWM(). -func (p *PCA9685Driver) PwmWrite(pin string, val byte) (err error) { +func (p *PCA9685Driver) PwmWrite(pin string, val byte) error { i, err := strconv.Atoi(pin) if err != nil { - return + return err } v := gobot.ToScale(gobot.FromScale(float64(val), 0, 255), 0, 4095) return p.SetPWM(i, 0, uint16(v)) @@ -202,10 +195,10 @@ func (p *PCA9685Driver) PwmWrite(pin string, val byte) (err error) { // ServoWrite writes a servo signal to the specified channel aka "pin". // Valid values are from 0-180, to conform to the ServoWriter interface. // If you need finer control, please look at SetPWM(). -func (p *PCA9685Driver) ServoWrite(pin string, val byte) (err error) { +func (p *PCA9685Driver) ServoWrite(pin string, val byte) error { i, err := strconv.Atoi(pin) if err != nil { - return + return err } v := gobot.ToScale(gobot.FromScale(float64(val), 0, 180), 200, 500) return p.SetPWM(i, 0, uint16(v)) diff --git a/drivers/i2c/pca9685_driver_test.go b/drivers/i2c/pca9685_driver_test.go index 4880ec140..9363f02b8 100644 --- a/drivers/i2c/pca9685_driver_test.go +++ b/drivers/i2c/pca9685_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" ) diff --git a/drivers/i2c/pcf8583_driver.go b/drivers/i2c/pcf8583_driver.go index 2db6821b2..70883b72a 100644 --- a/drivers/i2c/pcf8583_driver.go +++ b/drivers/i2c/pcf8583_driver.go @@ -43,7 +43,7 @@ const ( pcf8583CtrlStopCounting PCF8583Control = 0x80 // 0: count, 1: stop counting, reset divider ) -// PCF8583Driver is a Gobot Driver for the PCF8583 clock and calendar chip & 240 x 8-bit bit RAM with 1 address program pin. +// PCF8583Driver is a driver for the PCF8583 clock and calendar chip & 240 x 8-bit bit RAM with 1 address program pin. // please refer to data sheet: https://www.nxp.com/docs/en/data-sheet/PCF8583.pdf // // 0 1 0 1 0 0 0 A0|rd @@ -81,35 +81,34 @@ func NewPCF8583Driver(c Connector, options ...func(Config)) *PCF8583Driver { } // API commands + //nolint:forcetypeassert // ok here d.AddCommand("WriteTime", func(params map[string]interface{}) interface{} { val := params["val"].(time.Time) err := d.WriteTime(val) return map[string]interface{}{"err": err} }) - d.AddCommand("ReadTime", func(params map[string]interface{}) interface{} { val, err := d.ReadTime() return map[string]interface{}{"val": val, "err": err} }) - + //nolint:forcetypeassert // ok here d.AddCommand("WriteCounter", func(params map[string]interface{}) interface{} { val := params["val"].(int32) err := d.WriteCounter(val) return map[string]interface{}{"err": err} }) - d.AddCommand("ReadCounter", func(params map[string]interface{}) interface{} { val, err := d.ReadCounter() return map[string]interface{}{"val": val, "err": err} }) - + //nolint:forcetypeassert // ok here d.AddCommand("WriteRAM", func(params map[string]interface{}) interface{} { address := params["address"].(uint8) val := params["val"].(uint8) err := d.WriteRAM(address, val) return map[string]interface{}{"err": err} }) - + //nolint:forcetypeassert // ok here d.AddCommand("ReadRAM", func(params map[string]interface{}) interface{} { address := params["address"].(uint8) val, err := d.ReadRAM(address) @@ -152,12 +151,15 @@ func (d *PCF8583Driver) WriteTime(val time.Time) error { err = d.connection.WriteBlockData(uint8(pcf8583Reg_CTRL), []byte{ ctrlRegVal | uint8(pcf8583CtrlStopCounting), - pcf8583encodeBcd(uint8(val.Nanosecond() / 1000000 / 10)), // sub seconds in 1/10th seconds + // sub seconds in 1/10th seconds + pcf8583encodeBcd(uint8(val.Nanosecond() / 1000000 / 10)), pcf8583encodeBcd(uint8(val.Second())), pcf8583encodeBcd(uint8(val.Minute())), pcf8583encodeBcd(uint8(val.Hour())), - pcf8583encodeBcd(uint8(day)), // year, date (we keep the year counter zero and set the offset) - uint8(val.Weekday())<<5 | pcf8583encodeBcd(uint8(month)), // month, weekday (not BCD): Sunday = 0, Monday = 1 ... + // year, date (we keep the year counter zero and set the offset) + pcf8583encodeBcd(uint8(day)), + // month, weekday (not BCD): Sunday = 0, Monday = 1 ... + uint8(val.Weekday())<<5 | pcf8583encodeBcd(uint8(month)), }) if err != nil { return err @@ -167,7 +169,7 @@ func (d *PCF8583Driver) WriteTime(val time.Time) error { } // ReadTime reads the clock and returns the value -func (d *PCF8583Driver) ReadTime() (val time.Time, err error) { +func (d *PCF8583Driver) ReadTime() (time.Time, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -175,20 +177,20 @@ func (d *PCF8583Driver) ReadTime() (val time.Time, err error) { // is not needed when reading with auto increment ctrlRegVal, err := d.connection.ReadByteData(uint8(pcf8583Reg_CTRL)) if err != nil { - return + return time.Time{}, err } if !PCF8583Control(ctrlRegVal).isClockMode() { - return val, fmt.Errorf("%s: can't read time because the device is in wrong mode 0x%02x", d.name, ctrlRegVal) + return time.Time{}, fmt.Errorf("%s: can't read time because the device is in wrong mode 0x%02x", d.name, ctrlRegVal) } // auto increment feature is used clockDataSize := 6 data := make([]byte, clockDataSize) read, err := d.connection.Read(data) if err != nil { - return + return time.Time{}, err } if read != clockDataSize { - return val, fmt.Errorf("%s: %d bytes read, but %d expected", d.name, read, clockDataSize) + return time.Time{}, fmt.Errorf("%s: %d bytes read, but %d expected", d.name, read, clockDataSize) } nanos := int(pcf8583decodeBcd(data[0])) * 1000000 * 10 // sub seconds in 1/10th seconds seconds := int(pcf8583decodeBcd(data[1])) @@ -231,7 +233,7 @@ func (d *PCF8583Driver) WriteCounter(val int32) error { } // ReadCounter reads the counter registers -func (d *PCF8583Driver) ReadCounter() (val int32, err error) { +func (d *PCF8583Driver) ReadCounter() (int32, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -239,20 +241,20 @@ func (d *PCF8583Driver) ReadCounter() (val int32, err error) { // is not needed when reading with auto increment ctrlRegVal, err := d.connection.ReadByteData(uint8(pcf8583Reg_CTRL)) if err != nil { - return + return 0, err } if !PCF8583Control(ctrlRegVal).isCounterMode() { - return val, fmt.Errorf("%s: can't read counter because the device is in wrong mode 0x%02x", d.name, ctrlRegVal) + return 0, fmt.Errorf("%s: can't read counter because the device is in wrong mode 0x%02x", d.name, ctrlRegVal) } // auto increment feature is used counterDataSize := 3 data := make([]byte, counterDataSize) read, err := d.connection.Read(data) if err != nil { - return + return 0, err } if read != counterDataSize { - return val, fmt.Errorf("%s: %d bytes read, but %d expected", d.name, read, counterDataSize) + return 0, fmt.Errorf("%s: %d bytes read, but %d expected", d.name, read, counterDataSize) } return int32(pcf8583decodeBcd(data[0])) + int32(pcf8583decodeBcd(data[1]))*100 + @@ -272,13 +274,13 @@ func (d *PCF8583Driver) WriteRAM(address uint8, val uint8) error { } // ReadRAM reads a value from a given address (0x00-0xFF) -func (d *PCF8583Driver) ReadRAM(address uint8) (val uint8, err error) { +func (d *PCF8583Driver) ReadRAM(address uint8) (uint8, error) { d.mutex.Lock() defer d.mutex.Unlock() realAddress := uint16(address) + uint16(d.ramOffset) if realAddress > 0xFF { - return val, fmt.Errorf("%s: RAM address overflow %d", d.name, realAddress) + return 0, fmt.Errorf("%s: RAM address overflow %d", d.name, realAddress) } return d.connection.ReadByteData(uint8(realAddress)) } diff --git a/drivers/i2c/pcf8583_driver_test.go b/drivers/i2c/pcf8583_driver_test.go index 9fd6355b2..f91cd3e0c 100644 --- a/drivers/i2c/pcf8583_driver_test.go +++ b/drivers/i2c/pcf8583_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package i2c import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -248,7 +250,7 @@ func TestPCF8583WriteTimeNoTimeModeFails(t *testing.T) { err := d.WriteTime(time.Now()) // assert require.Error(t, err) - assert.Contains(t, err.Error(), "wrong mode 0x30") + require.ErrorContains(t, err, "wrong mode 0x30") assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 1, numCallsRead) @@ -320,7 +322,7 @@ func TestPCF8583ReadTimeNoTimeModeFails(t *testing.T) { got, err := d.ReadTime() // assert require.Error(t, err) - assert.Contains(t, err.Error(), "wrong mode 0x20") + require.ErrorContains(t, err, "wrong mode 0x20") assert.Equal(t, time.Time{}, got) assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) @@ -391,7 +393,7 @@ func TestPCF8583WriteCounterNoCounterModeFails(t *testing.T) { err := d.WriteCounter(123) // assert require.Error(t, err) - assert.Contains(t, err.Error(), "wrong mode 0x10") + require.ErrorContains(t, err, "wrong mode 0x10") assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) assert.Equal(t, 1, numCallsRead) @@ -458,7 +460,7 @@ func TestPCF8583ReadCounterNoCounterModeFails(t *testing.T) { got, err := d.ReadCounter() // assert require.Error(t, err) - assert.Contains(t, err.Error(), "wrong mode 0x30") + require.ErrorContains(t, err, "wrong mode 0x30") assert.Equal(t, int32(0), got) assert.Len(t, a.written, 1) assert.Equal(t, uint8(pcf8583Reg_CTRL), a.written[0]) @@ -495,7 +497,7 @@ func TestPCF8583WriteRamAddressOverflowFails(t *testing.T) { err := d.WriteRAM(uint8(0xF0), 15) // assert require.Error(t, err) - assert.Contains(t, err.Error(), "overflow 256") + require.ErrorContains(t, err, "overflow 256") assert.Empty(t, a.written) } @@ -547,7 +549,7 @@ func TestPCF8583ReadRamAddressOverflowFails(t *testing.T) { got, err := d.ReadRAM(uint8(0xF0)) // assert require.Error(t, err) - assert.Contains(t, err.Error(), "overflow 256") + require.ErrorContains(t, err, "overflow 256") assert.Equal(t, uint8(0), got) assert.Empty(t, a.written) assert.Equal(t, 0, numCallsRead) diff --git a/drivers/i2c/pcf8591_driver.go b/drivers/i2c/pcf8591_driver.go index e686429ad..8946cc03b 100644 --- a/drivers/i2c/pcf8591_driver.go +++ b/drivers/i2c/pcf8591_driver.go @@ -191,7 +191,7 @@ func WithPCF8591ForceRefresh(val uint8) func(Config) { // because some missing integration steps in each conversion (each byte value is a little bit lower than expected) // // So, for default, we drop the first three bytes to get the right value. -func (p *PCF8591Driver) AnalogRead(description string) (value int, err error) { +func (p *PCF8591Driver) AnalogRead(description string) (int, error) { p.mutex.Lock() defer p.mutex.Unlock() @@ -232,7 +232,7 @@ func (p *PCF8591Driver) AnalogRead(description string) (value int, err error) { } // prepare return value - value = int(uval) + value := int(uval) if mc.pcf8591IsDiff() { if uval > 127 { // first bit is set, means negative @@ -240,13 +240,13 @@ func (p *PCF8591Driver) AnalogRead(description string) (value int, err error) { } } - return value, err + return value, nil } // AnalogWrite writes the given value to the analog output (DAC) // Vlsb = (Vref-Vagnd)/256, Vaout = Vagnd+Vlsb*value // implements the aio.AnalogWriter interface, pin is unused here -func (p *PCF8591Driver) AnalogWrite(pin string, value int) (err error) { +func (p *PCF8591Driver) AnalogWrite(pin string, value int) error { p.mutex.Lock() defer p.mutex.Unlock() @@ -260,8 +260,7 @@ func (p *PCF8591Driver) AnalogWrite(pin string, value int) (err error) { } ctrlByte := p.lastCtrlByte | byte(pcf8591_ANAON) - err = p.connection.WriteByteData(ctrlByte, byteVal) - if err != nil { + if err := p.connection.WriteByteData(ctrlByte, byteVal); err != nil { return err } @@ -281,8 +280,8 @@ func (p *PCF8591Driver) AnalogOutputState(state bool) error { return p.analogOutputState(state) } -// PCF8591ParseModeChan is used to get a working combination between mode (single, mixed, 2 differential, 3 differential) -// and the related channel to read from, parsed from the given description string. +// PCF8591ParseModeChan is used to get a working combination between mode (single, mixed, 2 differential, +// 3 differential) and the related channel to read from, parsed from the given description string. func PCF8591ParseModeChan(description string) (*pcf8591ModeChan, error) { mc, ok := pcf8591ModeMap[description] if !ok { @@ -303,10 +302,8 @@ func (p *PCF8591Driver) writeCtrlByte(ctrlByte uint8, forceRefresh bool) error { return err } p.lastCtrlByte = ctrlByte - } else { - if pcf8591Debug { - log.Printf("write skipped because control byte unchanged: 0x%X\n", ctrlByte) - } + } else if pcf8591Debug { + log.Printf("write skipped because control byte unchanged: 0x%X\n", ctrlByte) } return nil } @@ -343,7 +340,7 @@ func (p *PCF8591Driver) initialize() error { return p.analogOutputState(false) } -func (p *PCF8591Driver) shutdown() (err error) { +func (p *PCF8591Driver) shutdown() error { return p.analogOutputState(false) } diff --git a/drivers/i2c/pcf8591_driver_test.go b/drivers/i2c/pcf8591_driver_test.go index 0936631b4..a0eedf1ab 100644 --- a/drivers/i2c/pcf8591_driver_test.go +++ b/drivers/i2c/pcf8591_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/sht2x_driver.go b/drivers/i2c/sht2x_driver.go index abbf376b6..f4c24f056 100644 --- a/drivers/i2c/sht2x_driver.go +++ b/drivers/i2c/sht2x_driver.go @@ -110,59 +110,59 @@ func NewSHT2xDriver(c Connector, options ...func(Config)) *SHT2xDriver { func (d *SHT2xDriver) Accuracy() byte { return d.accuracy } // SetAccuracy sets the accuracy of the sampling -func (d *SHT2xDriver) SetAccuracy(acc byte) (err error) { +func (d *SHT2xDriver) SetAccuracy(acc byte) error { d.accuracy = acc if d.connection != nil { - err = d.sendAccuracy() + return d.sendAccuracy() } - return + return nil } // Reset does a software reset of the device -func (d *SHT2xDriver) Reset() (err error) { - if err = d.connection.WriteByte(SHT2xSoftReset); err != nil { - return +func (d *SHT2xDriver) Reset() error { + if err := d.connection.WriteByte(SHT2xSoftReset); err != nil { + return err } time.Sleep(15 * time.Millisecond) // 15ms delay (from the datasheet 5.5) - return + return nil } // Temperature returns the current temperature, in celsius degrees. -func (d *SHT2xDriver) Temperature() (temp float32, err error) { - var rawT uint16 - if rawT, err = d.readSensor(SHT2xTriggerTempMeasureNohold); err != nil { - return +func (d *SHT2xDriver) Temperature() (float32, error) { + rawT, err := d.readSensor(SHT2xTriggerTempMeasureNohold) + if err != nil { + return 0, err } // From the datasheet 6.2: // T[C] = -46.85 + 175.72 * St / 2^16 - temp = -46.85 + 175.72/65536.0*float32(rawT) + temp := -46.85 + 175.72/65536.0*float32(rawT) - return + return temp, nil } // Humidity returns the current humidity in percentage of relative humidity -func (d *SHT2xDriver) Humidity() (humidity float32, err error) { - var rawH uint16 - if rawH, err = d.readSensor(SHT2xTriggerHumdMeasureNohold); err != nil { - return +func (d *SHT2xDriver) Humidity() (float32, error) { + rawH, err := d.readSensor(SHT2xTriggerHumdMeasureNohold) + if err != nil { + return 0, err } // From the datasheet 6.1: // RH = -6 + 125 * Srh / 2^16 - humidity = -6.0 + 125.0/65536.0*float32(rawH) + humidity := -6.0 + 125.0/65536.0*float32(rawH) - return + return humidity, nil } // sendCommandDelayGetResponse is a helper function to reduce duplicated code -func (d *SHT2xDriver) readSensor(cmd byte) (read uint16, err error) { - if err = d.connection.WriteByte(cmd); err != nil { - return +func (d *SHT2xDriver) readSensor(cmd byte) (uint16, error) { + if err := d.connection.WriteByte(cmd); err != nil { + return 0, err } // Hang out while measurement is taken. 85ms max, page 9 of datasheet. @@ -172,16 +172,14 @@ func (d *SHT2xDriver) readSensor(cmd byte) (read uint16, err error) { buf := make([]byte, 3) counter := 0 for { - var got int - got, err = d.connection.Read(buf) + got, err := d.connection.Read(buf) counter++ if counter > 50 { - return + return 0, err } if err == nil { if got != 3 { - err = ErrNotEnoughBytes - return + return 0, ErrNotEnoughBytes } break } @@ -191,13 +189,12 @@ func (d *SHT2xDriver) readSensor(cmd byte) (read uint16, err error) { // Store the result crc := crc8.Checksum(buf[0:2], d.crcTable) if buf[2] != crc { - err = errors.New("Invalid crc") - return + return 0, errors.New("Invalid crc") } - read = uint16(buf[0])<<8 | uint16(buf[1]) + read := uint16(buf[0])<<8 | uint16(buf[1]) read &= 0xfffc // clear two low bits (status bits) - return + return read, nil } func (d *SHT2xDriver) initialize() error { @@ -205,11 +202,7 @@ func (d *SHT2xDriver) initialize() error { return err } - if err := d.sendAccuracy(); err != nil { - return err - } - - return nil + return d.sendAccuracy() } func (d *SHT2xDriver) sendAccuracy() error { @@ -231,9 +224,6 @@ func (d *SHT2xDriver) sendAccuracy() error { return err } - if _, err := d.connection.ReadByte(); err != nil { - return err - } - - return nil + _, err = d.connection.ReadByte() + return err } diff --git a/drivers/i2c/sht2x_driver_test.go b/drivers/i2c/sht2x_driver_test.go index 9ae532b02..5c870c63f 100644 --- a/drivers/i2c/sht2x_driver_test.go +++ b/drivers/i2c/sht2x_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -87,11 +88,12 @@ func TestSHT2xAccuracy(t *testing.T) { d, a := initTestSHT2xDriverWithStubbedAdaptor() a.i2cReadImpl = func(b []byte) (int, error) { buf := new(bytes.Buffer) - if a.written[len(a.written)-1] == SHT2xReadUserReg { + switch { + case a.written[len(a.written)-1] == SHT2xReadUserReg: buf.Write([]byte{0x3a}) - } else if a.written[len(a.written)-2] == SHT2xWriteUserReg { + case a.written[len(a.written)-2] == SHT2xWriteUserReg: buf.Write([]byte{a.written[len(a.written)-1]}) - } else { + default: return 0, nil } copy(b, buf.Bytes()) diff --git a/drivers/i2c/sht3x_driver.go b/drivers/i2c/sht3x_driver.go index c9d16220a..066d9f9a7 100644 --- a/drivers/i2c/sht3x_driver.go +++ b/drivers/i2c/sht3x_driver.go @@ -91,7 +91,7 @@ func NewSHT3xDriver(c Connector, options ...func(Config)) *SHT3xDriver { func (s *SHT3xDriver) Accuracy() byte { return s.accuracy } // SetAccuracy sets the accuracy of the sampling -func (s *SHT3xDriver) SetAccuracy(a byte) (err error) { +func (s *SHT3xDriver) SetAccuracy(a byte) error { switch a { case SHT3xAccuracyLow: s.delay = 5 * time.Millisecond // Actual max is 4, wait 1 ms longer @@ -100,47 +100,53 @@ func (s *SHT3xDriver) SetAccuracy(a byte) (err error) { case SHT3xAccuracyHigh: s.delay = 16 * time.Millisecond // Actual max is 15, wait 1 ms longer default: - err = ErrInvalidAccuracy - return + return ErrInvalidAccuracy } s.accuracy = a - return + return nil } // SerialNumber returns the serial number of the chip -func (s *SHT3xDriver) SerialNumber() (sn uint32, err error) { +func (s *SHT3xDriver) SerialNumber() (uint32, error) { ret, err := s.sendCommandDelayGetResponse([]byte{0x37, 0x80}, nil, 2) - if nil == err { - sn = (uint32(ret[0]) << 16) | uint32(ret[1]) + if err != nil { + return 0, err } - return + sn := (uint32(ret[0]) << 16) | uint32(ret[1]) + + return sn, nil } // Heater returns true if the heater is enabled -func (s *SHT3xDriver) Heater() (status bool, err error) { +func (s *SHT3xDriver) Heater() (bool, error) { sr, err := s.getStatusRegister() - if err == nil { - if (1 << 13) == (sr & (1 << 13)) { - status = true - } + if err != nil { + return false, err } - return + + if (1 << 13) == (sr & (1 << 13)) { + return true, nil + } + + return false, nil } // SetHeater enables or disables the heater on the device -func (s *SHT3xDriver) SetHeater(enabled bool) (err error) { +func (s *SHT3xDriver) SetHeater(enabled bool) error { out := []byte{0x30, 0x66} if enabled { out[1] = 0x6d } - _, err = s.connection.Write(out) - return + _, err := s.connection.Write(out) + return err } // Sample returns the temperature in celsius and relative humidity for one sample +// +//nolint:nonamedreturns // is sufficient here func (s *SHT3xDriver) Sample() (temp float32, rh float32, err error) { ret, err := s.sendCommandDelayGetResponse([]byte{0x24, s.accuracy}, &s.delay, 2) if nil != err { @@ -170,18 +176,19 @@ func (s *SHT3xDriver) Sample() (temp float32, rh float32, err error) { } // getStatusRegister returns the device status register -func (s *SHT3xDriver) getStatusRegister() (status uint16, err error) { +func (s *SHT3xDriver) getStatusRegister() (uint16, error) { ret, err := s.sendCommandDelayGetResponse([]byte{0xf3, 0x2d}, nil, 1) - if nil == err { - status = ret[0] + if err != nil { + return 0, err } - return + + return ret[0], nil } // sendCommandDelayGetResponse is a helper function to reduce duplicated code -func (s *SHT3xDriver) sendCommandDelayGetResponse(send []byte, delay *time.Duration, expect int) (read []uint16, err error) { - if _, err = s.connection.Write(send); err != nil { - return +func (s *SHT3xDriver) sendCommandDelayGetResponse(send []byte, delay *time.Duration, expect int) ([]uint16, error) { + if _, err := s.connection.Write(send); err != nil { + return nil, err } if nil != delay { @@ -191,22 +198,20 @@ func (s *SHT3xDriver) sendCommandDelayGetResponse(send []byte, delay *time.Durat buf := make([]byte, 3*expect) got, err := s.connection.Read(buf) if err != nil { - return + return nil, err } if got != (3 * expect) { - err = ErrNotEnoughBytes - return + return nil, ErrNotEnoughBytes } - read = make([]uint16, expect) + read := make([]uint16, expect) for i := 0; i < expect; i++ { crc := crc8.Checksum(buf[i*3:i*3+2], s.crcTable) if buf[i*3+2] != crc { - err = ErrInvalidCrc - return + return nil, ErrInvalidCrc } read[i] = uint16(buf[i*3])<<8 | uint16(buf[i*3+1]) } - return + return read, nil } diff --git a/drivers/i2c/sht3x_driver_test.go b/drivers/i2c/sht3x_driver_test.go index 13611382c..9174cd544 100644 --- a/drivers/i2c/sht3x_driver_test.go +++ b/drivers/i2c/sht3x_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/ssd1306_driver.go b/drivers/i2c/ssd1306_driver.go index 9a8e92944..f7a674d05 100644 --- a/drivers/i2c/ssd1306_driver.go +++ b/drivers/i2c/ssd1306_driver.go @@ -234,11 +234,13 @@ func NewSSD1306Driver(c Connector, options ...func(Config)) *SSD1306Driver { s.Clear() return map[string]interface{}{} }) + //nolint:forcetypeassert // ok here s.AddCommand("SetContrast", func(params map[string]interface{}) interface{} { contrast := params["contrast"].(byte) err := s.SetContrast(contrast) return map[string]interface{}{"err": err} }) + //nolint:forcetypeassert // ok here s.AddCommand("Set", func(params map[string]interface{}) interface{} { x := params["x"].(int) y := params["y"].(int) @@ -280,31 +282,29 @@ func WithSSD1306ExternalVCC(val bool) func(Config) { } // Init initializes the ssd1306 display. -func (s *SSD1306Driver) Init() (err error) { +func (s *SSD1306Driver) Init() error { // turn off screen - if err = s.Off(); err != nil { + if err := s.Off(); err != nil { return err } // run through initialization commands - if err = s.commands(s.initSequence.GetSequence()); err != nil { + if err := s.commands(s.initSequence.GetSequence()); err != nil { return err } - if err = s.commands([]byte{ssd1306ColumnAddr, 0, byte(s.buffer.width) - 1}); err != nil { + if err := s.commands([]byte{ssd1306ColumnAddr, 0, byte(s.buffer.width) - 1}); err != nil { return err } - if err = s.commands([]byte{ssd1306PageAddr, 0, (byte(s.buffer.height / s.pageSize)) - 1}); err != nil { - return err - } - return nil + + return s.commands([]byte{ssd1306PageAddr, 0, (byte(s.buffer.height / s.pageSize)) - 1}) } // On turns on the display. -func (s *SSD1306Driver) On() (err error) { +func (s *SSD1306Driver) On() error { return s.command(ssd1306SetDisplayOn) } // Off turns off the display. -func (s *SSD1306Driver) Off() (err error) { +func (s *SSD1306Driver) Off() error { return s.command(ssd1306SetDisplayOff) } @@ -319,31 +319,28 @@ func (s *SSD1306Driver) Set(x, y, c int) { } // Reset clears display. -func (s *SSD1306Driver) Reset() (err error) { - if err = s.Off(); err != nil { +func (s *SSD1306Driver) Reset() error { + if err := s.Off(); err != nil { return err } s.Clear() - if err = s.On(); err != nil { - return err - } - return nil + + return s.On() } // SetContrast sets the display contrast. -func (s *SSD1306Driver) SetContrast(contrast byte) (err error) { - err = s.commands([]byte{ssd1306SetContrast, contrast}) - return +func (s *SSD1306Driver) SetContrast(contrast byte) error { + return s.commands([]byte{ssd1306SetContrast, contrast}) } // Display sends the memory buffer to the display. -func (s *SSD1306Driver) Display() (err error) { - _, err = s.connection.Write(append([]byte{0x40}, s.buffer.buffer...)) +func (s *SSD1306Driver) Display() error { + _, err := s.connection.Write(append([]byte{0x40}, s.buffer.buffer...)) return err } // ShowImage takes a standard Go image and displays it in monochrome. -func (s *SSD1306Driver) ShowImage(img image.Image) (err error) { +func (s *SSD1306Driver) ShowImage(img image.Image) error { if img.Bounds().Dx() != s.displayWidth || img.Bounds().Dy() != s.displayHeight { return fmt.Errorf("image must match display width and height: %dx%d", s.displayWidth, s.displayHeight) } @@ -360,22 +357,22 @@ func (s *SSD1306Driver) ShowImage(img image.Image) (err error) { } // command sends a command to the ssd1306 -func (s *SSD1306Driver) command(b byte) (err error) { - _, err = s.connection.Write([]byte{0x80, b}) +func (s *SSD1306Driver) command(b byte) error { + _, err := s.connection.Write([]byte{0x80, b}) return err } // commands sends a command sequence to the ssd1306 -func (s *SSD1306Driver) commands(commands []byte) (err error) { +func (s *SSD1306Driver) commands(commands []byte) error { var command []byte for _, d := range commands { command = append(command, []byte{0x80, d}...) } - _, err = s.connection.Write(command) + _, err := s.connection.Write(command) return err } -func (s *SSD1306Driver) initialize() (err error) { +func (s *SSD1306Driver) initialize() error { // check device size for supported resolutions switch { case s.displayWidth == 128 && s.displayHeight == 64: @@ -394,11 +391,9 @@ func (s *SSD1306Driver) initialize() (err error) { s.initSequence.contrast = 0x9F s.initSequence.prechargePeriod = 0x22 } - if err = s.Init(); err != nil { - return err - } - if err = s.On(); err != nil { + if err := s.Init(); err != nil { return err } - return nil + + return s.On() } diff --git a/drivers/i2c/ssd1306_driver_test.go b/drivers/i2c/ssd1306_driver_test.go index 204c6dbd8..58cec23ef 100644 --- a/drivers/i2c/ssd1306_driver_test.go +++ b/drivers/i2c/ssd1306_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package i2c import ( @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/th02_driver.go b/drivers/i2c/th02_driver.go index bf29309e7..2680a4239 100644 --- a/drivers/i2c/th02_driver.go +++ b/drivers/i2c/th02_driver.go @@ -154,6 +154,8 @@ func (s *TH02Driver) Heater() (bool, error) { } // Sample returns the temperature in celsius and relative humidity for one sample +// +//nolint:nonamedreturns // is sufficient here func (s *TH02Driver) Sample() (temperature float32, relhumidity float32, _ error) { s.mutex.Lock() defer s.mutex.Unlock() @@ -179,8 +181,7 @@ func (s *TH02Driver) Sample() (temperature float32, relhumidity float32, _ error } temperature = float32(rawt>>2)/32.0 - 50.0 - switch s.Units { - case "F": + if s.Units == "F" { temperature = 9.0/5.0*temperature + 32.0 } diff --git a/drivers/i2c/th02_driver_test.go b/drivers/i2c/th02_driver_test.go index 369900629..ca8bc5392 100644 --- a/drivers/i2c/th02_driver_test.go +++ b/drivers/i2c/th02_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/tsl2561_driver.go b/drivers/i2c/tsl2561_driver.go index cc3ff7160..44e94ac58 100644 --- a/drivers/i2c/tsl2561_driver.go +++ b/drivers/i2c/tsl2561_driver.go @@ -241,41 +241,44 @@ func (d *TSL2561Driver) SetGain(gain TSL2561Gain) error { // GetLuminocity gets the broadband and IR only values from the TSL2561, // adjusting gain if auto-gain is enabled -func (d *TSL2561Driver) GetLuminocity() (broadband uint16, ir uint16, err error) { +func (d *TSL2561Driver) GetLuminocity() (uint16, uint16, error) { // if auto gain disabled get a single reading and continue if !d.autoGain { - broadband, ir, err = d.getData() - return + return d.getData() } agcCheck := false hi, lo := d.getHiLo() // Read data until we find a valid range + var broadband uint16 + var ir uint16 + var err error valid := false for { broadband, ir, err = d.getData() if err != nil { - return + return broadband, ir, err } // Run an auto-gain check if we haven't already done so if !agcCheck { - if (broadband < lo) && (d.gain == TSL2561Gain1X) { + switch { + case (broadband < lo) && (d.gain == TSL2561Gain1X): // increase gain and try again err = d.SetGain(TSL2561Gain16X) if err != nil { - return + return broadband, ir, err } agcCheck = true - } else if (broadband > hi) && (d.gain == TSL2561Gain16X) { + case (broadband > hi) && (d.gain == TSL2561Gain16X): // drop gain and try again err = d.SetGain(TSL2561Gain1X) if err != nil { - return + return broadband, ir, err } agcCheck = true - } else { + default: // Reading is either valid, or we're already at the chips // limits valid = true @@ -292,12 +295,12 @@ func (d *TSL2561Driver) GetLuminocity() (broadband uint16, ir uint16, err error) } } - return + return broadband, ir, err } // CalculateLux converts raw sensor values to the standard SI Lux equivalent. // Returns 65536 if the sensor is saturated. -func (d *TSL2561Driver) CalculateLux(broadband uint16, ir uint16) (lux uint32) { +func (d *TSL2561Driver) CalculateLux(broadband uint16, ir uint16) uint32 { var channel1 uint32 var channel0 uint32 @@ -336,45 +339,44 @@ func (d *TSL2561Driver) CalculateLux(broadband uint16, ir uint16) (lux uint32) { temp += (1 << (tsl2561LuxLuxScale - 1)) // Strip off fractional portion - lux = temp >> tsl2561LuxLuxScale + lux := temp >> tsl2561LuxLuxScale return lux } -func (d *TSL2561Driver) enable() (err error) { - err = d.connection.WriteByteData(uint8(tsl2561CommandBit|tsl2561RegisterControl), tsl2561ControlPowerOn) - return err +func (d *TSL2561Driver) enable() error { + return d.connection.WriteByteData(uint8(tsl2561CommandBit|tsl2561RegisterControl), tsl2561ControlPowerOn) } -func (d *TSL2561Driver) disable() (err error) { - err = d.connection.WriteByteData(uint8(tsl2561CommandBit|tsl2561RegisterControl), tsl2561ControlPowerOff) - return err +func (d *TSL2561Driver) disable() error { + return d.connection.WriteByteData(uint8(tsl2561CommandBit|tsl2561RegisterControl), tsl2561ControlPowerOff) } -func (d *TSL2561Driver) getData() (broadband uint16, ir uint16, err error) { - if err = d.enable(); err != nil { - return +func (d *TSL2561Driver) getData() (uint16, uint16, error) { + if err := d.enable(); err != nil { + return 0, 0, err } d.waitForADC() // Reads a two byte value from channel 0 (visible + infrared) - broadband, err = d.connection.ReadWordData(tsl2561CommandBit | tsl2561WordBit | tsl2561RegisterChan0Low) + broadband, err := d.connection.ReadWordData(tsl2561CommandBit | tsl2561WordBit | tsl2561RegisterChan0Low) if err != nil { - return + return 0, 0, err } // Reads a two byte value from channel 1 (infrared) - ir, err = d.connection.ReadWordData(tsl2561CommandBit | tsl2561WordBit | tsl2561RegisterChan1Low) + ir, err := d.connection.ReadWordData(tsl2561CommandBit | tsl2561WordBit | tsl2561RegisterChan1Low) if err != nil { - return + return 0, 0, err } err = d.disable() - return + return broadband, ir, err } +//nolint:nonamedreturns // is sufficient here func (d *TSL2561Driver) getHiLo() (hi, lo uint16) { switch d.integrationTime { case TSL2561IntegrationTime13MS: @@ -390,6 +392,7 @@ func (d *TSL2561Driver) getHiLo() (hi, lo uint16) { return } +//nolint:nonamedreturns // is sufficient here func (d *TSL2561Driver) getClipScaling() (clipThreshold uint16, chScale uint32) { switch d.integrationTime { case TSL2561IntegrationTime13MS: @@ -405,6 +408,7 @@ func (d *TSL2561Driver) getClipScaling() (clipThreshold uint16, chScale uint32) return } +//nolint:nonamedreturns // is sufficient here func (d *TSL2561Driver) getBM(ratio uint32) (b uint32, m uint32) { switch { case ratio <= tsl2561LuxK1T: diff --git a/drivers/i2c/tsl2561_driver_test.go b/drivers/i2c/tsl2561_driver_test.go index a027b9abf..573a2c89f 100644 --- a/drivers/i2c/tsl2561_driver_test.go +++ b/drivers/i2c/tsl2561_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/wiichuck_driver.go b/drivers/i2c/wiichuck_driver.go index fc2d305bd..c78f0b67a 100644 --- a/drivers/i2c/wiichuck_driver.go +++ b/drivers/i2c/wiichuck_driver.go @@ -158,7 +158,7 @@ func (w *WiichuckDriver) parse(value []byte) { } // reads from adaptor using specified interval to update with new value -func (w *WiichuckDriver) initialize() (err error) { +func (w *WiichuckDriver) initialize() error { go func() { for { if _, err := w.connection.Write([]byte{0x40, 0x00}); err != nil { @@ -186,5 +186,5 @@ func (w *WiichuckDriver) initialize() (err error) { time.Sleep(w.interval) } }() - return + return nil } diff --git a/drivers/i2c/wiichuck_driver_test.go b/drivers/i2c/wiichuck_driver_test.go index 348336d9a..0f2b40109 100644 --- a/drivers/i2c/wiichuck_driver_test.go +++ b/drivers/i2c/wiichuck_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/i2c/yl40_driver.go b/drivers/i2c/yl40_driver.go index 4509ddfeb..b740150fe 100644 --- a/drivers/i2c/yl40_driver.go +++ b/drivers/i2c/yl40_driver.go @@ -186,7 +186,7 @@ func WithYL40OutputScaler(scaler func(input float64) (value int)) func(Config) { } // Start initializes the driver -func (y *YL40Driver) Start() (err error) { +func (y *YL40Driver) Start() error { // must be the first one if err := y.PCF8591Driver.Start(); err != nil { return err @@ -210,7 +210,7 @@ func (y *YL40Driver) Start() (err error) { } // Halt stops the driver -func (y *YL40Driver) Halt() (err error) { +func (y *YL40Driver) Halt() error { // we try halt on each device, not stopping on the first error var errors []string if err := y.aBri.Halt(); err != nil { @@ -240,7 +240,7 @@ func (y *YL40Driver) Halt() (err error) { // Read returns the current reading from the given pin of the driver // For the analog output pin the last written value is returned -func (y *YL40Driver) Read(pin YL40Pin) (val float64, err error) { +func (y *YL40Driver) Read(pin YL40Pin) (float64, error) { switch pin { case YL40Bri: return y.aBri.Read() @@ -258,27 +258,27 @@ func (y *YL40Driver) Read(pin YL40Pin) (val float64, err error) { } // ReadBrightness returns the current reading from brightness pin of the driver -func (y *YL40Driver) ReadBrightness() (val float64, err error) { +func (y *YL40Driver) ReadBrightness() (float64, error) { return y.Read(YL40Bri) } // ReadTemperature returns the current reading from temperature pin of the driver -func (y *YL40Driver) ReadTemperature() (val float64, err error) { +func (y *YL40Driver) ReadTemperature() (float64, error) { return y.Read(YL40Temp) } // ReadAIN2 returns the current reading from analog input pin 2 pin of the driver -func (y *YL40Driver) ReadAIN2() (val float64, err error) { +func (y *YL40Driver) ReadAIN2() (float64, error) { return y.Read(YL40AIN2) } // ReadPotentiometer returns the current reading from potentiometer pin of the driver -func (y *YL40Driver) ReadPotentiometer() (val float64, err error) { +func (y *YL40Driver) ReadPotentiometer() (float64, error) { return y.Read(YL40Poti) } // Value returns the last read or written value from the given pin of the driver -func (y *YL40Driver) Value(pin YL40Pin) (val float64, err error) { +func (y *YL40Driver) Value(pin YL40Pin) (float64, error) { switch pin { case YL40Bri: return y.aBri.Value(), nil @@ -296,31 +296,31 @@ func (y *YL40Driver) Value(pin YL40Pin) (val float64, err error) { } // Brightness returns the last read brightness of the driver -func (y *YL40Driver) Brightness() (val float64, err error) { +func (y *YL40Driver) Brightness() (float64, error) { return y.Value(YL40Bri) } // Temperature returns the last read temperature of the driver -func (y *YL40Driver) Temperature() (val float64, err error) { +func (y *YL40Driver) Temperature() (float64, error) { return y.Value(YL40Temp) } // AIN2 returns the last read analog input value of the driver -func (y *YL40Driver) AIN2() (val float64, err error) { +func (y *YL40Driver) AIN2() (float64, error) { return y.Value(YL40AIN2) } // Potentiometer returns the last read potentiometer value of the driver -func (y *YL40Driver) Potentiometer() (val float64, err error) { +func (y *YL40Driver) Potentiometer() (float64, error) { return y.Value(YL40Poti) } // AOUT returns the last written value of the driver -func (y *YL40Driver) AOUT() (val float64, err error) { +func (y *YL40Driver) AOUT() (float64, error) { return y.Value(YL40AOUT) } // Write writes the given value to the analog output -func (y *YL40Driver) Write(val float64) (err error) { +func (y *YL40Driver) Write(val float64) error { return y.aOut.Write(val) } diff --git a/drivers/i2c/yl40_driver_test.go b/drivers/i2c/yl40_driver_test.go index 2975ceec1..91ea22ffb 100644 --- a/drivers/i2c/yl40_driver_test.go +++ b/drivers/i2c/yl40_driver_test.go @@ -56,10 +56,10 @@ func TestYL40DriverWithYL40Interval(t *testing.T) { func TestYL40DriverWithYL40InputScaler(t *testing.T) { // arrange yl := NewYL40Driver(newI2cTestAdaptor()) - f1 := func(input int) (value float64) { return 0.1 } - f2 := func(input int) (value float64) { return 0.2 } - f3 := func(input int) (value float64) { return 0.3 } - f4 := func(input int) (value float64) { return 0.4 } + f1 := func(input int) float64 { return 0.1 } + f2 := func(input int) float64 { return 0.2 } + f3 := func(input int) float64 { return 0.3 } + f4 := func(input int) float64 { return 0.4 } // act WithYL40InputScaler(YL40Bri, f1)(yl) WithYL40InputScaler(YL40Temp, f2)(yl) @@ -75,7 +75,7 @@ func TestYL40DriverWithYL40InputScaler(t *testing.T) { func TestYL40DriverWithYL40WithYL40OutputScaler(t *testing.T) { // arrange yl := NewYL40Driver(newI2cTestAdaptor()) - fo := func(input float64) (value int) { return 123 } + fo := func(input float64) int { return 123 } // act WithYL40OutputScaler(fo)(yl) // assert diff --git a/drivers/spi/apa102_test.go b/drivers/spi/apa102_test.go index bca281a5f..5a032d95d 100644 --- a/drivers/spi/apa102_test.go +++ b/drivers/spi/apa102_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/spi/mcp3002.go b/drivers/spi/mcp3002.go index 5358f67e6..44b0b9911 100644 --- a/drivers/spi/mcp3002.go +++ b/drivers/spi/mcp3002.go @@ -56,9 +56,7 @@ func (d *MCP3002Driver) Read(channel int) (int, error) { } // AnalogRead returns value from analog reading of specified pin -func (d *MCP3002Driver) AnalogRead(pin string) (value int, err error) { +func (d *MCP3002Driver) AnalogRead(pin string) (int, error) { channel, _ := strconv.Atoi(pin) - value, err = d.Read(channel) - - return + return d.Read(channel) } diff --git a/drivers/spi/mcp3002_test.go b/drivers/spi/mcp3002_test.go index c8b341d17..1b8c5f914 100644 --- a/drivers/spi/mcp3002_test.go +++ b/drivers/spi/mcp3002_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) diff --git a/drivers/spi/mcp3004.go b/drivers/spi/mcp3004.go index eb5d77ee8..3f7b739a0 100644 --- a/drivers/spi/mcp3004.go +++ b/drivers/spi/mcp3004.go @@ -37,7 +37,7 @@ func NewMCP3004Driver(a Connector, options ...func(Config)) *MCP3004Driver { } // Read reads the current analog data for the desired channel. -func (d *MCP3004Driver) Read(channel int) (result int, err error) { +func (d *MCP3004Driver) Read(channel int) (int, error) { if channel < 0 || channel > MCP3004DriverMaxChannel-1 { return 0, fmt.Errorf("Invalid channel '%d' for read", channel) } @@ -49,18 +49,17 @@ func (d *MCP3004Driver) Read(channel int) (result int, err error) { rx := make([]byte, 3) - err = d.connection.ReadCommandData(tx, rx) - if err == nil && len(rx) == 3 { - result = int((rx[1]&0x3))<<8 + int(rx[2]) + if err := d.connection.ReadCommandData(tx, rx); err != nil || len(rx) != 3 { + return 0, err } - return result, err + result := int((rx[1]&0x3))<<8 + int(rx[2]) + + return result, nil } // AnalogRead returns value from analog reading of specified pin -func (d *MCP3004Driver) AnalogRead(pin string) (value int, err error) { +func (d *MCP3004Driver) AnalogRead(pin string) (int, error) { channel, _ := strconv.Atoi(pin) - value, err = d.Read(channel) - - return + return d.Read(channel) } diff --git a/drivers/spi/mcp3004_test.go b/drivers/spi/mcp3004_test.go index c6b0660b7..2eeb69408 100644 --- a/drivers/spi/mcp3004_test.go +++ b/drivers/spi/mcp3004_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) diff --git a/drivers/spi/mcp3008.go b/drivers/spi/mcp3008.go index 15a1f1622..ca6044967 100644 --- a/drivers/spi/mcp3008.go +++ b/drivers/spi/mcp3008.go @@ -37,7 +37,7 @@ func NewMCP3008Driver(a Connector, options ...func(Config)) *MCP3008Driver { } // Read reads the current analog data for the desired channel. -func (d *MCP3008Driver) Read(channel int) (result int, err error) { +func (d *MCP3008Driver) Read(channel int) (int, error) { if channel < 0 || channel > MCP3008DriverMaxChannel-1 { return 0, fmt.Errorf("Invalid channel '%d' for read", channel) } @@ -49,18 +49,17 @@ func (d *MCP3008Driver) Read(channel int) (result int, err error) { rx := make([]byte, 3) - err = d.connection.ReadCommandData(tx, rx) - if err == nil && len(rx) == 3 { - result = int((rx[1]&0x3))<<8 + int(rx[2]) + if err := d.connection.ReadCommandData(tx, rx); err != nil || len(rx) != 3 { + return 0, err } - return result, err + result := int((rx[1]&0x3))<<8 + int(rx[2]) + + return result, nil } // AnalogRead returns value from analog reading of specified pin -func (d *MCP3008Driver) AnalogRead(pin string) (value int, err error) { +func (d *MCP3008Driver) AnalogRead(pin string) (int, error) { channel, _ := strconv.Atoi(pin) - value, err = d.Read(channel) - - return + return d.Read(channel) } diff --git a/drivers/spi/mcp3008_test.go b/drivers/spi/mcp3008_test.go index 4ad5d91a6..6c85a9b91 100644 --- a/drivers/spi/mcp3008_test.go +++ b/drivers/spi/mcp3008_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) diff --git a/drivers/spi/mcp3202.go b/drivers/spi/mcp3202.go index 6c687c8a4..575adce95 100644 --- a/drivers/spi/mcp3202.go +++ b/drivers/spi/mcp3202.go @@ -39,7 +39,7 @@ func NewMCP3202Driver(a Connector, options ...func(Config)) *MCP3202Driver { } // Read reads the current analog data for the desired channel. -func (d *MCP3202Driver) Read(channel int) (result int, err error) { +func (d *MCP3202Driver) Read(channel int) (int, error) { if channel < 0 || channel > MCP3202DriverMaxChannel-1 { return 0, fmt.Errorf("Invalid channel '%d' for read", channel) } @@ -51,21 +51,22 @@ func (d *MCP3202Driver) Read(channel int) (result int, err error) { rx := make([]byte, 3) - err = d.connection.ReadCommandData(tx, rx) - if err == nil && len(rx) == 3 { - result = int((rx[1]&0xf))<<8 + int(rx[2]) + if err := d.connection.ReadCommandData(tx, rx); err != nil || len(rx) != 3 { + return 0, err } - return result, err + result := int((rx[1]&0xf))<<8 + int(rx[2]) + + return result, nil } // AnalogRead returns value from analog reading of specified pin, scaled to 0-1023 value. -func (d *MCP3202Driver) AnalogRead(pin string) (value int, err error) { +func (d *MCP3202Driver) AnalogRead(pin string) (int, error) { channel, _ := strconv.Atoi(pin) - value, err = d.Read(channel) + value, err := d.Read(channel) if err != nil { - value = int(gobot.ToScale(gobot.FromScale(float64(value), 0, 4095), 0, 1023)) + return 0, err } - return + return int(gobot.ToScale(gobot.FromScale(float64(value), 0, 4095), 0, 1023)), err } diff --git a/drivers/spi/mcp3202_test.go b/drivers/spi/mcp3202_test.go index ec414964b..15729617f 100644 --- a/drivers/spi/mcp3202_test.go +++ b/drivers/spi/mcp3202_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) diff --git a/drivers/spi/mcp3204.go b/drivers/spi/mcp3204.go index d8deaf42f..aa05b480c 100644 --- a/drivers/spi/mcp3204.go +++ b/drivers/spi/mcp3204.go @@ -39,7 +39,7 @@ func NewMCP3204Driver(a Connector, options ...func(Config)) *MCP3204Driver { } // Read reads the current analog data for the desired channel. -func (d *MCP3204Driver) Read(channel int) (result int, err error) { +func (d *MCP3204Driver) Read(channel int) (int, error) { if channel < 0 || channel > MCP3204DriverMaxChannel-1 { return 0, fmt.Errorf("Invalid channel '%d' for read", channel) } @@ -51,21 +51,22 @@ func (d *MCP3204Driver) Read(channel int) (result int, err error) { rx := make([]byte, 3) - err = d.connection.ReadCommandData(tx, rx) - if err == nil && len(rx) == 3 { - result = int((rx[1]&0xf))<<8 + int(rx[2]) + if err := d.connection.ReadCommandData(tx, rx); err != nil || len(rx) != 3 { + return 0, err } - return result, err + result := int((rx[1]&0xf))<<8 + int(rx[2]) + + return result, nil } // AnalogRead returns value from analog reading of specified pin, scaled to 0-1023 value. -func (d *MCP3204Driver) AnalogRead(pin string) (value int, err error) { +func (d *MCP3204Driver) AnalogRead(pin string) (int, error) { channel, _ := strconv.Atoi(pin) - value, err = d.Read(channel) + value, err := d.Read(channel) if err != nil { - value = int(gobot.ToScale(gobot.FromScale(float64(value), 0, 4095), 0, 1023)) + return 0, err } - return + return int(gobot.ToScale(gobot.FromScale(float64(value), 0, 4095), 0, 1023)), err } diff --git a/drivers/spi/mcp3204_test.go b/drivers/spi/mcp3204_test.go index c948fe630..11fc103e3 100644 --- a/drivers/spi/mcp3204_test.go +++ b/drivers/spi/mcp3204_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) diff --git a/drivers/spi/mcp3208.go b/drivers/spi/mcp3208.go index 274e46e74..f8886e95c 100644 --- a/drivers/spi/mcp3208.go +++ b/drivers/spi/mcp3208.go @@ -39,7 +39,7 @@ func NewMCP3208Driver(a Connector, options ...func(Config)) *MCP3208Driver { } // Read reads the current analog data for the desired channel. -func (d *MCP3208Driver) Read(channel int) (result int, err error) { +func (d *MCP3208Driver) Read(channel int) (int, error) { if channel < 0 || channel > MCP3208DriverMaxChannel-1 { return 0, fmt.Errorf("Invalid channel '%d' for read", channel) } @@ -51,21 +51,22 @@ func (d *MCP3208Driver) Read(channel int) (result int, err error) { rx := make([]byte, 3) - err = d.connection.ReadCommandData(tx, rx) - if err == nil && len(rx) == 3 { - result = int((rx[1]&0xf))<<8 + int(rx[2]) + if err := d.connection.ReadCommandData(tx, rx); err != nil || len(rx) != 3 { + return 0, err } - return result, err + result := int((rx[1]&0xf))<<8 + int(rx[2]) + + return result, nil } // AnalogRead returns value from analog reading of specified pin, scaled to 0-1023 value. -func (d *MCP3208Driver) AnalogRead(pin string) (value int, err error) { +func (d *MCP3208Driver) AnalogRead(pin string) (int, error) { channel, _ := strconv.Atoi(pin) - value, err = d.Read(channel) + value, err := d.Read(channel) if err != nil { - value = int(gobot.ToScale(gobot.FromScale(float64(value), 0, 4095), 0, 1023)) + return 0, err } - return + return int(gobot.ToScale(gobot.FromScale(float64(value), 0, 4095), 0, 1023)), err } diff --git a/drivers/spi/mcp3208_test.go b/drivers/spi/mcp3208_test.go index 9150aa61d..7bfe0d32f 100644 --- a/drivers/spi/mcp3208_test.go +++ b/drivers/spi/mcp3208_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) diff --git a/drivers/spi/mcp3304.go b/drivers/spi/mcp3304.go index 1f6aa58fb..d3dff61ab 100644 --- a/drivers/spi/mcp3304.go +++ b/drivers/spi/mcp3304.go @@ -39,7 +39,7 @@ func NewMCP3304Driver(a Connector, options ...func(Config)) *MCP3304Driver { } // Read reads the current analog data for the desired channel. -func (d *MCP3304Driver) Read(channel int) (result int, err error) { +func (d *MCP3304Driver) Read(channel int) (int, error) { if channel < 0 || channel > MCP3304DriverMaxChannel-1 { return 0, fmt.Errorf("Invalid channel '%d' for read", channel) } @@ -51,21 +51,22 @@ func (d *MCP3304Driver) Read(channel int) (result int, err error) { rx := make([]byte, 3) - err = d.connection.ReadCommandData(tx, rx) - if err == nil && len(rx) == 3 { - result = int((rx[1]&0xf))<<8 + int(rx[2]) + if err := d.connection.ReadCommandData(tx, rx); err != nil || len(rx) != 3 { + return 0, err } - return result, err + result := int((rx[1]&0xf))<<8 + int(rx[2]) + + return result, nil } // AnalogRead returns value from analog reading of specified pin, scaled to 0-1023 value. -func (d *MCP3304Driver) AnalogRead(pin string) (value int, err error) { +func (d *MCP3304Driver) AnalogRead(pin string) (int, error) { channel, _ := strconv.Atoi(pin) - value, err = d.Read(channel) + value, err := d.Read(channel) if err != nil { - value = int(gobot.ToScale(gobot.FromScale(float64(value), 0, 4095), 0, 1023)) + return 0, err } - return + return int(gobot.ToScale(gobot.FromScale(float64(value), 0, 4095), 0, 1023)), err } diff --git a/drivers/spi/mcp3304_test.go b/drivers/spi/mcp3304_test.go index b9a3b3860..e928795fe 100644 --- a/drivers/spi/mcp3304_test.go +++ b/drivers/spi/mcp3304_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" ) diff --git a/drivers/spi/mfrc522_driver_test.go b/drivers/spi/mfrc522_driver_test.go index bbfc54715..1bd88baca 100644 --- a/drivers/spi/mfrc522_driver_test.go +++ b/drivers/spi/mfrc522_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/spi/spi_connection_test.go b/drivers/spi/spi_connection_test.go index d849e96b5..1d4d94ad7 100644 --- a/drivers/spi/spi_connection_test.go +++ b/drivers/spi/spi_connection_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) diff --git a/drivers/spi/spi_driver.go b/drivers/spi/spi_driver.go index b18acc6a3..b25878596 100644 --- a/drivers/spi/spi_driver.go +++ b/drivers/spi/spi_driver.go @@ -1,6 +1,7 @@ package spi import ( + "log" "sync" "gobot.io/x/gobot/v2" @@ -108,7 +109,14 @@ func (d *Driver) Name() string { return d.name } func (d *Driver) SetName(n string) { d.name = n } // Connection returns the Connection of the device. -func (d *Driver) Connection() gobot.Connection { return d.connector.(gobot.Connection) } +func (d *Driver) Connection() gobot.Connection { + if conn, ok := d.connector.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil +} // Start initializes the driver. func (d *Driver) Start() error { @@ -130,7 +138,7 @@ func (d *Driver) Start() error { } // Halt stops the driver. -func (d *Driver) Halt() (err error) { +func (d *Driver) Halt() error { d.mutex.Lock() defer d.mutex.Unlock() diff --git a/drivers/spi/spi_driver_test.go b/drivers/spi/spi_driver_test.go index 60ecb2b75..9f35c5591 100644 --- a/drivers/spi/spi_driver_test.go +++ b/drivers/spi/spi_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/drivers/spi/ssd1306_driver.go b/drivers/spi/ssd1306_driver.go index e57ac28a5..819a6a2a7 100644 --- a/drivers/spi/ssd1306_driver.go +++ b/drivers/spi/ssd1306_driver.go @@ -169,11 +169,13 @@ func NewSSD1306Driver(a gobot.Adaptor, options ...func(Config)) *SSD1306Driver { err := s.Clear() return map[string]interface{}{"err": err} }) + //nolint:forcetypeassert // ok here s.AddCommand("SetContrast", func(params map[string]interface{}) interface{} { contrast := params["contrast"].(byte) err := s.SetContrast(contrast) return map[string]interface{}{"err": err} }) + //nolint:forcetypeassert // ok here s.AddCommand("Set", func(params map[string]interface{}) interface{} { x := params["x"].(int) y := params["y"].(int) diff --git a/drivers/spi/ssd1306_driver_test.go b/drivers/spi/ssd1306_driver_test.go index 57b39b7fc..b72765196 100644 --- a/drivers/spi/ssd1306_driver_test.go +++ b/drivers/spi/ssd1306_driver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -49,65 +50,65 @@ type gpioTestAdaptor struct { port string mtx sync.Mutex Connector - digitalWriteFunc func() (err error) - servoWriteFunc func() (err error) - pwmWriteFunc func() (err error) + digitalWriteFunc func() error + servoWriteFunc func() error + pwmWriteFunc func() error analogReadFunc func() (val int, err error) digitalReadFunc func() (val int, err error) } -func (t *gpioTestAdaptor) ServoWrite(string, byte) (err error) { +func (t *gpioTestAdaptor) ServoWrite(string, byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.servoWriteFunc() } -func (t *gpioTestAdaptor) PwmWrite(string, byte) (err error) { +func (t *gpioTestAdaptor) PwmWrite(string, byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.pwmWriteFunc() } -func (t *gpioTestAdaptor) AnalogRead(string) (val int, err error) { +func (t *gpioTestAdaptor) AnalogRead(string) (int, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.analogReadFunc() } -func (t *gpioTestAdaptor) DigitalRead(string) (val int, err error) { +func (t *gpioTestAdaptor) DigitalRead(string) (int, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.digitalReadFunc() } -func (t *gpioTestAdaptor) DigitalWrite(string, byte) (err error) { +func (t *gpioTestAdaptor) DigitalWrite(string, byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.digitalWriteFunc() } -func (t *gpioTestAdaptor) Connect() (err error) { return } -func (t *gpioTestAdaptor) Finalize() (err error) { return } -func (t *gpioTestAdaptor) Name() string { return t.name } -func (t *gpioTestAdaptor) SetName(n string) { t.name = n } -func (t *gpioTestAdaptor) Port() string { return t.port } +func (t *gpioTestAdaptor) Connect() error { return nil } +func (t *gpioTestAdaptor) Finalize() error { return nil } +func (t *gpioTestAdaptor) Name() string { return t.name } +func (t *gpioTestAdaptor) SetName(n string) { t.name = n } +func (t *gpioTestAdaptor) Port() string { return t.port } func newGpioTestAdaptor() *gpioTestAdaptor { a := newSpiTestAdaptor() return &gpioTestAdaptor{ port: "/dev/null", - digitalWriteFunc: func() (err error) { + digitalWriteFunc: func() error { return nil }, - servoWriteFunc: func() (err error) { + servoWriteFunc: func() error { return nil }, - pwmWriteFunc: func() (err error) { + pwmWriteFunc: func() error { return nil }, - analogReadFunc: func() (val int, err error) { + analogReadFunc: func() (int, error) { return 99, nil }, - digitalReadFunc: func() (val int, err error) { + digitalReadFunc: func() (int, error) { return 1, nil }, Connector: a, diff --git a/eventer.go b/eventer.go index dacda7c5a..fce3c2362 100644 --- a/eventer.go +++ b/eventer.go @@ -46,10 +46,10 @@ type Eventer interface { Unsubscribe(events eventChannel) // Event handler - On(name string, f func(s interface{})) (err error) + On(name string, f func(s interface{})) error // Event handler, only executes one time - Once(name string, f func(s interface{})) (err error) + Once(name string, f func(s interface{})) error } // NewEventer returns a new Eventer. @@ -119,7 +119,7 @@ func (e *eventer) Unsubscribe(events eventChannel) { } // On executes the event handler f when e is Published to. -func (e *eventer) On(n string, f func(s interface{})) (err error) { +func (e *eventer) On(n string, f func(s interface{})) error { out := e.Subscribe() go func() { for { @@ -130,11 +130,11 @@ func (e *eventer) On(n string, f func(s interface{})) (err error) { } }() - return + return nil } // Once is similar to On except that it only executes f one time. -func (e *eventer) Once(n string, f func(s interface{})) (err error) { +func (e *eventer) Once(n string, f func(s interface{})) error { out := e.Subscribe() go func() { ProcessEvents: @@ -147,5 +147,5 @@ func (e *eventer) Once(n string, f func(s interface{})) (err error) { } }() - return + return nil } diff --git a/examples/batty.go b/examples/batty.go index 918e99440..7ea6aa7f4 100644 --- a/examples/batty.go +++ b/examples/batty.go @@ -52,11 +52,11 @@ type loopbackAdaptor struct { port string } -func (t *loopbackAdaptor) Finalize() (err error) { return } -func (t *loopbackAdaptor) Connect() (err error) { return } -func (t *loopbackAdaptor) Name() string { return t.name } -func (t *loopbackAdaptor) SetName(n string) { t.name = n } -func (t *loopbackAdaptor) Port() string { return t.port } +func (t *loopbackAdaptor) Finalize() error { return nil } +func (t *loopbackAdaptor) Connect() error { return nil } +func (t *loopbackAdaptor) Name() string { return t.name } +func (t *loopbackAdaptor) SetName(n string) { t.name = n } +func (t *loopbackAdaptor) Port() string { return t.port } func NewLoopbackAdaptor(port string) *loopbackAdaptor { return &loopbackAdaptor{ @@ -75,8 +75,8 @@ type pingDriver struct { gobot.Commander } -func (t *pingDriver) Start() (err error) { return } -func (t *pingDriver) Halt() (err error) { return } +func (t *pingDriver) Start() error { return nil } +func (t *pingDriver) Halt() error { return nil } func (t *pingDriver) Name() string { return t.name } func (t *pingDriver) SetName(n string) { t.name = n } func (t *pingDriver) Pin() string { return t.pin } diff --git a/examples/raspi_adafruit2327_servo.go b/examples/raspi_adafruit2327_servo.go index b34f1b6c4..9a93aa985 100644 --- a/examples/raspi_adafruit2327_servo.go +++ b/examples/raspi_adafruit2327_servo.go @@ -51,7 +51,7 @@ func main() { robot.Start() } -func adafruitServoMotorRunner(a *i2c.Adafruit2327Driver) (err error) { +func adafruitServoMotorRunner(a *i2c.Adafruit2327Driver) error { log.Printf("Servo Motor Run Loop...\n") var channel byte = 1 @@ -59,30 +59,30 @@ func adafruitServoMotorRunner(a *i2c.Adafruit2327Driver) (err error) { // Do not need to set this every run loop freq := 60.0 - if err = a.SetServoMotorFreq(freq); err != nil { + if err := a.SetServoMotorFreq(freq); err != nil { log.Printf("%s", err.Error()) - return + return err } // start in the middle of the 180-deg range pulse := degree2pulse(deg) - if err = a.SetServoMotorPulse(channel, 0, pulse); err != nil { + if err := a.SetServoMotorPulse(channel, 0, pulse); err != nil { log.Printf(err.Error()) - return + return err } // INCR pulse = degree2pulse(deg + degIncrease) - if err = a.SetServoMotorPulse(channel, 0, pulse); err != nil { + if err := a.SetServoMotorPulse(channel, 0, pulse); err != nil { log.Printf(err.Error()) - return + return err } time.Sleep(2000 * time.Millisecond) // DECR pulse = degree2pulse(deg - degIncrease) - if err = a.SetServoMotorPulse(channel, 0, pulse); err != nil { + if err := a.SetServoMotorPulse(channel, 0, pulse); err != nil { log.Printf(err.Error()) - return + return err } - return + return nil } func degree2pulse(deg int) int32 { diff --git a/examples/raspi_adafruit2348_dcmotor.go b/examples/raspi_adafruit2348_dcmotor.go index c617d0b48..b15967109 100644 --- a/examples/raspi_adafruit2348_dcmotor.go +++ b/examples/raspi_adafruit2348_dcmotor.go @@ -37,30 +37,30 @@ func main() { robot.Start() } -func adafruitDCMotorRunner(a *i2c.Adafruit2348Driver, dcMotor int) (err error) { +func adafruitDCMotorRunner(a *i2c.Adafruit2348Driver, dcMotor int) error { log.Printf("DC Motor Run Loop...\n") // set the speed: var speed int32 = 255 // 255 = full speed! - if err = a.SetDCMotorSpeed(dcMotor, speed); err != nil { - return + if err := a.SetDCMotorSpeed(dcMotor, speed); err != nil { + return err } // run FORWARD - if err = a.RunDCMotor(dcMotor, i2c.Adafruit2348Forward); err != nil { - return + if err := a.RunDCMotor(dcMotor, i2c.Adafruit2348Forward); err != nil { + return err } // Sleep and RELEASE time.Sleep(2000 * time.Millisecond) - if err = a.RunDCMotor(dcMotor, i2c.Adafruit2348Release); err != nil { - return + if err := a.RunDCMotor(dcMotor, i2c.Adafruit2348Release); err != nil { + return err } // run BACKWARD - if err = a.RunDCMotor(dcMotor, i2c.Adafruit2348Backward); err != nil { - return + if err := a.RunDCMotor(dcMotor, i2c.Adafruit2348Backward); err != nil { + return err } // Sleep and RELEASE time.Sleep(2000 * time.Millisecond) - if err = a.RunDCMotor(dcMotor, i2c.Adafruit2348Release); err != nil { - return + if err := a.RunDCMotor(dcMotor, i2c.Adafruit2348Release); err != nil { + return err } - return + return nil } diff --git a/examples/raspi_adafruit2348_stepper.go b/examples/raspi_adafruit2348_stepper.go index cbac4bc6e..c1eb80f38 100644 --- a/examples/raspi_adafruit2348_stepper.go +++ b/examples/raspi_adafruit2348_stepper.go @@ -37,7 +37,7 @@ func main() { robot.Start() } -func adafruitStepperMotorRunner(a *i2c.Adafruit2348Driver, motor int) (err error) { +func adafruitStepperMotorRunner(a *i2c.Adafruit2348Driver, motor int) error { log.Printf("Stepper Motor Run Loop...\n") // set the speed state: speed := 30 // rpm @@ -46,13 +46,13 @@ func adafruitStepperMotorRunner(a *i2c.Adafruit2348Driver, motor int) (err error a.SetStepperMotorSpeed(motor, speed) - if err = a.Step(motor, steps, i2c.Adafruit2348Forward, style); err != nil { + if err := a.Step(motor, steps, i2c.Adafruit2348Forward, style); err != nil { log.Printf(err.Error()) - return + return err } - if err = a.Step(motor, steps, i2c.Adafruit2348Backward, style); err != nil { + if err := a.Step(motor, steps, i2c.Adafruit2348Backward, style); err != nil { log.Printf(err.Error()) - return + return err } - return + return nil } diff --git a/helpers_test.go b/helpers_test.go index dee5d39a1..1c0206c00 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -24,12 +24,12 @@ type testDriver struct { } var ( - testDriverStart = func() (err error) { return } - testDriverHalt = func() (err error) { return } + testDriverStart = func() error { return nil } + testDriverHalt = func() error { return nil } ) -func (t *testDriver) Start() (err error) { return testDriverStart() } -func (t *testDriver) Halt() (err error) { return testDriverHalt() } +func (t *testDriver) Start() error { return testDriverStart() } +func (t *testDriver) Halt() error { return testDriverHalt() } func (t *testDriver) Name() string { return t.name } func (t *testDriver) SetName(n string) { t.name = n } func (t *testDriver) Pin() string { return t.pin } @@ -54,15 +54,15 @@ type testAdaptor struct { } var ( - testAdaptorConnect = func() (err error) { return } - testAdaptorFinalize = func() (err error) { return } + testAdaptorConnect = func() error { return nil } + testAdaptorFinalize = func() error { return nil } ) -func (t *testAdaptor) Finalize() (err error) { return testAdaptorFinalize() } -func (t *testAdaptor) Connect() (err error) { return testAdaptorConnect() } -func (t *testAdaptor) Name() string { return t.name } -func (t *testAdaptor) SetName(n string) { t.name = n } -func (t *testAdaptor) Port() string { return t.port } +func (t *testAdaptor) Finalize() error { return testAdaptorFinalize() } +func (t *testAdaptor) Connect() error { return testAdaptorConnect() } +func (t *testAdaptor) Name() string { return t.name } +func (t *testAdaptor) SetName(n string) { t.name = n } +func (t *testAdaptor) Port() string { return t.port } func newTestAdaptor(name string, port string) *testAdaptor { //nolint:unparam // keep for tests return &testAdaptor{ diff --git a/master.go b/master.go index 9e16b269d..6119d6d12 100644 --- a/master.go +++ b/master.go @@ -88,7 +88,7 @@ func (g *Master) Stop() error { // Running returns if the Master is currently started or not func (g *Master) Running() bool { - return g.running.Load().(bool) + return g.running.Load().(bool) //nolint:forcetypeassert // no error return value, so there is no better way } // Robots returns all robots associated with this Gobot Master. diff --git a/master_test.go b/master_test.go index ac7cea80a..6ac1ddca6 100644 --- a/master_test.go +++ b/master_test.go @@ -90,7 +90,7 @@ func TestMasterStartAutoRun(t *testing.T) { func TestMasterStartDriverErrors(t *testing.T) { g := initTestMaster1Robot() e := errors.New("driver start error 1") - testDriverStart = func() (err error) { + testDriverStart = func() error { return e } @@ -102,13 +102,13 @@ func TestMasterStartDriverErrors(t *testing.T) { assert.Equal(t, want, g.Start()) require.NoError(t, g.Stop()) - testDriverStart = func() (err error) { return } + testDriverStart = func() error { return nil } } func TestMasterHaltFromRobotDriverErrors(t *testing.T) { g := initTestMaster1Robot() var ec int - testDriverHalt = func() (err error) { + testDriverHalt = func() error { ec++ return fmt.Errorf("driver halt error %d", ec) } @@ -126,7 +126,7 @@ func TestMasterHaltFromRobotDriverErrors(t *testing.T) { func TestMasterStartRobotAdaptorErrors(t *testing.T) { g := initTestMaster1Robot() var ec int - testAdaptorConnect = func() (err error) { + testAdaptorConnect = func() error { ec++ return fmt.Errorf("adaptor start error %d", ec) } @@ -141,13 +141,13 @@ func TestMasterStartRobotAdaptorErrors(t *testing.T) { assert.Equal(t, want, g.Start()) require.NoError(t, g.Stop()) - testAdaptorConnect = func() (err error) { return } + testAdaptorConnect = func() error { return nil } } func TestMasterFinalizeErrors(t *testing.T) { g := initTestMaster1Robot() var ec int - testAdaptorFinalize = func() (err error) { + testAdaptorFinalize = func() error { ec++ return fmt.Errorf("adaptor finalize error %d", ec) } diff --git a/platforms/adaptors/digitalpinsadaptor.go b/platforms/adaptors/digitalpinsadaptor.go index 08cd04da6..e62d91c70 100644 --- a/platforms/adaptors/digitalpinsadaptor.go +++ b/platforms/adaptors/digitalpinsadaptor.go @@ -50,7 +50,11 @@ type DigitalPinsAdaptor struct { // to the internal file name or chip/line nomenclature. This varies by each platform. If for some reasons the default // initializer is not suitable, it can be given by the option "WithDigitalPinInitializer()". This is especially needed, // if some values needs to be adjusted after the pin was created but before the pin is exported. -func NewDigitalPinsAdaptor(sys *system.Accesser, t digitalPinTranslator, options ...func(Optioner)) *DigitalPinsAdaptor { +func NewDigitalPinsAdaptor( + sys *system.Accesser, + t digitalPinTranslator, + options ...func(Optioner), +) *DigitalPinsAdaptor { a := &DigitalPinsAdaptor{ sys: sys, translate: t, @@ -219,10 +223,11 @@ func (a *DigitalPinsAdaptor) Connect() error { } // Finalize closes connection to digital pins -func (a *DigitalPinsAdaptor) Finalize() (err error) { +func (a *DigitalPinsAdaptor) Finalize() error { a.mutex.Lock() defer a.mutex.Unlock() + var err error for _, pin := range a.pins { if pin != nil { if e := pin.Unexport(); e != nil { @@ -232,7 +237,7 @@ func (a *DigitalPinsAdaptor) Finalize() (err error) { } a.pins = nil a.pinOptions = nil - return + return err } // DigitalPin returns a digital pin. If the pin is initially acquired, it is an input. @@ -395,7 +400,10 @@ func (a *DigitalPinsAdaptor) prepareDigitalPinPollForEdgeDetection( a.pinOptions[id] = append(a.pinOptions[id], system.WithPinPollForEdgeDetection(pollInterval, pollQuitChan)) } -func (a *DigitalPinsAdaptor) digitalPin(id string, opts ...func(gobot.DigitalPinOptioner) bool) (gobot.DigitalPinner, error) { +func (a *DigitalPinsAdaptor) digitalPin( + id string, + opts ...func(gobot.DigitalPinOptioner) bool, +) (gobot.DigitalPinner, error) { if a.pins == nil { return nil, fmt.Errorf("not connected for pin %s", id) } diff --git a/platforms/adaptors/digitalpinsadaptor_test.go b/platforms/adaptors/digitalpinsadaptor_test.go index 2e91c561a..ae0785df8 100644 --- a/platforms/adaptors/digitalpinsadaptor_test.go +++ b/platforms/adaptors/digitalpinsadaptor_test.go @@ -1,3 +1,4 @@ +//nolint:nonamedreturns // ok for tests package adaptors import ( @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/system" @@ -101,7 +103,7 @@ func TestDigitalPinsFinalize(t *testing.T) { require.NoError(t, a.DigitalWrite("3", 2)) delete(fs.Files, "/sys/class/gpio/unexport") err = a.Finalize() - assert.Contains(t, err.Error(), "/sys/class/gpio/unexport: no such file") + require.ErrorContains(t, err, "/sys/class/gpio/unexport: no such file") } func TestDigitalPinsReConnect(t *testing.T) { diff --git a/platforms/adaptors/i2cbusadaptor.go b/platforms/adaptors/i2cbusadaptor.go index cc1041972..401d6cf73 100644 --- a/platforms/adaptors/i2cbusadaptor.go +++ b/platforms/adaptors/i2cbusadaptor.go @@ -5,6 +5,7 @@ import ( "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" diff --git a/platforms/adaptors/i2cbusadaptor_test.go b/platforms/adaptors/i2cbusadaptor_test.go index 116f97524..70d7ab8b8 100644 --- a/platforms/adaptors/i2cbusadaptor_test.go +++ b/platforms/adaptors/i2cbusadaptor_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/system" ) @@ -94,7 +95,7 @@ func TestI2cFinalize(t *testing.T) { _, _ = con.Write([]byte{0xbf}) fs.WithCloseError = true err := a.Finalize() - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func TestI2cReConnect(t *testing.T) { diff --git a/platforms/adaptors/pwmpinsadaptor.go b/platforms/adaptors/pwmpinsadaptor.go index b3a159fcf..4d0834adc 100644 --- a/platforms/adaptors/pwmpinsadaptor.go +++ b/platforms/adaptors/pwmpinsadaptor.go @@ -5,6 +5,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) @@ -90,10 +91,11 @@ func (a *PWMPinsAdaptor) Connect() error { } // Finalize closes connection to PWM pins. -func (a *PWMPinsAdaptor) Finalize() (err error) { +func (a *PWMPinsAdaptor) Finalize() error { a.mutex.Lock() defer a.mutex.Unlock() + var err error for _, pin := range a.pins { if pin != nil { if errs := pin.SetEnabled(false); errs != nil { @@ -109,13 +111,13 @@ func (a *PWMPinsAdaptor) Finalize() (err error) { } // PwmWrite writes a PWM signal to the specified pin. -func (a *PWMPinsAdaptor) PwmWrite(id string, val byte) (err error) { +func (a *PWMPinsAdaptor) PwmWrite(id string, val byte) error { a.mutex.Lock() defer a.mutex.Unlock() pin, err := a.pwmPin(id) if err != nil { - return + return err } period, err := pin.Period() if err != nil { @@ -126,13 +128,13 @@ func (a *PWMPinsAdaptor) PwmWrite(id string, val byte) (err error) { } // ServoWrite writes a servo signal to the specified pin. -func (a *PWMPinsAdaptor) ServoWrite(id string, angle byte) (err error) { +func (a *PWMPinsAdaptor) ServoWrite(id string, angle byte) error { a.mutex.Lock() defer a.mutex.Unlock() pin, err := a.pwmPin(id) if err != nil { - return + return err } period, err := pin.Period() if err != nil { diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index 94d8d61ca..0770695b6 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -1,16 +1,16 @@ +//nolint:nonamedreturns // ok for tests package adaptors import ( "fmt" - "log" "runtime" "strconv" - "strings" "sync" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/system" @@ -151,13 +151,13 @@ func TestPWMPinsFinalize(t *testing.T) { require.NoError(t, a.PwmWrite("33", 2)) delete(fs.Files, pwmUnexportPath) err = a.Finalize() - assert.Contains(t, err.Error(), pwmUnexportPath+": no such file") + require.ErrorContains(t, err, pwmUnexportPath+": no such file") // arrange write error require.NoError(t, a.Connect()) require.NoError(t, a.PwmWrite("33", 2)) fs.WithWriteError = true err = a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestPWMPinsReConnect(t *testing.T) { @@ -191,12 +191,12 @@ func TestPwmWrite(t *testing.T) { fs.WithWriteError = true err = a.PwmWrite("33", 100) - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") fs.WithWriteError = false fs.WithReadError = true err = a.PwmWrite("33", 100) - assert.Contains(t, err.Error(), "read error") + require.ErrorContains(t, err, "read error") } func TestServoWrite(t *testing.T) { @@ -219,12 +219,12 @@ func TestServoWrite(t *testing.T) { fs.WithWriteError = true err = a.ServoWrite("33", 100) - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") fs.WithWriteError = false fs.WithReadError = true err = a.ServoWrite("33", 100) - assert.Contains(t, err.Error(), "read error") + require.ErrorContains(t, err, "read error") } func TestSetPeriod(t *testing.T) { @@ -292,14 +292,16 @@ func Test_PWMPin(t *testing.T) { mockPaths: []string{}, translate: translator, pin: "33", - wantErr: "Export() failed for id 44 with : /sys/devices/platform/ff680020.pwm/pwm/pwmchip3/export: no such file", + wantErr: "Export() failed for id 44 with : " + + "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/export: no such file", }, "init_setenabled_error": { mockPaths: []string{pwmExportPath, pwmPeriodPath}, period: "1000", translate: translator, pin: "33", - wantErr: "SetEnabled(false) failed for id 44 with : /sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/enable: no such file", + wantErr: "SetEnabled(false) failed for id 44 with : " + + "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/enable: no such file", }, "init_setperiod_dutycycle_no_error": { mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmDutyCyclePath, pwmPolarityPath}, @@ -313,7 +315,8 @@ func Test_PWMPin(t *testing.T) { dutyCycle: "0", translate: translator, pin: "33", - wantErr: "SetPeriod(10000000) failed for id 44 with : /sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/period: no such file", + wantErr: "SetPeriod(10000000) failed for id 44 with : " + + "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/period: no such file", }, "init_setpolarity_error": { mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmDutyCyclePath}, @@ -321,7 +324,8 @@ func Test_PWMPin(t *testing.T) { dutyCycle: "0", translate: translator, pin: "33", - wantErr: "SetPolarity(normal) failed for id 44 with : /sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/polarity: no such file", + wantErr: "SetPolarity(normal) failed for id 44 with : " + + "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/polarity: no such file", }, "translate_error": { translate: func(string) (string, int, error) { return "", -1, fmt.Errorf(translateErr) }, @@ -350,10 +354,7 @@ func Test_PWMPin(t *testing.T) { require.NoError(t, err) assert.NotNil(t, got) } else { - if !strings.Contains(err.Error(), tc.wantErr) { - log.Println(err.Error()) - } - assert.Contains(t, err.Error(), tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) assert.Nil(t, got) } }) diff --git a/platforms/adaptors/spibusadaptor.go b/platforms/adaptors/spibusadaptor.go index 55608300a..2672fc9e4 100644 --- a/platforms/adaptors/spibusadaptor.go +++ b/platforms/adaptors/spibusadaptor.go @@ -5,6 +5,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2/drivers/spi" "gobot.io/x/gobot/v2/system" ) diff --git a/platforms/adaptors/spibusadaptor_test.go b/platforms/adaptors/spibusadaptor_test.go index ac3ca2a07..df4375b62 100644 --- a/platforms/adaptors/spibusadaptor_test.go +++ b/platforms/adaptors/spibusadaptor_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2/drivers/spi" "gobot.io/x/gobot/v2/system" ) @@ -105,7 +106,7 @@ func TestSpiFinalizeWithError(t *testing.T) { // act err := a.Finalize() // assert - assert.Contains(t, err.Error(), "error while SPI close") + require.ErrorContains(t, err, "error while SPI close") } func TestSpiReConnect(t *testing.T) { diff --git a/platforms/audio/audio_adaptor.go b/platforms/audio/audio_adaptor.go index 09d96f931..612eb3b19 100644 --- a/platforms/audio/audio_adaptor.go +++ b/platforms/audio/audio_adaptor.go @@ -41,7 +41,7 @@ func (a *Adaptor) Sound(fileName string) []error { if fileName == "" { log.Println("Requires filename for audio file.") - errorsList = append(errorsList, errors.New("Requires filename for audio file.")) + errorsList = append(errorsList, errors.New("requires filename for audio file")) return errorsList } @@ -74,14 +74,15 @@ func (a *Adaptor) Sound(fileName string) []error { // CommandName defines the playback command for a sound and accepts: // // string: The filename of the audio that needs playback -func CommandName(fileName string) (commandName string, err error) { +func CommandName(fileName string) (string, error) { fileType := path.Ext(fileName) - if fileType == ".mp3" { + switch fileType { + case ".mp3": return "mpg123", nil - } else if fileType == ".wav" { + case ".wav": return "aplay", nil - } else { - return "", errors.New("Unknown filetype for audio file.") + default: + return "", errors.New("unknown filetype for audio file") } } diff --git a/platforms/audio/audio_adaptor_test.go b/platforms/audio/audio_adaptor_test.go index 1545515fe..1e411f8a5 100644 --- a/platforms/audio/audio_adaptor_test.go +++ b/platforms/audio/audio_adaptor_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -41,21 +42,21 @@ func TestAudioAdaptorCommandsMp3(t *testing.T) { func TestAudioAdaptorCommandsUnknown(t *testing.T) { cmd, err := CommandName("whatever.unk") assert.NotEqual(t, "mpg123", cmd) - require.ErrorContains(t, err, "Unknown filetype for audio file.") + require.ErrorContains(t, err, "unknown filetype for audio file") } func TestAudioAdaptorSoundWithNoFilename(t *testing.T) { a := NewAdaptor() errors := a.Sound("") - assert.Equal(t, "Requires filename for audio file.", errors[0].Error()) + require.ErrorContains(t, errors[0], "requires filename for audio file") } func TestAudioAdaptorSoundWithNonexistingFilename(t *testing.T) { a := NewAdaptor() errors := a.Sound("doesnotexist.mp3") - assert.Equal(t, "stat doesnotexist.mp3: no such file or directory", errors[0].Error()) + require.ErrorContains(t, errors[0], "stat doesnotexist.mp3: no such file or directory") } func TestAudioAdaptorSoundWithValidMP3Filename(t *testing.T) { diff --git a/platforms/audio/audio_driver.go b/platforms/audio/audio_driver.go index 8027a3e54..a00dc5cc2 100644 --- a/platforms/audio/audio_driver.go +++ b/platforms/audio/audio_driver.go @@ -53,6 +53,7 @@ func (d *Driver) Connection() gobot.Connection { // // string: The filename of the audio to start playing func (d *Driver) Sound(fileName string) []error { + //nolint:forcetypeassert // ok here return d.Connection().(*Adaptor).Sound(fileName) } @@ -62,11 +63,11 @@ func (d *Driver) Play() []error { } // Start starts the Driver -func (d *Driver) Start() (err error) { - return +func (d *Driver) Start() error { + return nil } // Halt halts the Driver -func (d *Driver) Halt() (err error) { - return +func (d *Driver) Halt() error { + return nil } diff --git a/platforms/audio/audio_driver_test.go b/platforms/audio/audio_driver_test.go index 88c5cde4c..b2efb41ba 100644 --- a/platforms/audio/audio_driver_test.go +++ b/platforms/audio/audio_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -37,7 +38,7 @@ func TestAudioDriverSoundWithNoFilename(t *testing.T) { d := NewDriver(NewAdaptor(), "") errors := d.Sound("") - assert.Equal(t, "Requires filename for audio file.", errors[0].Error()) + require.ErrorContains(t, errors[0], "requires filename for audio file") } func TestAudioDriverSoundWithDefaultFilename(t *testing.T) { diff --git a/platforms/beaglebone/beaglebone_adaptor.go b/platforms/beaglebone/beaglebone_adaptor.go index 2486b9cf2..7048a3c66 100644 --- a/platforms/beaglebone/beaglebone_adaptor.go +++ b/platforms/beaglebone/beaglebone_adaptor.go @@ -8,6 +8,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -140,26 +141,26 @@ func (c *Adaptor) DigitalWrite(id string, val byte) error { } // AnalogRead returns an analog value from specified pin -func (c *Adaptor) AnalogRead(pin string) (val int, err error) { +func (c *Adaptor) AnalogRead(pin string) (int, error) { analogPin, err := c.translateAnalogPin(pin) if err != nil { - return + return 0, err } fi, err := c.sys.OpenFile(fmt.Sprintf("%v/%v", c.analogPath, analogPin), os.O_RDONLY, 0o644) defer fi.Close() //nolint:staticcheck // for historical reasons if err != nil { - return + return 0, err } buf := make([]byte, 1024) _, err = fi.Read(buf) if err != nil { - return + return 0, err } - val, _ = strconv.Atoi(strings.Split(string(buf), "\n")[0]) - return + val, _ := strconv.Atoi(strings.Split(string(buf), "\n")[0]) + return val, nil } func (c *Adaptor) validateSpiBusNumber(busNr int) error { @@ -218,13 +219,13 @@ func (c *Adaptor) translateAndMuxPWMPin(id string) (string, int, error) { return path, pinInfo.channel, nil } -func (p pwmPinData) findPWMDir(sys *system.Accesser) (dir string, err error) { +func (p pwmPinData) findPWMDir(sys *system.Accesser) (string, error) { items, _ := sys.Find(p.dir, p.dirRegexp) if len(items) == 0 { return "", fmt.Errorf("No path found for PWM directory pattern, '%s' in path '%s'", p.dirRegexp, p.dir) } - dir = items[0] + dir := items[0] info, err := sys.Stat(dir) if err != nil { return "", fmt.Errorf("Error (%v) on access '%s'", err, dir) @@ -233,7 +234,7 @@ func (p pwmPinData) findPWMDir(sys *system.Accesser) (dir string, err error) { return "", fmt.Errorf("The item '%s' is not a directory, which is not expected", dir) } - return + return dir, nil } func (c *Adaptor) muxPin(pin, cmd string) error { diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index f9d03362f..1f5641ba9 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" @@ -172,7 +173,7 @@ func TestAnalogReadFileError(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) _, err := a.AnalogRead("P9_40") - assert.Contains(t, err.Error(), "/sys/bus/iio/devices/iio:device0/in_voltage1_raw: no such file") + require.ErrorContains(t, err, "/sys/bus/iio/devices/iio:device0/in_voltage1_raw: no such file") } func TestDigitalPinDirectionFileError(t *testing.T) { @@ -185,7 +186,7 @@ func TestDigitalPinDirectionFileError(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) err := a.DigitalWrite("P9_12", 1) - assert.Contains(t, err.Error(), "/sys/class/gpio/gpio60/direction: no such file") + require.ErrorContains(t, err, "/sys/class/gpio/gpio60/direction: no such file") // no pin added after previous problem, so no pin to unexport in finalize err = a.Finalize() @@ -206,7 +207,7 @@ func TestDigitalPinFinalizeFileError(t *testing.T) { require.NoError(t, err) err = a.Finalize() - assert.Contains(t, err.Error(), "/sys/class/gpio/unexport: no such file") + require.ErrorContains(t, err, "/sys/class/gpio/unexport: no such file") } func TestPocketName(t *testing.T) { @@ -243,7 +244,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateSpiBusNumber(t *testing.T) { diff --git a/platforms/beaglebone/black_pins.go b/platforms/beaglebone/black_pins.go index e6e877770..9d8357f46 100644 --- a/platforms/beaglebone/black_pins.go +++ b/platforms/beaglebone/black_pins.go @@ -50,14 +50,27 @@ var bbbPinMap = map[string]int{ } var bbbPwmPinMap = map[string]pwmPinData{ - "P8_13": {dir: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1}, - "P8_19": {dir: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0}, - - "P9_14": {dir: "/sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0}, - "P9_16": {dir: "/sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1}, - "P9_21": {dir: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1}, - "P9_22": {dir: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0}, - "P9_42": {dir: "/sys/devices/platform/ocp/48300000.epwmss/48300100.ecap/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0}, + "P8_13": { + dir: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1, + }, + "P8_19": { + dir: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0, + }, + "P9_14": { + dir: "/sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0, + }, + "P9_16": { + dir: "/sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1, + }, + "P9_21": { + dir: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1, + }, + "P9_22": { + dir: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0, + }, + "P9_42": { + dir: "/sys/devices/platform/ocp/48300000.epwmss/48300100.ecap/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0, + }, } var bbbAnalogPinMap = map[string]string{ diff --git a/platforms/ble/battery_driver.go b/platforms/ble/battery_driver.go index fc38e7262..4b3e59628 100644 --- a/platforms/ble/battery_driver.go +++ b/platforms/ble/battery_driver.go @@ -36,27 +36,25 @@ func (b *BatteryDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *BatteryDriver) adaptor() BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(BLEConnector) } // Start tells driver to get ready to do work -func (b *BatteryDriver) Start() (err error) { - return -} +func (b *BatteryDriver) Start() error { return nil } // Halt stops battery driver (void) -func (b *BatteryDriver) Halt() (err error) { return } +func (b *BatteryDriver) Halt() error { return nil } // GetBatteryLevel reads and returns the current battery level -func (b *BatteryDriver) GetBatteryLevel() (level uint8) { - var l uint8 +func (b *BatteryDriver) GetBatteryLevel() uint8 { c, err := b.adaptor().ReadCharacteristic("2a19") if err != nil { log.Println(err) - return + return 0 } buf := bytes.NewBuffer(c) val, _ := buf.ReadByte() - l = val - return l + level := val + return level } diff --git a/platforms/ble/battery_driver_test.go b/platforms/ble/battery_driver_test.go index 70ee9d133..84e671f70 100644 --- a/platforms/ble/battery_driver_test.go +++ b/platforms/ble/battery_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/ble/ble_client_adaptor.go b/platforms/ble/ble_client_adaptor.go index d3a270e0a..8273e1c94 100644 --- a/platforms/ble/ble_client_adaptor.go +++ b/platforms/ble/ble_client_adaptor.go @@ -6,9 +6,9 @@ import ( "sync" "time" - "gobot.io/x/gobot/v2" - "tinygo.org/x/bluetooth" + + "gobot.io/x/gobot/v2" ) var ( @@ -154,7 +154,7 @@ func (b *ClientAdaptor) Finalize() error { // ReadCharacteristic returns bytes from the BLE device for the // requested characteristic uuid -func (b *ClientAdaptor) ReadCharacteristic(cUUID string) (data []byte, err error) { +func (b *ClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { if !b.connected { return nil, fmt.Errorf("Cannot read from BLE device until connected") } diff --git a/platforms/ble/ble_client_adaptor_test.go b/platforms/ble/ble_client_adaptor_test.go index 96fb233f1..0862405e8 100644 --- a/platforms/ble/ble_client_adaptor_test.go +++ b/platforms/ble/ble_client_adaptor_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/ble/device_information_driver.go b/platforms/ble/device_information_driver.go index 0629a21db..79710a9df 100644 --- a/platforms/ble/device_information_driver.go +++ b/platforms/ble/device_information_driver.go @@ -36,35 +36,34 @@ func (b *DeviceInformationDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor for this device func (b *DeviceInformationDriver) adaptor() BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(BLEConnector) } // Start tells driver to get ready to do work -func (b *DeviceInformationDriver) Start() (err error) { - return -} +func (b *DeviceInformationDriver) Start() error { return nil } // Halt stops driver (void) -func (b *DeviceInformationDriver) Halt() (err error) { return } +func (b *DeviceInformationDriver) Halt() error { return nil } // GetModelNumber returns the model number for the BLE Peripheral -func (b *DeviceInformationDriver) GetModelNumber() (model string) { +func (b *DeviceInformationDriver) GetModelNumber() string { c, err := b.adaptor().ReadCharacteristic("2a24") if err != nil { log.Println(err) - return + return "" } buf := bytes.NewBuffer(c) - model = buf.String() - return + model := buf.String() + return model } // GetFirmwareRevision returns the firmware revision for the BLE Peripheral -func (b *DeviceInformationDriver) GetFirmwareRevision() (revision string) { +func (b *DeviceInformationDriver) GetFirmwareRevision() string { c, err := b.adaptor().ReadCharacteristic("2a26") if err != nil { log.Println(err) - return + return "" } buf := bytes.NewBuffer(c) val := buf.String() @@ -72,11 +71,11 @@ func (b *DeviceInformationDriver) GetFirmwareRevision() (revision string) { } // GetHardwareRevision returns the hardware revision for the BLE Peripheral -func (b *DeviceInformationDriver) GetHardwareRevision() (revision string) { +func (b *DeviceInformationDriver) GetHardwareRevision() string { c, err := b.adaptor().ReadCharacteristic("2a27") if err != nil { log.Println(err) - return + return "" } buf := bytes.NewBuffer(c) val := buf.String() @@ -84,11 +83,11 @@ func (b *DeviceInformationDriver) GetHardwareRevision() (revision string) { } // GetManufacturerName returns the manufacturer name for the BLE Peripheral -func (b *DeviceInformationDriver) GetManufacturerName() (manufacturer string) { +func (b *DeviceInformationDriver) GetManufacturerName() string { c, err := b.adaptor().ReadCharacteristic("2a29") if err != nil { log.Println(err) - return + return "" } buf := bytes.NewBuffer(c) val := buf.String() @@ -96,11 +95,11 @@ func (b *DeviceInformationDriver) GetManufacturerName() (manufacturer string) { } // GetPnPId returns the PnP ID for the BLE Peripheral -func (b *DeviceInformationDriver) GetPnPId() (model string) { +func (b *DeviceInformationDriver) GetPnPId() string { c, err := b.adaptor().ReadCharacteristic("2a50") if err != nil { log.Println(err) - return + return "" } buf := bytes.NewBuffer(c) val := buf.String() diff --git a/platforms/ble/device_information_driver_test.go b/platforms/ble/device_information_driver_test.go index 72b14a908..1835ce8d1 100644 --- a/platforms/ble/device_information_driver_test.go +++ b/platforms/ble/device_information_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/ble/generic_access_driver.go b/platforms/ble/generic_access_driver.go index 7e4f9d59f..3b3f40c08 100644 --- a/platforms/ble/generic_access_driver.go +++ b/platforms/ble/generic_access_driver.go @@ -37,6 +37,7 @@ func (b *GenericAccessDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor for this device func (b *GenericAccessDriver) adaptor() BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(BLEConnector) } diff --git a/platforms/ble/generic_access_driver_test.go b/platforms/ble/generic_access_driver_test.go index 9b09d6435..c32b3384e 100644 --- a/platforms/ble/generic_access_driver_test.go +++ b/platforms/ble/generic_access_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/ble/helpers_test.go b/platforms/ble/helpers_test.go index 7df468b72..dfcd7e36d 100644 --- a/platforms/ble/helpers_test.go +++ b/platforms/ble/helpers_test.go @@ -14,30 +14,30 @@ type bleTestClientAdaptor struct { testWriteCharacteristic func(string, []byte) error } -func (t *bleTestClientAdaptor) Connect() (err error) { return } -func (t *bleTestClientAdaptor) Reconnect() (err error) { return } -func (t *bleTestClientAdaptor) Disconnect() (err error) { return } -func (t *bleTestClientAdaptor) Finalize() (err error) { return } +func (t *bleTestClientAdaptor) Connect() error { return nil } +func (t *bleTestClientAdaptor) Reconnect() error { return nil } +func (t *bleTestClientAdaptor) Disconnect() error { return nil } +func (t *bleTestClientAdaptor) Finalize() error { return nil } func (t *bleTestClientAdaptor) Name() string { return t.name } func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } func (t *bleTestClientAdaptor) Address() string { return t.address } func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) (data []byte, err error) { +func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testReadCharacteristic(cUUID) } -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) (err error) { +func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.testWriteCharacteristic(cUUID, data) } -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) (err error) { +func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { // TODO: implement this... - return + return nil } func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { @@ -46,7 +46,7 @@ func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data t.testReadCharacteristic = f } -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) (err error)) { +func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { t.mtx.Lock() defer t.mtx.Unlock() t.testWriteCharacteristic = f @@ -55,11 +55,11 @@ func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data func NewBleTestAdaptor() *bleTestClientAdaptor { return &bleTestClientAdaptor{ address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) (data []byte, e error) { - return + testReadCharacteristic: func(cUUID string) ([]byte, error) { + return []byte{}, nil }, - testWriteCharacteristic: func(cUUID string, data []byte) (e error) { - return + testWriteCharacteristic: func(cUUID string, data []byte) error { + return nil }, } } diff --git a/platforms/ble/serial_port.go b/platforms/ble/serial_port.go index db6307591..4cbfedbe6 100644 --- a/platforms/ble/serial_port.go +++ b/platforms/ble/serial_port.go @@ -37,13 +37,13 @@ func (p *SerialPort) Open() error { } // Read reads bytes from BLE serial port connection -func (p *SerialPort) Read(b []byte) (n int, err error) { +func (p *SerialPort) Read(b []byte) (int, error) { if len(p.responseData) == 0 { - return + return 0, nil } p.responseMutex.Lock() - n = len(b) + n := len(b) if len(p.responseData) < n { n = len(p.responseData) } @@ -56,14 +56,14 @@ func (p *SerialPort) Read(b []byte) (n int, err error) { } p.responseMutex.Unlock() - return + return n, nil } // Write writes to the BLE serial port connection -func (p *SerialPort) Write(b []byte) (n int, err error) { - err = p.client.WriteCharacteristic(p.tid, b) - n = len(b) - return +func (p *SerialPort) Write(b []byte) (int, error) { + err := p.client.WriteCharacteristic(p.tid, b) + n := len(b) + return n, err } // Close closes the BLE serial port connection diff --git a/platforms/chip/chip_adaptor.go b/platforms/chip/chip_adaptor.go index 4cc9eda5f..c7dd3a21a 100644 --- a/platforms/chip/chip_adaptor.go +++ b/platforms/chip/chip_adaptor.go @@ -9,6 +9,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -108,14 +109,14 @@ func (c *Adaptor) Finalize() error { return err } -func getXIOBase() (baseAddr int, err error) { +func getXIOBase() (int, error) { // Default to original base from 4.3 kernel - baseAddr = 408 + baseAddr := 408 const expanderID = "pcf8574a" labels, err := filepath.Glob("/sys/class/gpio/*/label") if err != nil { - return + return baseAddr, err } for _, labelPath := range labels { diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index f8dc92ee2..d319119d6 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -78,7 +79,7 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestFinalizeErrorAfterPWM(t *testing.T) { @@ -92,7 +93,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestDigitalIO(t *testing.T) { @@ -175,7 +176,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateI2cBusNumber(t *testing.T) { diff --git a/platforms/dexter/gopigo3/driver.go b/platforms/dexter/gopigo3/driver.go index f4c3f12ad..0edbdb1d2 100644 --- a/platforms/dexter/gopigo3/driver.go +++ b/platforms/dexter/gopigo3/driver.go @@ -8,10 +8,12 @@ import ( "bytes" "encoding/binary" "fmt" + "log" "math" "time" "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/spi" ) @@ -66,15 +68,22 @@ const ( ) const ( - WHEEL_BASE_WIDTH = 117 // distance (mm) from left wheel to right wheel. This works with the initial GPG3 prototype. Will need to be adjusted. - WHEEL_DIAMETER = 66.5 // wheel diameter (mm) - WHEEL_BASE_CIRCUMFERENCE = WHEEL_BASE_WIDTH * math.Pi // circumference of the circle the wheels will trace while turning (mm) - WHEEL_CIRCUMFERENCE = WHEEL_DIAMETER * math.Pi // circumference of the wheels (mm) - MOTOR_GEAR_RATIO = 120 // motor gear ratio - ENCODER_TICKS_PER_ROTATION = 6 // encoder ticks per motor rotation (number of magnet positions) - MOTOR_TICKS_PER_DEGREE = ((MOTOR_GEAR_RATIO * ENCODER_TICKS_PER_ROTATION) / 360.0) // encoder ticks per output shaft rotation degree - GROVE_I2C_LENGTH_LIMIT = 16 - MOTOR_FLOAT = -128 + // distance (mm) from left wheel to right wheel. This works with the initial GPG3 prototype. Will need to be adjusted. + WHEEL_BASE_WIDTH = 117 + // wheel diameter (mm) + WHEEL_DIAMETER = 66.5 + // circumference of the circle the wheels will trace while turning (mm) + WHEEL_BASE_CIRCUMFERENCE = WHEEL_BASE_WIDTH * math.Pi + // circumference of the wheels (mm) + WHEEL_CIRCUMFERENCE = WHEEL_DIAMETER * math.Pi + // motor gear ratio + MOTOR_GEAR_RATIO = 120 + // encoder ticks per motor rotation (number of magnet positions) + ENCODER_TICKS_PER_ROTATION = 6 + // encoder ticks per output shaft rotation degree + MOTOR_TICKS_PER_DEGREE = ((MOTOR_GEAR_RATIO * ENCODER_TICKS_PER_ROTATION) / 360.0) + GROVE_I2C_LENGTH_LIMIT = 16 + MOTOR_FLOAT = -128 ) // GroveMode sets the mode of AD pins on the gopigo3. @@ -182,55 +191,62 @@ func NewDriver(a spi.Connector, options ...func(spi.Config)) *Driver { // use /dev/spidev0.1 spiConfig.SetBusNumber(0) spiConfig.SetChipNumber(1) - g := &Driver{ + d := &Driver{ name: gobot.DefaultName("GoPiGo3"), connector: a, Config: spiConfig, } for _, option := range options { - option(g) + option(d) } - return g + return d } // Name returns the name of the device. -func (g *Driver) Name() string { return g.name } +func (d *Driver) Name() string { return d.name } // SetName sets the name of the device. -func (g *Driver) SetName(n string) { g.name = n } +func (d *Driver) SetName(n string) { d.name = n } // Connection returns the Connection of the device. -func (g *Driver) Connection() gobot.Connection { return g.connection.(gobot.Connection) } +func (d *Driver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.name) + return nil +} // Halt stops the driver. -func (g *Driver) Halt() error { - err := g.resetAll() +func (d *Driver) Halt() error { + err := d.resetAll() time.Sleep(10 * time.Millisecond) return err } // Start initializes the GoPiGo3 -func (g *Driver) Start() error { - bus := g.GetBusNumberOrDefault(g.connector.SpiDefaultBusNumber()) - chip := g.GetChipNumberOrDefault(g.connector.SpiDefaultChipNumber()) - mode := g.GetModeOrDefault(g.connector.SpiDefaultMode()) - bits := g.GetBitCountOrDefault(g.connector.SpiDefaultBitCount()) - maxSpeed := g.GetSpeedOrDefault(g.connector.SpiDefaultMaxSpeed()) +func (d *Driver) Start() error { + bus := d.GetBusNumberOrDefault(d.connector.SpiDefaultBusNumber()) + chip := d.GetChipNumberOrDefault(d.connector.SpiDefaultChipNumber()) + mode := d.GetModeOrDefault(d.connector.SpiDefaultMode()) + bits := d.GetBitCountOrDefault(d.connector.SpiDefaultBitCount()) + maxSpeed := d.GetSpeedOrDefault(d.connector.SpiDefaultMaxSpeed()) var err error - g.connection, err = g.connector.GetSpiConnection(bus, chip, mode, bits, maxSpeed) + d.connection, err = d.connector.GetSpiConnection(bus, chip, mode, bits, maxSpeed) return err } // GetManufacturerName returns the manufacturer from the firmware. -func (g *Driver) GetManufacturerName() (mName string, err error) { +func (d *Driver) GetManufacturerName() (string, error) { // read 24 bytes to get manufacturer name - response, err := g.readBytes(goPiGo3Address, GET_MANUFACTURER, 24) + response, err := d.readBytes(goPiGo3Address, GET_MANUFACTURER, 24) if err != nil { - return mName, err + return "", err } - if err := g.responseValid(response); err != nil { - return mName, err + if err := d.responseValid(response); err != nil { + return "", err } mf := response[4:23] mf = bytes.Trim(mf, "\x00") @@ -238,14 +254,14 @@ func (g *Driver) GetManufacturerName() (mName string, err error) { } // GetBoardName returns the board name from the firmware. -func (g *Driver) GetBoardName() (bName string, err error) { +func (d *Driver) GetBoardName() (string, error) { // read 24 bytes to get board name - response, err := g.readBytes(goPiGo3Address, GET_NAME, 24) + response, err := d.readBytes(goPiGo3Address, GET_NAME, 24) if err != nil { - return bName, err + return "", err } - if err := g.responseValid(response); err != nil { - return bName, err + if err := d.responseValid(response); err != nil { + return "", err } mf := response[4:23] mf = bytes.Trim(mf, "\x00") @@ -253,10 +269,10 @@ func (g *Driver) GetBoardName() (bName string, err error) { } // GetHardwareVersion returns the hardware version from the firmware. -func (g *Driver) GetHardwareVersion() (hVer string, err error) { - response, err := g.readUint32(goPiGo3Address, GET_HARDWARE_VERSION) +func (d *Driver) GetHardwareVersion() (string, error) { + response, err := d.readUint32(goPiGo3Address, GET_HARDWARE_VERSION) if err != nil { - return hVer, err + return "", err } major := response / 1000000 minor := response / 1000 % 1000 @@ -265,10 +281,10 @@ func (g *Driver) GetHardwareVersion() (hVer string, err error) { } // GetFirmwareVersion returns the current firmware version. -func (g *Driver) GetFirmwareVersion() (fVer string, err error) { - response, err := g.readUint32(goPiGo3Address, GET_FIRMWARE_VERSION) +func (d *Driver) GetFirmwareVersion() (string, error) { + response, err := d.readUint32(goPiGo3Address, GET_FIRMWARE_VERSION) if err != nil { - return fVer, err + return "", err } major := response / 1000000 minor := response / 1000 % 1000 @@ -277,33 +293,35 @@ func (g *Driver) GetFirmwareVersion() (fVer string, err error) { } // GetSerialNumber returns the 128-bit hardware serial number of the board. -func (g *Driver) GetSerialNumber() (sNum string, err error) { +func (d *Driver) GetSerialNumber() (string, error) { // read 20 bytes to get the serial number - response, err := g.readBytes(goPiGo3Address, GET_ID, 20) + response, err := d.readBytes(goPiGo3Address, GET_ID, 20) if err != nil { - return sNum, err + return "", err } - if err := g.responseValid(response); err != nil { - return sNum, err + if err := d.responseValid(response); err != nil { + return "", err } - return fmt.Sprintf("%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", response[4], response[5], response[6], response[7], response[8], response[9], response[10], response[11], response[12], response[13], response[14], response[15], response[16], response[17], response[18], response[19]), nil + return fmt.Sprintf("%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", response[4], response[5], + response[6], response[7], response[8], response[9], response[10], response[11], response[12], response[13], + response[14], response[15], response[16], response[17], response[18], response[19]), nil } // Get5vVoltage returns the current voltage on the 5v line. -func (g *Driver) Get5vVoltage() (voltage float32, err error) { - val, err := g.readUint16(goPiGo3Address, GET_VOLTAGE_5V) +func (d *Driver) Get5vVoltage() (float32, error) { + val, err := d.readUint16(goPiGo3Address, GET_VOLTAGE_5V) return (float32(val) / 1000.0), err } // GetBatteryVoltage gets the battery voltage from the main battery pack (7v-12v). -func (g *Driver) GetBatteryVoltage() (voltage float32, err error) { - val, err := g.readUint16(goPiGo3Address, GET_VOLTAGE_VCC) +func (d *Driver) GetBatteryVoltage() (float32, error) { + val, err := d.readUint16(goPiGo3Address, GET_VOLTAGE_VCC) return (float32(val) / 1000.0), err } // SetLED sets rgb values from 0 to 255. -func (g *Driver) SetLED(led Led, red, green, blue uint8) error { - return g.writeBytes([]byte{ +func (d *Driver) SetLED(led Led, red, green, blue uint8) error { + return d.writeBytes([]byte{ goPiGo3Address, SET_LED, byte(led), @@ -314,8 +332,8 @@ func (g *Driver) SetLED(led Led, red, green, blue uint8) error { } // SetServo sets a servo's position in microseconds (0-16666). -func (g *Driver) SetServo(srvo Servo, us uint16) error { - return g.writeBytes([]byte{ +func (d *Driver) SetServo(srvo Servo, us uint16) error { + return d.writeBytes([]byte{ goPiGo3Address, SET_SERVO, byte(srvo), @@ -326,7 +344,7 @@ func (g *Driver) SetServo(srvo Servo, us uint16) error { // ServoWrite writes an angle (0-180) to the given servo (servo 1 or servo 2). // Must implement the ServoWriter interface of gpio package. -func (g *Driver) ServoWrite(port string, angle byte) error { +func (d *Driver) ServoWrite(port string, angle byte) error { srvo := SERVO_1 // default for unknown ports if port == "2" || port == "SERVO_2" { srvo = SERVO_2 @@ -337,12 +355,12 @@ func (g *Driver) ServoWrite(port string, angle byte) error { angle = 180 } pulseWidth := ((1500 - (pulseWidthRange / 2)) + ((pulseWidthRange / 180) * int(angle))) - return g.SetServo(srvo, uint16(pulseWidth)) + return d.SetServo(srvo, uint16(pulseWidth)) } // SetMotorPower sets a motor's power from -128 to 127. -func (g *Driver) SetMotorPower(motor Motor, power int8) error { - return g.writeBytes([]byte{ +func (d *Driver) SetMotorPower(motor Motor, power int8) error { + return d.writeBytes([]byte{ goPiGo3Address, SET_MOTOR_PWM, byte(motor), @@ -351,9 +369,9 @@ func (g *Driver) SetMotorPower(motor Motor, power int8) error { } // SetMotorPosition sets the motor's position in degrees. -func (g *Driver) SetMotorPosition(motor Motor, position int) error { +func (d *Driver) SetMotorPosition(motor Motor, position int) error { positionRaw := position * MOTOR_TICKS_PER_DEGREE - return g.writeBytes([]byte{ + return d.writeBytes([]byte{ goPiGo3Address, SET_MOTOR_POSITION, byte(motor), @@ -365,21 +383,21 @@ func (g *Driver) SetMotorPosition(motor Motor, position int) error { } // SetMotorDps sets the motor target speed in degrees per second. -func (g *Driver) SetMotorDps(motor Motor, dps int) error { - d := dps * MOTOR_TICKS_PER_DEGREE - return g.writeBytes([]byte{ +func (d *Driver) SetMotorDps(motor Motor, dps int) error { + mdps := dps * MOTOR_TICKS_PER_DEGREE + return d.writeBytes([]byte{ goPiGo3Address, SET_MOTOR_DPS, byte(motor), - byte((d >> 8) & 0xFF), - byte(d & 0xFF), + byte((mdps >> 8) & 0xFF), + byte(mdps & 0xFF), }) } // SetMotorLimits sets the speed limits for a motor. -func (g *Driver) SetMotorLimits(motor Motor, power int8, dps int) error { +func (d *Driver) SetMotorLimits(motor Motor, power int8, dps int) error { dpsUint := dps * MOTOR_TICKS_PER_DEGREE - return g.writeBytes([]byte{ + return d.writeBytes([]byte{ goPiGo3Address, SET_MOTOR_LIMITS, byte(motor), @@ -390,16 +408,18 @@ func (g *Driver) SetMotorLimits(motor Motor, power int8, dps int) error { } // GetMotorStatus returns the status for the given motor. -func (g *Driver) GetMotorStatus(motor Motor) (flags uint8, power uint16, encoder, dps int, err error) { +// +//nolint:nonamedreturns // sufficient here +func (d *Driver) GetMotorStatus(motor Motor) (flags uint8, power uint16, encoder, dps int, err error) { message := GET_MOTOR_STATUS_RIGHT if motor == MOTOR_LEFT { message = GET_MOTOR_STATUS_LEFT } - response, err := g.readBytes(goPiGo3Address, message, 12) + response, err := d.readBytes(goPiGo3Address, message, 12) if err != nil { return flags, power, encoder, dps, err } - if err := g.responseValid(response); err != nil { + if err := d.responseValid(response); err != nil { return flags, power, encoder, dps, err } // get flags @@ -421,10 +441,10 @@ func (g *Driver) GetMotorStatus(motor Motor) (flags uint8, power uint16, encoder encoder = int(uint64(e) - 0x100000000) } // get dps - d := make([]byte, 4) - d[1] = response[10] - d[0] = response[11] - ds := binary.LittleEndian.Uint32(d) + dpsRaw := make([]byte, 4) + dpsRaw[1] = response[10] + dpsRaw[0] = response[11] + ds := binary.LittleEndian.Uint32(dpsRaw) dps = int(ds) if ds&0x8000 == 0x8000 { dps = int(ds - 0x10000) @@ -433,16 +453,16 @@ func (g *Driver) GetMotorStatus(motor Motor) (flags uint8, power uint16, encoder } // GetMotorEncoder reads a motor's encoder in degrees. -func (g *Driver) GetMotorEncoder(motor Motor) (encoder int64, err error) { +func (d *Driver) GetMotorEncoder(motor Motor) (int64, error) { message := GET_MOTOR_ENCODER_RIGHT if motor == MOTOR_LEFT { message = GET_MOTOR_ENCODER_LEFT } - response, err := g.readUint32(goPiGo3Address, message) + response, err := d.readUint32(goPiGo3Address, message) if err != nil { - return encoder, err + return 0, err } - encoder = int64(response) + encoder := int64(response) if response&0x80000000 != 0 { encoder = encoder - 0x100000000 } @@ -451,9 +471,9 @@ func (g *Driver) GetMotorEncoder(motor Motor) (encoder int64, err error) { } // OffsetMotorEncoder offsets a motor's encoder for calibration purposes. -func (g *Driver) OffsetMotorEncoder(motor Motor, offset float64) error { +func (d *Driver) OffsetMotorEncoder(motor Motor, offset float64) error { offsetUint := math.Float64bits(offset * MOTOR_TICKS_PER_DEGREE) - return g.writeBytes([]byte{ + return d.writeBytes([]byte{ goPiGo3Address, OFFSET_MOTOR_ENCODER, byte(motor), @@ -465,8 +485,8 @@ func (g *Driver) OffsetMotorEncoder(motor Motor, offset float64) error { } // SetGroveType sets the given port to a grove device type. -func (g *Driver) SetGroveType(port Grove, gType GroveType) error { - return g.writeBytes([]byte{ +func (d *Driver) SetGroveType(port Grove, gType GroveType) error { + return d.writeBytes([]byte{ goPiGo3Address, SET_GROVE_TYPE, byte(port), @@ -475,8 +495,8 @@ func (g *Driver) SetGroveType(port Grove, gType GroveType) error { } // SetGroveMode sets the mode a given pin/port of the grove connector. -func (g *Driver) SetGroveMode(port Grove, mode GroveMode) error { - return g.writeBytes([]byte{ +func (d *Driver) SetGroveMode(port Grove, mode GroveMode) error { + return d.writeBytes([]byte{ goPiGo3Address, SET_GROVE_MODE, byte(port), @@ -485,12 +505,12 @@ func (g *Driver) SetGroveMode(port Grove, mode GroveMode) error { } // SetPWMDuty sets the pwm duty cycle for the given pin/port. -func (g *Driver) SetPWMDuty(port Grove, duty uint16) error { +func (d *Driver) SetPWMDuty(port Grove, duty uint16) error { if duty > 100 { duty = 100 } duty = duty * 10 - return g.writeBytes([]byte{ + return d.writeBytes([]byte{ goPiGo3Address, SET_GROVE_PWM_DUTY, byte(port), @@ -500,14 +520,14 @@ func (g *Driver) SetPWMDuty(port Grove, duty uint16) error { } // SetPWMFreq setst the pwm frequency for the given pin/port. -func (g *Driver) SetPWMFreq(port Grove, freq uint16) error { +func (d *Driver) SetPWMFreq(port Grove, freq uint16) error { if freq < 3 { freq = 3 } if freq > 48000 { freq = 48000 } - return g.writeBytes([]byte{ + return d.writeBytes([]byte{ goPiGo3Address, SET_GROVE_PWM_FREQUENCY, byte(port), @@ -517,7 +537,7 @@ func (g *Driver) SetPWMFreq(port Grove, freq uint16) error { } // PwmWrite implents the pwm interface for the gopigo3. -func (g *Driver) PwmWrite(pin string, val byte) error { +func (d *Driver) PwmWrite(pin string, val byte) error { var ( grovePin, grovePort Grove err error @@ -525,49 +545,45 @@ func (g *Driver) PwmWrite(pin string, val byte) error { if grovePin, grovePort, _, _, err = getGroveAddresses(pin); err != nil { return err } - if err := g.SetGroveType(grovePort, CUSTOM); err != nil { + if err := d.SetGroveType(grovePort, CUSTOM); err != nil { return err } time.Sleep(10 * time.Millisecond) - if err = g.SetGroveMode(grovePin, GROVE_OUTPUT_PWM); err != nil { + if err = d.SetGroveMode(grovePin, GROVE_OUTPUT_PWM); err != nil { return err } time.Sleep(10 * time.Millisecond) - if err = g.SetPWMFreq(grovePin, 24000); err != nil { + if err = d.SetPWMFreq(grovePin, 24000); err != nil { return err } val64 := math.Float64frombits(uint64(val)) dutyCycle := uint16(math.Float64bits((100.0 / 255.0) * val64)) - return g.SetPWMDuty(grovePin, dutyCycle) + return d.SetPWMDuty(grovePin, dutyCycle) } // AnalogRead returns the analog value of the given pin. -func (g *Driver) AnalogRead(pin string) (value int, err error) { - var ( - grovePin, grovePort Grove - analogCmd byte - ) - grovePin, grovePort, analogCmd, _, err = getGroveAddresses(pin) +func (d *Driver) AnalogRead(pin string) (int, error) { + grovePin, grovePort, analogCmd, _, err := getGroveAddresses(pin) if err != nil { - return value, err + return 0, err } - if err := g.SetGroveType(grovePort, CUSTOM); err != nil { - return value, err + if err := d.SetGroveType(grovePort, CUSTOM); err != nil { + return 0, err } time.Sleep(10 * time.Millisecond) - if err := g.SetGroveMode(grovePin, GROVE_INPUT_ANALOG); err != nil { - return value, err + if err := d.SetGroveMode(grovePin, GROVE_INPUT_ANALOG); err != nil { + return 0, err } time.Sleep(10 * time.Millisecond) - response, err := g.readBytes(goPiGo3Address, analogCmd, 7) + response, err := d.readBytes(goPiGo3Address, analogCmd, 7) if err != nil { - return value, err + return 0, err } - if err := g.responseValid(response); err != nil { - return value, err + if err := d.responseValid(response); err != nil { + return 0, err } - if err := g.valueValid(response); err != nil { - return value, err + if err := d.valueValid(response); err != nil { + return 0, err } highBytes := uint16(response[5]) lowBytes := uint16(response[6]) @@ -575,7 +591,7 @@ func (g *Driver) AnalogRead(pin string) (value int, err error) { } // DigitalWrite writes a 0/1 value to the given pin. -func (g *Driver) DigitalWrite(pin string, val byte) error { +func (d *Driver) DigitalWrite(pin string, val byte) error { var ( grovePin, grovePort Grove err error @@ -584,15 +600,15 @@ func (g *Driver) DigitalWrite(pin string, val byte) error { if err != nil { return err } - if err := g.SetGroveType(grovePort, CUSTOM); err != nil { + if err := d.SetGroveType(grovePort, CUSTOM); err != nil { return err } time.Sleep(10 * time.Millisecond) - if err := g.SetGroveMode(grovePin, GROVE_OUTPUT_DIGITAL); err != nil { + if err := d.SetGroveMode(grovePin, GROVE_OUTPUT_DIGITAL); err != nil { return err } time.Sleep(10 * time.Millisecond) - return g.writeBytes([]byte{ + return d.writeBytes([]byte{ goPiGo3Address, SET_GROVE_STATE, byte(grovePin), @@ -601,38 +617,35 @@ func (g *Driver) DigitalWrite(pin string, val byte) error { } // DigitalRead reads the 0/1 value from the given pin. -func (g *Driver) DigitalRead(pin string) (value int, err error) { - var ( - grovePin, grovePort Grove - stateCmd byte - ) - grovePin, grovePort, _, stateCmd, err = getGroveAddresses(pin) +func (d *Driver) DigitalRead(pin string) (int, error) { + grovePin, grovePort, _, stateCmd, err := getGroveAddresses(pin) if err != nil { - return value, err + return 0, err } - err = g.SetGroveType(grovePort, CUSTOM) + err = d.SetGroveType(grovePort, CUSTOM) if err != nil { - return value, err + return 0, err } time.Sleep(10 * time.Millisecond) - err = g.SetGroveMode(grovePin, GROVE_INPUT_DIGITAL) + err = d.SetGroveMode(grovePin, GROVE_INPUT_DIGITAL) if err != nil { - return value, err + return 0, err } time.Sleep(10 * time.Millisecond) - response, err := g.readBytes(goPiGo3Address, stateCmd, 6) + response, err := d.readBytes(goPiGo3Address, stateCmd, 6) if err != nil { - return value, err + return 0, err } - if err := g.responseValid(response); err != nil { - return value, err + if err := d.responseValid(response); err != nil { + return 0, err } - if err := g.valueValid(response); err != nil { - return value, err + if err := d.valueValid(response); err != nil { + return 0, err } return int(response[5]), nil } +//nolint:nonamedreturns // sufficient here func getGroveAddresses(pin string) (gPin, gPort Grove, analog, state byte, err error) { switch pin { case "AD_1_1": @@ -661,75 +674,74 @@ func getGroveAddresses(pin string) (gPin, gPort Grove, analog, state byte, err e return gPin, gPort, analog, state, err } -func (g *Driver) responseValid(response []byte) error { +func (d *Driver) responseValid(response []byte) error { if response[3] != 0xA5 { return fmt.Errorf("No SPI response, response not valid") } return nil } -func (g *Driver) valueValid(value []byte) error { +func (d *Driver) valueValid(value []byte) error { if value[4] != byte(VALID_DATA) { return fmt.Errorf("Invalid value") } return nil } -func (g *Driver) readBytes(address byte, msg byte, numBytes int) (val []byte, err error) { +func (d *Driver) readBytes(address byte, msg byte, numBytes int) ([]byte, error) { w := make([]byte, numBytes) w[0] = address w[1] = msg r := make([]byte, len(w)) - err = g.connection.ReadCommandData(w, r) - if err != nil { - return val, err + if err := d.connection.ReadCommandData(w, r); err != nil { + return nil, err } return r, nil } -func (g *Driver) readUint16(address, msg byte) (val uint16, err error) { - r, err := g.readBytes(address, msg, 8) +func (d *Driver) readUint16(address, msg byte) (uint16, error) { + r, err := d.readBytes(address, msg, 8) if err != nil { - return val, err + return 0, err } - if err := g.responseValid(r); err != nil { - return val, err + if err := d.responseValid(r); err != nil { + return 0, err } return uint16(r[4])<<8 | uint16(r[5]), nil } -func (g *Driver) readUint32(address, msg byte) (val uint32, err error) { - r, err := g.readBytes(address, msg, 8) +func (d *Driver) readUint32(address, msg byte) (uint32, error) { + r, err := d.readBytes(address, msg, 8) if err != nil { - return val, err + return 0, err } - if err := g.responseValid(r); err != nil { - return val, err + if err := d.responseValid(r); err != nil { + return 0, err } return uint32(r[4])<<24 | uint32(r[5])<<16 | uint32(r[6])<<8 | uint32(r[7]), nil } -func (g *Driver) writeBytes(w []byte) error { - return g.connection.WriteBytes(w) +func (d *Driver) writeBytes(w []byte) error { + return d.connection.WriteBytes(w) } -func (g *Driver) resetAll() error { - err := g.SetGroveType(AD_1_G+AD_2_G, CUSTOM) +func (d *Driver) resetAll() error { + err := d.SetGroveType(AD_1_G+AD_2_G, CUSTOM) time.Sleep(10 * time.Millisecond) - if e := g.SetGroveMode(AD_1_G+AD_2_G, GROVE_INPUT_DIGITAL); e != nil { + if e := d.SetGroveMode(AD_1_G+AD_2_G, GROVE_INPUT_DIGITAL); e != nil { err = multierror.Append(err, e) } time.Sleep(10 * time.Millisecond) - if e := g.SetMotorPower(MOTOR_LEFT+MOTOR_RIGHT, 0.0); e != nil { + if e := d.SetMotorPower(MOTOR_LEFT+MOTOR_RIGHT, 0.0); e != nil { err = multierror.Append(err, e) } - if e := g.SetMotorLimits(MOTOR_LEFT+MOTOR_RIGHT, 0, 0); e != nil { + if e := d.SetMotorLimits(MOTOR_LEFT+MOTOR_RIGHT, 0, 0); e != nil { err = multierror.Append(err, e) } - if e := g.SetServo(SERVO_1+SERVO_2, 0); e != nil { + if e := d.SetServo(SERVO_1+SERVO_2, 0); e != nil { err = multierror.Append(err, e) } - if e := g.SetLED(LED_EYE_LEFT+LED_EYE_RIGHT+LED_BLINKER_LEFT+LED_BLINKER_RIGHT, 0, 0, 0); e != nil { + if e := d.SetLED(LED_EYE_LEFT+LED_EYE_RIGHT+LED_BLINKER_LEFT+LED_BLINKER_RIGHT, 0, 0, 0); e != nil { err = multierror.Append(err, e) } diff --git a/platforms/dexter/gopigo3/driver_test.go b/platforms/dexter/gopigo3/driver_test.go index 10e20658d..5e76c1ccd 100644 --- a/platforms/dexter/gopigo3/driver_test.go +++ b/platforms/dexter/gopigo3/driver_test.go @@ -4,7 +4,9 @@ import ( "encoding/hex" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/spi" ) @@ -31,226 +33,163 @@ func TestDriverHalt(t *testing.T) { } func TestDriverManufacturerName(t *testing.T) { - expectedName := "Dexter Industries" + wantName := "Dexter Industries" d := initTestDriver() name, err := d.GetManufacturerName() - if err != nil { - t.Error(err) - } - if name != expectedName { - t.Errorf("Expected name: %x, got: %x", expectedName, name) - } + require.NoError(t, err) + assert.Equal(t, wantName, name) } func TestDriverBoardName(t *testing.T) { - expectedBoardName := "GoPiGo3" + wantBoardName := "GoPiGo3" d := initTestDriver() name, err := d.GetBoardName() - if err != nil { - t.Error(err) - } - if name != expectedBoardName { - t.Errorf("Expected name: %s, got: %s", expectedBoardName, name) - } + require.NoError(t, err) + assert.Equal(t, wantBoardName, name) } func TestDriverHardwareVersion(t *testing.T) { - expectedHwVer := "3.1.3" + wantHwVer := "3.1.3" d := initTestDriver() ver, err := d.GetHardwareVersion() - if err != nil { - t.Error(err) - } - if ver != expectedHwVer { - t.Errorf("Expected hw ver: %s, got: %s", expectedHwVer, ver) - } + require.NoError(t, err) + assert.Equal(t, wantHwVer, ver) } func TestDriverFirmareVersion(t *testing.T) { - expectedFwVer := "0.3.4" + wantFwVer := "0.3.4" d := initTestDriver() ver, err := d.GetFirmwareVersion() - if err != nil { - t.Error(err) - } - if ver != expectedFwVer { - t.Errorf("Expected fw ver: %s, got: %s", expectedFwVer, ver) - } + require.NoError(t, err) + assert.Equal(t, wantFwVer, ver) } func TestGetSerialNumber(t *testing.T) { - expectedSerialNumber := "E0180A54514E343732202020FF112137" + wantSerialNumber := "E0180A54514E343732202020FF112137" d := initTestDriver() serial, err := d.GetSerialNumber() - if err != nil { - t.Error(err) - } - if serial != expectedSerialNumber { - t.Errorf("Expected serial number: %s, got: %s", expectedSerialNumber, serial) - } + require.NoError(t, err) + assert.Equal(t, wantSerialNumber, serial) } func TestGetFiveVolts(t *testing.T) { - expectedVoltage := float32(5.047000) + wantVoltage := float32(5.047000) d := initTestDriver() voltage, err := d.Get5vVoltage() - if err != nil { - t.Error(err) - } - if voltage != expectedVoltage { - t.Errorf("Expected 5v voltage: %f, got: %f", expectedVoltage, voltage) - } + require.NoError(t, err) + assert.InDelta(t, wantVoltage, voltage, 0.0) } func TestGetBatVolts(t *testing.T) { - expectedBatVoltage := float32(15.411000) + wantBatVoltage := float32(15.411000) d := initTestDriver() voltage, err := d.GetBatteryVoltage() - if err != nil { - t.Error(err) - } - if voltage != expectedBatVoltage { - t.Errorf("Expected battery voltage: %f, got: %f", expectedBatVoltage, voltage) - } + require.NoError(t, err) + assert.InDelta(t, wantBatVoltage, voltage, 0.0) } func TestGetMotorStatus(t *testing.T) { - expectedPower := uint16(65408) + wantPower := uint16(65408) d := initTestDriver() - _, power, _, _, err := d.GetMotorStatus(MOTOR_LEFT) - if err != nil { - t.Error(err) - } - if power != expectedPower { - t.Errorf("Expected power: %d, got: %d", expectedPower, power) - } + f1, power, f2, f3, err := d.GetMotorStatus(MOTOR_LEFT) + require.NoError(t, err) + assert.Equal(t, wantPower, power) + assert.Equal(t, uint8(0), f1) + assert.Equal(t, 0, f2) + assert.Equal(t, 0, f3) } func TestGetEncoderStatusPos(t *testing.T) { negativeEncoder = false - expectedEncoderValue := int64(127) + wantEncoderValue := int64(127) d := initTestDriver() encoderValue, err := d.GetMotorEncoder(MOTOR_LEFT) - if err != nil { - t.Error(err) - } - if encoderValue != expectedEncoderValue { - t.Errorf("Expected encoder value: %d, got: %d", expectedEncoderValue, encoderValue) - } + require.NoError(t, err) + assert.Equal(t, wantEncoderValue, encoderValue) } func TestGetEncoderStatusNeg(t *testing.T) { negativeEncoder = true - expectedEncoderValue := int64(-128) + wantEncoderValue := int64(-128) d := initTestDriver() encoderValue, err := d.GetMotorEncoder(MOTOR_LEFT) - if err != nil { - t.Error(err) - } - if encoderValue != expectedEncoderValue { - t.Errorf("Expected encoder value: %d, got: %d", expectedEncoderValue, encoderValue) - } + require.NoError(t, err) + assert.Equal(t, wantEncoderValue, encoderValue) } func TestAnalogRead(t *testing.T) { - expectedVal := 160 + wantVal := 160 d := initTestDriver() val, err := d.AnalogRead("AD_1_1") - if err != nil { - t.Error(err) - } - if val != expectedVal { - t.Errorf("Expected value: %d, got: %d", expectedVal, val) - } + require.NoError(t, err) + assert.Equal(t, wantVal, val) } func TestDigitalRead(t *testing.T) { - expectedVal := 1 + wantVal := 1 d := initTestDriver() val, err := d.DigitalRead("AD_1_2") - if err != nil { - t.Error(err) - } - if val != expectedVal { - t.Errorf("Expected value: %d, got: %d", expectedVal, val) - } + require.NoError(t, err) + assert.Equal(t, wantVal, val) } func TestServoWrite(t *testing.T) { d := initTestDriver() err := d.ServoWrite("SERVO_1", 0x7F) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestSetMotorPosition(t *testing.T) { d := initTestDriver() err := d.SetMotorPosition(MOTOR_LEFT, 12.0) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestSetMotorPower(t *testing.T) { d := initTestDriver() err := d.SetMotorPower(MOTOR_LEFT, 127) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestSetMotorDps(t *testing.T) { d := initTestDriver() err := d.SetMotorDps(MOTOR_LEFT, 12.0) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestOffsetMotorEncoder(t *testing.T) { d := initTestDriver() err := d.OffsetMotorEncoder(MOTOR_LEFT, 12.0) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestSetPWMDuty(t *testing.T) { d := initTestDriver() err := d.SetPWMDuty(AD_1_1_G, 80) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestSetPWMfreq(t *testing.T) { d := initTestDriver() err := d.SetPWMFreq(AD_1_2_G, 100) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestPwmWrite(t *testing.T) { d := initTestDriver() err := d.PwmWrite("AD_2_2", 80) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestDigitalWrite(t *testing.T) { d := initTestDriver() err := d.DigitalWrite("AD_2_1", 1) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } type TestConnector struct{} -func (ctr *TestConnector) GetSpiConnection(busNum, chipNum, mode, bits int, maxSpeed int64) (device spi.Connection, err error) { +func (ctr *TestConnector) GetSpiConnection(busNum, chipNum, mode, bits int, maxSpeed int64) (spi.Connection, error) { return TestSpiDevice{}, nil } diff --git a/platforms/digispark/digispark_adaptor.go b/platforms/digispark/digispark_adaptor.go index 29c0815b0..7d715ab8c 100644 --- a/platforms/digispark/digispark_adaptor.go +++ b/platforms/digispark/digispark_adaptor.go @@ -19,19 +19,20 @@ type Adaptor struct { servo bool pwm bool i2c bool - connect func(*Adaptor) (err error) + connect func(*Adaptor) error } // NewAdaptor returns a new Digispark Adaptor func NewAdaptor() *Adaptor { return &Adaptor{ name: gobot.DefaultName("Digispark"), - connect: func(d *Adaptor) (err error) { + connect: func(d *Adaptor) error { d.littleWire = littleWireConnect() + //nolint:forcetypeassert // ok here if d.littleWire.(*littleWire).lwHandle == nil { return ErrConnection } - return + return nil }, } } @@ -43,37 +44,36 @@ func (d *Adaptor) Name() string { return d.name } func (d *Adaptor) SetName(n string) { d.name = n } // Connect starts a connection to the digispark -func (d *Adaptor) Connect() (err error) { - err = d.connect(d) - return +func (d *Adaptor) Connect() error { + return d.connect(d) } // Finalize implements the Adaptor interface -func (d *Adaptor) Finalize() (err error) { return } +func (d *Adaptor) Finalize() error { return nil } // DigitalWrite writes a value to the pin. Acceptable values are 1 or 0. -func (d *Adaptor) DigitalWrite(pin string, level byte) (err error) { +func (d *Adaptor) DigitalWrite(pin string, level byte) error { p, err := strconv.Atoi(pin) if err != nil { - return + return err } - if err = d.littleWire.pinMode(uint8(p), 0); err != nil { - return + if err := d.littleWire.pinMode(uint8(p), 0); err != nil { + return err } return d.littleWire.digitalWrite(uint8(p), level) } // PwmWrite writes the 0-254 value to the specified pin -func (d *Adaptor) PwmWrite(pin string, value byte) (err error) { +func (d *Adaptor) PwmWrite(pin string, value byte) error { if !d.pwm { - if err = d.littleWire.pwmInit(); err != nil { - return + if err := d.littleWire.pwmInit(); err != nil { + return err } - if err = d.littleWire.pwmUpdatePrescaler(1); err != nil { - return + if err := d.littleWire.pwmUpdatePrescaler(1); err != nil { + return err } d.pwm = true } @@ -82,10 +82,10 @@ func (d *Adaptor) PwmWrite(pin string, value byte) (err error) { } // ServoWrite writes the 0-180 degree val to the specified pin. -func (d *Adaptor) ServoWrite(pin string, angle uint8) (err error) { +func (d *Adaptor) ServoWrite(pin string, angle uint8) error { if !d.servo { - if err = d.littleWire.servoInit(); err != nil { - return + if err := d.littleWire.servoInit(); err != nil { + return err } d.servo = true } @@ -94,7 +94,7 @@ func (d *Adaptor) ServoWrite(pin string, angle uint8) (err error) { // GetI2cConnection returns an i2c connection to a device on a specified bus. // Only supports bus number 0 -func (d *Adaptor) GetI2cConnection(address int, bus int) (connection i2c.Connection, err error) { +func (d *Adaptor) GetI2cConnection(address int, bus int) (i2c.Connection, error) { if bus != 0 { return nil, fmt.Errorf("Invalid bus number %d, only 0 is supported", bus) } diff --git a/platforms/digispark/digispark_adaptor_test.go b/platforms/digispark/digispark_adaptor_test.go index 2c1610d58..677018fa6 100644 --- a/platforms/digispark/digispark_adaptor_test.go +++ b/platforms/digispark/digispark_adaptor_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package digispark import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" ) @@ -77,7 +79,7 @@ func (l *mock) i2cUpdateDelay(duration uint) error func initTestAdaptor() *Adaptor { a := NewAdaptor() - a.connect = func(a *Adaptor) (err error) { return nil } + a.connect = func(a *Adaptor) error { return nil } a.littleWire = new(mock) errorFunc = func() error { return nil } pwmInitErrorFunc = func() error { return nil } diff --git a/platforms/digispark/digispark_i2c.go b/platforms/digispark/digispark_i2c.go index 6249c2a20..b63f50f1e 100644 --- a/platforms/digispark/digispark_i2c.go +++ b/platforms/digispark/digispark_i2c.go @@ -15,19 +15,19 @@ type digisparkI2cConnection struct { // NewDigisparkI2cConnection creates an i2c connection to an i2c device at // the specified address -func NewDigisparkI2cConnection(adaptor *Adaptor, address uint8) (connection *digisparkI2cConnection) { +func NewDigisparkI2cConnection(adaptor *Adaptor, address uint8) *digisparkI2cConnection { return &digisparkI2cConnection{adaptor: adaptor, address: address} } // Init makes sure that the i2c device is already initialized -func (c *digisparkI2cConnection) Init() (err error) { +func (c *digisparkI2cConnection) Init() error { if !c.adaptor.i2c { - if err = c.adaptor.littleWire.i2cInit(); err != nil { - return + if err := c.adaptor.littleWire.i2cInit(); err != nil { + return err } c.adaptor.i2c = true } - return + return nil } // Test tests i2c connection with the given address @@ -48,7 +48,7 @@ func (c *digisparkI2cConnection) UpdateDelay(duration uint) error { // Read tries to read a full buffer from the i2c device. // Returns an empty array if the response from the board has timed out. -func (c *digisparkI2cConnection) Read(b []byte) (countRead int, err error) { +func (c *digisparkI2cConnection) Read(b []byte) (int, error) { c.mtx.Lock() defer c.mtx.Unlock() @@ -56,7 +56,7 @@ func (c *digisparkI2cConnection) Read(b []byte) (countRead int, err error) { } // Write writes the buffer content in data to the i2c device. -func (c *digisparkI2cConnection) Write(data []byte) (countWritten int, err error) { +func (c *digisparkI2cConnection) Write(data []byte) (int, error) { c.mtx.Lock() defer c.mtx.Unlock() @@ -69,61 +69,61 @@ func (c *digisparkI2cConnection) Close() error { } // ReadByte reads one byte from the i2c device. -func (c *digisparkI2cConnection) ReadByte() (val byte, err error) { +func (c *digisparkI2cConnection) ReadByte() (byte, error) { c.mtx.Lock() defer c.mtx.Unlock() buf := []byte{0} - if err = c.readAndCheckCount(buf); err != nil { - return + if err := c.readAndCheckCount(buf); err != nil { + return 0, err } - val = buf[0] - return + val := buf[0] + return val, nil } // ReadByteData reads one byte of the given register address from the i2c device. -func (c *digisparkI2cConnection) ReadByteData(reg uint8) (val uint8, err error) { +func (c *digisparkI2cConnection) ReadByteData(reg uint8) (uint8, error) { c.mtx.Lock() defer c.mtx.Unlock() - if err = c.writeAndCheckCount([]byte{reg}, false); err != nil { - return + if err := c.writeAndCheckCount([]byte{reg}, false); err != nil { + return 0, err } buf := []byte{0} - if err = c.readAndCheckCount(buf); err != nil { - return + if err := c.readAndCheckCount(buf); err != nil { + return 0, err } - val = buf[0] - return + val := buf[0] + return val, nil } // ReadWordData reads two bytes of the given register address from the i2c device. -func (c *digisparkI2cConnection) ReadWordData(reg uint8) (val uint16, err error) { +func (c *digisparkI2cConnection) ReadWordData(reg uint8) (uint16, error) { c.mtx.Lock() defer c.mtx.Unlock() - if err = c.writeAndCheckCount([]byte{reg}, false); err != nil { - return + if err := c.writeAndCheckCount([]byte{reg}, false); err != nil { + return 0, err } buf := []byte{0, 0} - if err = c.readAndCheckCount(buf); err != nil { - return + if err := c.readAndCheckCount(buf); err != nil { + return 0, err } low, high := buf[0], buf[1] - val = (uint16(high) << 8) | uint16(low) - return + val := (uint16(high) << 8) | uint16(low) + return val, nil } // ReadBlockData reads a block of maximum 32 bytes from the given register address of the i2c device. -func (c *digisparkI2cConnection) ReadBlockData(reg uint8, data []byte) (err error) { +func (c *digisparkI2cConnection) ReadBlockData(reg uint8, data []byte) error { c.mtx.Lock() defer c.mtx.Unlock() - if err = c.writeAndCheckCount([]byte{reg}, false); err != nil { - return + if err := c.writeAndCheckCount([]byte{reg}, false); err != nil { + return err } if len(data) > 32 { @@ -212,42 +212,43 @@ func (c *digisparkI2cConnection) writeAndCheckCount(buf []byte, finalStop bool) return nil } -func (c *digisparkI2cConnection) readInternal(b []byte) (countRead int, err error) { +func (c *digisparkI2cConnection) readInternal(b []byte) (int, error) { if !c.adaptor.i2c { - err = errors.New("Digispark i2c not initialized") - return + err := errors.New("Digispark i2c not initialized") + return 0, err } - if err = c.adaptor.littleWire.i2cStart(c.address, 1); err != nil { - return + if err := c.adaptor.littleWire.i2cStart(c.address, 1); err != nil { + return 0, err } l := 8 stop := uint8(0) + var countRead int for stop == 0 { if countRead+l >= len(b) { l = len(b) - countRead stop = 1 } - if err = c.adaptor.littleWire.i2cRead(b[countRead:countRead+l], l, stop); err != nil { - return + if err := c.adaptor.littleWire.i2cRead(b[countRead:countRead+l], l, stop); err != nil { + return countRead, err } countRead += l } - return + return countRead, nil } -func (c *digisparkI2cConnection) writeInternal(data []byte, finalStop bool) (countWritten int, err error) { +func (c *digisparkI2cConnection) writeInternal(data []byte, finalStop bool) (int, error) { if !c.adaptor.i2c { - err = errors.New("Digispark i2c not initialized") - return + return 0, errors.New("Digispark i2c not initialized") } - if err = c.adaptor.littleWire.i2cStart(c.address, 0); err != nil { - return + if err := c.adaptor.littleWire.i2cStart(c.address, 0); err != nil { + return 0, err } l := 4 lastQuadruplet := false stop := uint8(0) + var countWritten int for !lastQuadruplet { if countWritten+l >= len(data) { lastQuadruplet = true @@ -256,10 +257,10 @@ func (c *digisparkI2cConnection) writeInternal(data []byte, finalStop bool) (cou stop = 1 } } - if err = c.adaptor.littleWire.i2cWrite(data[countWritten:countWritten+l], l, stop); err != nil { - return + if err := c.adaptor.littleWire.i2cWrite(data[countWritten:countWritten+l], l, stop); err != nil { + return countWritten, err } countWritten += l } - return + return countWritten, nil } diff --git a/platforms/digispark/digispark_i2c_test.go b/platforms/digispark/digispark_i2c_test.go index ff6412255..b14b7fb38 100644 --- a/platforms/digispark/digispark_i2c_test.go +++ b/platforms/digispark/digispark_i2c_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package digispark import ( @@ -6,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2/drivers/i2c" ) @@ -31,7 +33,7 @@ type i2cMock struct { func initTestAdaptorI2c() *Adaptor { a := NewAdaptor() - a.connect = func(a *Adaptor) (err error) { return nil } + a.connect = func(a *Adaptor) error { return nil } a.littleWire = new(i2cMock) return a } diff --git a/platforms/digispark/littleWire.go b/platforms/digispark/littleWire.go index f88c8990b..39f129c1e 100644 --- a/platforms/digispark/littleWire.go +++ b/platforms/digispark/littleWire.go @@ -3,7 +3,7 @@ package digispark //#cgo pkg-config: libusb //#include "littleWire.h" //#include "littleWire_servo.h" -//typedef usb_dev_handle littleWire; +// typedef usb_dev_handle littleWire; import "C" import ( diff --git a/platforms/dji/tello/crc.go b/platforms/dji/tello/crc.go index 3aa031b0d..27ef8da15 100644 --- a/platforms/dji/tello/crc.go +++ b/platforms/dji/tello/crc.go @@ -29,6 +29,7 @@ func CalculateCRC8(pkt []byte) byte { return crc } +//nolint:lll // ok here var crc16table = []uint16{ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, diff --git a/platforms/dji/tello/driver.go b/platforms/dji/tello/driver.go index 808993c05..0510c0316 100644 --- a/platforms/dji/tello/driver.go +++ b/platforms/dji/tello/driver.go @@ -205,8 +205,8 @@ func NewDriver(port string) *Driver { return NewDriverWithIP("192.168.10.1", port) } -// NewDriverWithIP creates a driver for the Tello EDU drone. Pass in the ip address and UDP port to use for the responses -// from the drone. +// NewDriverWithIP creates a driver for the Tello EDU drone. Pass in the ip address and UDP port to use for +// the responses from the drone. func NewDriverWithIP(ip string, port string) *Driver { d := &Driver{ name: gobot.DefaultName("Tello"), @@ -533,6 +533,8 @@ func bound(x, y float32) float32 { //nolint:unparam // keep y as parameter // Values are from 0 to 1. // x, y, z denote forward, side and vertical translation, // and psi yaw (rotation around the z-axis). +// +//nolint:nonamedreturns // sufficient here func (d *Driver) Vector() (x, y, z, psi float32) { return d.ry, d.rx, d.ly, d.lx } @@ -890,7 +892,8 @@ func (d *Driver) SendStickCommand() error { // speed control axis5 := int16(d.throttle) - packedAxis := int64(axis1)&0x7FF | int64(axis2&0x7FF)<<11 | 0x7FF&int64(axis3)<<22 | 0x7FF&int64(axis4)<<33 | int64(axis5)<<44 + packedAxis := int64(axis1)&0x7FF | int64(axis2&0x7FF)<<11 | 0x7FF&int64(axis3)<<22 | 0x7FF&int64(axis4)<<33 | + int64(axis5)<<44 if err := binary.Write(buf, binary.LittleEndian, byte(0xFF&packedAxis)); err != nil { return err } @@ -1071,8 +1074,8 @@ func (d *Driver) processVideo() error { return nil } -func (d *Driver) createPacket(cmd int16, pktType byte, len int16) (*bytes.Buffer, error) { - l := len + 11 +func (d *Driver) createPacket(cmd int16, pktType byte, pktLen int16) (*bytes.Buffer, error) { + l := pktLen + 11 buf := &bytes.Buffer{} if err := binary.Write(buf, binary.LittleEndian, byte(messageStart)); err != nil { diff --git a/platforms/dji/tello/driver_test.go b/platforms/dji/tello/driver_test.go index 3571c0160..cef8c2c08 100644 --- a/platforms/dji/tello/driver_test.go +++ b/platforms/dji/tello/driver_test.go @@ -10,6 +10,8 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -17,7 +19,7 @@ var _ gobot.Driver = (*Driver)(nil) type WriteCloserDoNothing struct{} -func (w *WriteCloserDoNothing) Write(p []byte) (n int, err error) { +func (w *WriteCloserDoNothing) Write(p []byte) (int, error) { return 0, nil } @@ -113,9 +115,7 @@ func Test_handleResponse(t *testing.T) { d := NewDriver("8888") events := d.Subscribe() err := d.handleResponse(bytes.NewReader(tc.msg)) - if tc.err != err { - t.Errorf("expected '%v' error, got: %v", tc.err, err) - } + require.ErrorIs(t, tc.err, err) if tc.wantEvent != "" { select { case ev, ok := <-events: diff --git a/platforms/dragonboard/dragonboard_adaptor.go b/platforms/dragonboard/dragonboard_adaptor.go index cd79f5117..0f75eac41 100644 --- a/platforms/dragonboard/dragonboard_adaptor.go +++ b/platforms/dragonboard/dragonboard_adaptor.go @@ -5,6 +5,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" diff --git a/platforms/dragonboard/dragonboard_adaptor_test.go b/platforms/dragonboard/dragonboard_adaptor_test.go index d6c8fe4b0..cd8cb6adf 100644 --- a/platforms/dragonboard/dragonboard_adaptor_test.go +++ b/platforms/dragonboard/dragonboard_adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -77,7 +78,7 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestI2cDefaultBus(t *testing.T) { @@ -99,7 +100,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateI2cBusNumber(t *testing.T) { diff --git a/platforms/firmata/ble_firmata_adaptor.go b/platforms/firmata/ble_firmata_adaptor.go index 2aa8d2a6c..7150b8de5 100644 --- a/platforms/firmata/ble_firmata_adaptor.go +++ b/platforms/firmata/ble_firmata_adaptor.go @@ -27,10 +27,11 @@ type BLEAdaptor struct { // NewBLEAdaptor opens and uses a BLE connection to a // microcontroller running FirmataBLE func NewBLEAdaptor(args ...interface{}) *BLEAdaptor { - address := args[0].(string) + address := args[0].(string) //nolint:forcetypeassert // ok here rid := ReceiveID wid := TransmitID + //nolint:forcetypeassert // ok here if len(args) >= 3 { rid = args[1].(string) wid = args[2].(string) diff --git a/platforms/firmata/ble_firmata_adaptor_test.go b/platforms/firmata/ble_firmata_adaptor_test.go index 0e6c88079..774f43c11 100644 --- a/platforms/firmata/ble_firmata_adaptor_test.go +++ b/platforms/firmata/ble_firmata_adaptor_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/firmata/client/client.go b/platforms/firmata/client/client.go index d445ed2a2..0f0f6f246 100644 --- a/platforms/firmata/client/client.go +++ b/platforms/firmata/client/client.go @@ -135,11 +135,13 @@ func (b *Client) Disconnect() error { // Connecting returns true when the client is connecting func (b *Client) Connecting() bool { + //nolint:forcetypeassert // ok here return b.connecting.Load().(bool) } // Connected returns the current connection state of the Client func (b *Client) Connected() bool { + //nolint:forcetypeassert // ok here return b.connected.Load().(bool) } @@ -371,7 +373,7 @@ func (b *Client) WriteSysex(data []byte) error { } func (b *Client) write(data []byte) error { - _, err := b.connection.Write(data[:]) + _, err := b.connection.Write(data) return err } @@ -530,7 +532,7 @@ func (b *Client) process() error { name = append(name, val) } } - b.FirmwareName = string(name[:]) + b.FirmwareName = string(name) b.Publish(b.Event("FirmwareQuery"), b.FirmwareName) case StringData: str := currentBuffer[2:] diff --git a/platforms/firmata/client/client_test.go b/platforms/firmata/client/client_test.go index 0bf1690e4..63f08457b 100644 --- a/platforms/firmata/client/client_test.go +++ b/platforms/firmata/client/client_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" ) -const semPublishWait = 10 * time.Millisecond +const semPublishWait = 20 * time.Millisecond type readWriteCloser struct { id string diff --git a/platforms/firmata/firmata_adaptor.go b/platforms/firmata/firmata_adaptor.go index 4246b14d2..24f64f9c5 100644 --- a/platforms/firmata/firmata_adaptor.go +++ b/platforms/firmata/firmata_adaptor.go @@ -10,6 +10,7 @@ import ( "time" "go.bug.st/serial" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/platforms/firmata/client" @@ -19,7 +20,7 @@ type firmataBoard interface { Connect(conn io.ReadWriteCloser) error Disconnect() error Pins() []client.Pin - AnalogWrite(pin int, value int) (err error) + AnalogWrite(pin int, value int) error SetPinMode(pin int, mode int) error ReportAnalog(pin int, state int) error ReportDigital(pin int, state int) error @@ -186,18 +187,18 @@ func (f *Adaptor) DigitalWrite(pin string, level byte) error { // DigitalRead retrieves digital value from specified pin. // Returns -1 if the response from the board has timed out -func (f *Adaptor) DigitalRead(pin string) (val int, err error) { +func (f *Adaptor) DigitalRead(pin string) (int, error) { p, err := strconv.Atoi(pin) if err != nil { - return + return 0, err } if f.Board.Pins()[p].Mode != client.Input { - if err = f.Board.SetPinMode(p, client.Input); err != nil { - return + if err := f.Board.SetPinMode(p, client.Input); err != nil { + return 0, err } - if err = f.Board.ReportDigital(p, 1); err != nil { - return + if err := f.Board.ReportDigital(p, 1); err != nil { + return 0, err } <-time.After(10 * time.Millisecond) } diff --git a/platforms/firmata/firmata_adaptor_test.go b/platforms/firmata/firmata_adaptor_test.go index 23ecf4591..1e62a7abf 100644 --- a/platforms/firmata/firmata_adaptor_test.go +++ b/platforms/firmata/firmata_adaptor_test.go @@ -1,6 +1,7 @@ //go:build !windows // +build !windows +//nolint:forcetypeassert // ok here package firmata import ( @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" diff --git a/platforms/firmata/firmata_i2c.go b/platforms/firmata/firmata_i2c.go index 4e7759a10..e4c5d8714 100644 --- a/platforms/firmata/firmata_i2c.go +++ b/platforms/firmata/firmata_i2c.go @@ -19,13 +19,13 @@ type firmataI2cConnection struct { // NewFirmataI2cConnection creates an I2C connection to an I2C device at // the specified address -func NewFirmataI2cConnection(adaptor *Adaptor, address int) (connection *firmataI2cConnection) { +func NewFirmataI2cConnection(adaptor *Adaptor, address int) *firmataI2cConnection { return &firmataI2cConnection{adaptor: adaptor, address: address} } // Read tries to read a full buffer from the i2c device. // Returns an empty array if the response from the board has timed out. -func (c *firmataI2cConnection) Read(b []byte) (read int, err error) { +func (c *firmataI2cConnection) Read(b []byte) (int, error) { c.mtx.Lock() defer c.mtx.Unlock() @@ -33,7 +33,7 @@ func (c *firmataI2cConnection) Read(b []byte) (read int, err error) { } // Write writes the buffer content in data to the i2c device. -func (c *firmataI2cConnection) Write(data []byte) (written int, err error) { +func (c *firmataI2cConnection) Write(data []byte) (int, error) { c.mtx.Lock() defer c.mtx.Unlock() @@ -205,7 +205,7 @@ func (c *firmataI2cConnection) readInternal(b []byte) (int, error) { } if err := c.adaptor.Board.Once(c.adaptor.Board.Event("I2cReply"), func(data interface{}) { - ret <- data.(client.I2cReply).Data + ret <- data.(client.I2cReply).Data //nolint:forcetypeassert // ok here }); err != nil { return 0, err } @@ -227,7 +227,7 @@ func (c *firmataI2cConnection) writeInternal(data []byte) (int, error) { written += len(chunk) } if len(data) > 0 { - if err := c.adaptor.Board.I2cWrite(c.address, data[:]); err != nil { + if err := c.adaptor.Board.I2cWrite(c.address, data); err != nil { return written, err } written += len(data) diff --git a/platforms/firmata/firmata_i2c_test.go b/platforms/firmata/firmata_i2c_test.go index 4a12040ec..8b06ca6f6 100644 --- a/platforms/firmata/firmata_i2c_test.go +++ b/platforms/firmata/firmata_i2c_test.go @@ -1,6 +1,7 @@ //go:build !windows // +build !windows +//nolint:forcetypeassert // ok here package firmata import ( @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/platforms/firmata/client" diff --git a/platforms/firmata/tcp_firmata_adaptor.go b/platforms/firmata/tcp_firmata_adaptor.go index af34cac96..5a5b47b6e 100644 --- a/platforms/firmata/tcp_firmata_adaptor.go +++ b/platforms/firmata/tcp_firmata_adaptor.go @@ -16,22 +16,20 @@ type TCPAdaptor struct { *Adaptor } -func connect(address string) (io.ReadWriteCloser, error) { - return net.Dial("tcp", address) -} - // NewTCPAdaptor opens and uses a TCP connection to a microcontroller running // WiFiFirmata func NewTCPAdaptor(args ...interface{}) *TCPAdaptor { - address := args[0].(string) + address := args[0].(string) //nolint:forcetypeassert // ok here a := NewAdaptor(address) a.SetName(gobot.DefaultName("TCPFirmata")) - a.PortOpener = func(port string) (io.ReadWriteCloser, error) { - return connect(port) - } + a.PortOpener = connect return &TCPAdaptor{ Adaptor: a, } } + +func connect(address string) (io.ReadWriteCloser, error) { + return net.Dial("tcp", address) +} diff --git a/platforms/firmata/tcp_firmata_adaptor_test.go b/platforms/firmata/tcp_firmata_adaptor_test.go index b63937a21..b5d8542af 100644 --- a/platforms/firmata/tcp_firmata_adaptor_test.go +++ b/platforms/firmata/tcp_firmata_adaptor_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/holystone/holystone.go b/platforms/holystone/holystone.go index 6a9ea73b7..a1f233583 100644 --- a/platforms/holystone/holystone.go +++ b/platforms/holystone/holystone.go @@ -2,4 +2,6 @@ // Currently only have support for the HS200 drone. // For more information, go to: // http://www.holystone.com/product/Holy_Stone_HS200W_FPV_Drone_with_720P_HD_Live_Video_Wifi_Camera_2_4GHz_4CH_6_Axis_Gyro_RC_Quadcopter_with_Altitude_Hold,_Gravity_Sensor_and_Headless_Mode_Function_RTF,_Color_Red-39.html +// +//nolint:lll // ok here package holystone // import "gobot.io/x/gobot/v2/platforms/holystone" diff --git a/platforms/holystone/hs200/hs200_driver.go b/platforms/holystone/hs200/hs200_driver.go index e11f4114d..477c1561f 100644 --- a/platforms/holystone/hs200/hs200_driver.go +++ b/platforms/holystone/hs200/hs200_driver.go @@ -61,7 +61,7 @@ func (d *Driver) SetName(n string) { d.name = n } func (d *Driver) Connection() gobot.Connection { return nil } // Start starts the driver. -func (d *Driver) Start() (err error) { +func (d *Driver) Start() error { tc, terr := net.Dial("tcp", d.tcpaddress) if terr != nil { return terr @@ -74,13 +74,13 @@ func (d *Driver) Start() (err error) { d.udpconn = uc d.tcpconn = tc - return + return nil } // Halt stops the driver. -func (d *Driver) Halt() (err error) { +func (d *Driver) Halt() error { d.stop() - return + return nil } func (d *Driver) stop() { diff --git a/platforms/holystone/hs200/hs200_driver_test.go b/platforms/holystone/hs200/hs200_driver_test.go index 42519a829..9bd32abe2 100644 --- a/platforms/holystone/hs200/hs200_driver_test.go +++ b/platforms/holystone/hs200/hs200_driver_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/intel-iot/curie/imu_driver.go b/platforms/intel-iot/curie/imu_driver.go index ea1e7852f..15998c84d 100644 --- a/platforms/intel-iot/curie/imu_driver.go +++ b/platforms/intel-iot/curie/imu_driver.go @@ -75,6 +75,7 @@ func NewIMUDriver(a *firmata.Adaptor) *IMUDriver { // Start starts up the IMUDriver func (imu *IMUDriver) Start() error { return imu.connection.On("SysexResponse", func(res interface{}) { + //nolint:forcetypeassert // ok here data := res.([]byte) if err := imu.handleEvent(data); err != nil { panic(err) diff --git a/platforms/intel-iot/curie/imu_driver_test.go b/platforms/intel-iot/curie/imu_driver_test.go index 051112fab..16422af86 100644 --- a/platforms/intel-iot/curie/imu_driver_test.go +++ b/platforms/intel-iot/curie/imu_driver_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/firmata" "gobot.io/x/gobot/v2/platforms/firmata/client" ) @@ -216,7 +216,9 @@ func TestIMUDriverReadMotionData(t *testing.T) { _, err := parseMotionData([]byte{}) require.ErrorContains(t, err, "Invalid data") - result, err := parseMotionData([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7}) + result, err := parseMotionData([]byte{ + 0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7, + }) require.NoError(t, err) assert.Equal(t, &MotionData{AX: 1920, AY: 1920, AZ: 1920, GX: 1920, GY: 1920, GZ: 1920}, result) } @@ -231,5 +233,7 @@ func TestIMUDriverHandleEvents(t *testing.T) { require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x03, 0x00, 0x02, 0xf7})) require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x04, 0x00, 0x02, 0xf7})) require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x05, 0x00, 0x02, 0xf7})) - require.NoError(t, d.handleEvent([]byte{0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7})) + require.NoError(t, d.handleEvent([]byte{ + 0xF0, 0x11, 0x06, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0xf7, + })) } diff --git a/platforms/intel-iot/edison/edison_adaptor.go b/platforms/intel-iot/edison/edison_adaptor.go index bcd754126..17a7b24ff 100644 --- a/platforms/intel-iot/edison/edison_adaptor.go +++ b/platforms/intel-iot/edison/edison_adaptor.go @@ -7,6 +7,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -104,7 +105,8 @@ func (c *Adaptor) Connect() error { } // Finalize releases all i2c devices and exported analog, digital, pwm pins. -func (c *Adaptor) Finalize() (err error) { +func (c *Adaptor) Finalize() error { + var err error if c.tristate != nil { if errs := c.tristate.Unexport(); errs != nil { err = multierror.Append(err, errs) @@ -129,23 +131,23 @@ func (c *Adaptor) Finalize() (err error) { err = multierror.Append(err, e) } c.arduinoI2cInitialized = false - return + return err } // DigitalRead reads digital value from pin -func (c *Adaptor) DigitalRead(pin string) (i int, err error) { +func (c *Adaptor) DigitalRead(pin string) (int, error) { c.mutex.Lock() defer c.mutex.Unlock() sysPin, err := c.digitalPin(pin, system.WithPinDirectionInput()) if err != nil { - return + return 0, err } return sysPin.Read() } // DigitalWrite writes a value to the pin. Acceptable values are 1 or 0. -func (c *Adaptor) DigitalWrite(pin string, val byte) (err error) { +func (c *Adaptor) DigitalWrite(pin string, val byte) error { c.mutex.Lock() defer c.mutex.Unlock() @@ -162,13 +164,13 @@ func (c *Adaptor) DigitalPin(id string) (gobot.DigitalPinner, error) { } // AnalogRead returns value from analog reading of specified pin -func (c *Adaptor) AnalogRead(pin string) (val int, err error) { +func (c *Adaptor) AnalogRead(pin string) (int, error) { buf, err := c.readFile("/sys/bus/iio/devices/iio:device1/in_voltage" + pin + "_raw") if err != nil { - return + return 0, err } - val, err = strconv.Atoi(string(buf[0 : len(buf)-1])) + val, err := strconv.Atoi(string(buf[0 : len(buf)-1])) return val / 4, err } @@ -370,7 +372,10 @@ func (c *Adaptor) newUnexportedDigitalPin(i int, o ...func(gobot.DigitalPinOptio return io.Unexport() } -func (c *Adaptor) newExportedDigitalPin(pin int, o ...func(gobot.DigitalPinOptioner) bool) (gobot.DigitalPinner, error) { +func (c *Adaptor) newExportedDigitalPin( + pin int, + o ...func(gobot.DigitalPinOptioner) bool, +) (gobot.DigitalPinner, error) { sysPin := c.sys.NewDigitalPin("", pin, o...) err := sysPin.Export() return sysPin, err @@ -387,10 +392,10 @@ func (c *Adaptor) changePinMode(pin, mode string) error { return err } -func (c *Adaptor) digitalWrite(pin string, val byte) (err error) { +func (c *Adaptor) digitalWrite(pin string, val byte) error { sysPin, err := c.digitalPin(pin, system.WithPinDirectionOutput(int(val))) if err != nil { - return + return err } return sysPin.Write(int(val)) } diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index 64a2a7b6e..6709d9991 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" @@ -244,7 +245,7 @@ func TestArduinoSetupFail263(t *testing.T) { delete(fs.Files, "/sys/class/gpio/gpio263/direction") err := a.arduinoSetup() - assert.Contains(t, err.Error(), "/sys/class/gpio/gpio263/direction: no such file") + require.ErrorContains(t, err, "/sys/class/gpio/gpio263/direction: no such file") } func TestArduinoSetupFail240(t *testing.T) { @@ -252,7 +253,7 @@ func TestArduinoSetupFail240(t *testing.T) { delete(fs.Files, "/sys/class/gpio/gpio240/direction") err := a.arduinoSetup() - assert.Contains(t, err.Error(), "/sys/class/gpio/gpio240/direction: no such file") + require.ErrorContains(t, err, "/sys/class/gpio/gpio240/direction: no such file") } func TestArduinoSetupFail111(t *testing.T) { @@ -260,7 +261,7 @@ func TestArduinoSetupFail111(t *testing.T) { delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux") err := a.arduinoSetup() - assert.Contains(t, err.Error(), "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux: no such file") + require.ErrorContains(t, err, "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux: no such file") } func TestArduinoSetupFail131(t *testing.T) { @@ -268,7 +269,7 @@ func TestArduinoSetupFail131(t *testing.T) { delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux") err := a.arduinoSetup() - assert.Contains(t, err.Error(), "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux: no such file") + require.ErrorContains(t, err, "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux: no such file") } func TestArduinoI2CSetupFailTristate(t *testing.T) { @@ -287,7 +288,7 @@ func TestArduinoI2CSetupFail14(t *testing.T) { delete(fs.Files, "/sys/class/gpio/gpio14/direction") err := a.arduinoI2CSetup() - assert.Contains(t, err.Error(), "/sys/class/gpio/gpio14/direction: no such file") + require.ErrorContains(t, err, "/sys/class/gpio/gpio14/direction: no such file") } func TestArduinoI2CSetupUnexportFail(t *testing.T) { @@ -297,7 +298,7 @@ func TestArduinoI2CSetupUnexportFail(t *testing.T) { delete(fs.Files, "/sys/class/gpio/unexport") err := a.arduinoI2CSetup() - assert.Contains(t, err.Error(), "/sys/class/gpio/unexport: no such file") + require.ErrorContains(t, err, "/sys/class/gpio/unexport: no such file") } func TestArduinoI2CSetupFail236(t *testing.T) { @@ -307,7 +308,7 @@ func TestArduinoI2CSetupFail236(t *testing.T) { delete(fs.Files, "/sys/class/gpio/gpio236/direction") err := a.arduinoI2CSetup() - assert.Contains(t, err.Error(), "/sys/class/gpio/gpio236/direction: no such file") + require.ErrorContains(t, err, "/sys/class/gpio/gpio236/direction: no such file") } func TestArduinoI2CSetupFail28(t *testing.T) { @@ -317,7 +318,7 @@ func TestArduinoI2CSetupFail28(t *testing.T) { delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux") err := a.arduinoI2CSetup() - assert.Contains(t, err.Error(), "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux: no such file") + require.ErrorContains(t, err, "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux: no such file") } func TestConnectArduinoError(t *testing.T) { @@ -325,7 +326,7 @@ func TestConnectArduinoError(t *testing.T) { fs.WithWriteError = true err := a.Connect() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestConnectArduinoWriteError(t *testing.T) { @@ -333,7 +334,7 @@ func TestConnectArduinoWriteError(t *testing.T) { fs.WithWriteError = true err := a.Connect() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestConnectSparkfun(t *testing.T) { @@ -356,7 +357,7 @@ func TestConnectUnknown(t *testing.T) { a := NewAdaptor("wha") err := a.Connect() - assert.Contains(t, err.Error(), "Unknown board type: wha") + require.ErrorContains(t, err, "Unknown board type: wha") } func TestFinalize(t *testing.T) { @@ -376,8 +377,8 @@ func TestFinalize(t *testing.T) { // remove one file to force Finalize error delete(fs.Files, "/sys/class/gpio/unexport") err := a.Finalize() - assert.Contains(t, err.Error(), "1 error occurred") - assert.Contains(t, err.Error(), "/sys/class/gpio/unexport") + require.ErrorContains(t, err, "1 error occurred") + require.ErrorContains(t, err, "/sys/class/gpio/unexport") } func TestFinalizeError(t *testing.T) { @@ -387,10 +388,10 @@ func TestFinalizeError(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "6 errors occurred") - assert.Contains(t, err.Error(), "write error") - assert.Contains(t, err.Error(), "SetEnabled(false) failed for id 1 with write error") - assert.Contains(t, err.Error(), "Unexport() failed for id 1 with write error") + require.ErrorContains(t, err, "6 errors occurred") + require.ErrorContains(t, err, "write error") + require.ErrorContains(t, err, "SetEnabled(false) failed for id 1 with write error") + require.ErrorContains(t, err, "Unexport() failed for id 1 with write error") } func TestDigitalIO(t *testing.T) { @@ -413,7 +414,7 @@ func TestDigitalPinInFileError(t *testing.T) { _ = a.Connect() _, err := a.DigitalPin("13") - assert.Contains(t, err.Error(), "no such file") + require.ErrorContains(t, err, "no such file") } func TestDigitalPinInResistorFileError(t *testing.T) { @@ -424,7 +425,7 @@ func TestDigitalPinInResistorFileError(t *testing.T) { _ = a.Connect() _, err := a.DigitalPin("13") - assert.Contains(t, err.Error(), "no such file") + require.ErrorContains(t, err, "no such file") } func TestDigitalPinInLevelShifterFileError(t *testing.T) { @@ -435,7 +436,7 @@ func TestDigitalPinInLevelShifterFileError(t *testing.T) { _ = a.Connect() _, err := a.DigitalPin("13") - assert.Contains(t, err.Error(), "no such file") + require.ErrorContains(t, err, "no such file") } func TestDigitalPinInMuxFileError(t *testing.T) { @@ -446,7 +447,7 @@ func TestDigitalPinInMuxFileError(t *testing.T) { _ = a.Connect() _, err := a.DigitalPin("13") - assert.Contains(t, err.Error(), "no such file") + require.ErrorContains(t, err, "no such file") } func TestDigitalWriteError(t *testing.T) { @@ -484,7 +485,7 @@ func TestPwmExportError(t *testing.T) { require.NoError(t, err) err = a.PwmWrite("5", 100) - assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/export: no such file") + require.ErrorContains(t, err, "/sys/class/pwm/pwmchip0/export: no such file") } func TestPwmEnableError(t *testing.T) { @@ -494,7 +495,7 @@ func TestPwmEnableError(t *testing.T) { _ = a.Connect() err := a.PwmWrite("5", 100) - assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/pwm1/enable: no such file") + require.ErrorContains(t, err, "/sys/class/pwm/pwmchip0/pwm1/enable: no such file") } func TestPwmWritePinError(t *testing.T) { @@ -510,7 +511,7 @@ func TestPwmWriteError(t *testing.T) { fs.WithWriteError = true err := a.PwmWrite("5", 100) - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestPwmReadError(t *testing.T) { @@ -518,7 +519,7 @@ func TestPwmReadError(t *testing.T) { fs.WithReadError = true err := a.PwmWrite("5", 100) - assert.Contains(t, err.Error(), "read error") + require.ErrorContains(t, err, "read error") } func TestAnalog(t *testing.T) { @@ -570,7 +571,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { err = a.Finalize() // assert require.Error(t, err) - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateI2cBusNumber(t *testing.T) { diff --git a/platforms/intel-iot/joule/joule_adaptor.go b/platforms/intel-iot/joule/joule_adaptor.go index 3de700344..0afdc83d5 100644 --- a/platforms/intel-iot/joule/joule_adaptor.go +++ b/platforms/intel-iot/joule/joule_adaptor.go @@ -5,6 +5,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -40,7 +41,8 @@ func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { sys: sys, } c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) - c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin, adaptors.WithPWMPinInitializer(pwmPinInitializer)) + c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin, + adaptors.WithPWMPinInitializer(pwmPinInitializer)) c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber) return c } diff --git a/platforms/intel-iot/joule/joule_adaptor_test.go b/platforms/intel-iot/joule/joule_adaptor_test.go index 21896a35d..fa159a4ab 100644 --- a/platforms/intel-iot/joule/joule_adaptor_test.go +++ b/platforms/intel-iot/joule/joule_adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -156,7 +157,7 @@ func TestPwmPinExportError(t *testing.T) { delete(fs.Files, "/sys/class/pwm/pwmchip0/export") err := a.PwmWrite("J12_26", 100) - assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/export: no such file") + require.ErrorContains(t, err, "/sys/class/pwm/pwmchip0/export: no such file") } func TestPwmPinEnableError(t *testing.T) { @@ -164,7 +165,7 @@ func TestPwmPinEnableError(t *testing.T) { delete(fs.Files, "/sys/class/pwm/pwmchip0/pwm0/enable") err := a.PwmWrite("J12_26", 100) - assert.Contains(t, err.Error(), "/sys/class/pwm/pwmchip0/pwm0/enable: no such file") + require.ErrorContains(t, err, "/sys/class/pwm/pwmchip0/pwm0/enable: no such file") } func TestI2cDefaultBus(t *testing.T) { @@ -186,7 +187,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateI2cBusNumber(t *testing.T) { diff --git a/platforms/jetson/jetson_adaptor.go b/platforms/jetson/jetson_adaptor.go index c0e25b4c4..ce336ed34 100644 --- a/platforms/jetson/jetson_adaptor.go +++ b/platforms/jetson/jetson_adaptor.go @@ -6,6 +6,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -121,7 +122,7 @@ func (c *Adaptor) PWMPin(pin string) (gobot.PWMPinner, error) { } // PwmWrite writes a PWM signal to the specified pin -func (c *Adaptor) PwmWrite(pin string, val byte) (err error) { +func (c *Adaptor) PwmWrite(pin string, val byte) error { c.mutex.Lock() defer c.mutex.Unlock() @@ -135,7 +136,7 @@ func (c *Adaptor) PwmWrite(pin string, val byte) (err error) { } // ServoWrite writes a servo signal to the specified pin -func (c *Adaptor) ServoWrite(pin string, angle byte) (err error) { +func (c *Adaptor) ServoWrite(pin string, angle byte) error { c.mutex.Lock() defer c.mutex.Unlock() @@ -200,7 +201,7 @@ func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id) } -func (c *Adaptor) translatePwmPin(pin string) (fn string, err error) { +func (c *Adaptor) translatePwmPin(pin string) (string, error) { if fn, ok := pwmPins[pin]; ok { return fn, nil } diff --git a/platforms/jetson/jetson_adaptor_test.go b/platforms/jetson/jetson_adaptor_test.go index dd74c8327..11c9e3338 100644 --- a/platforms/jetson/jetson_adaptor_test.go +++ b/platforms/jetson/jetson_adaptor_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -173,7 +174,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateSpiBusNumber(t *testing.T) { diff --git a/platforms/jetson/pwm_pin.go b/platforms/jetson/pwm_pin.go index 78f1ad407..558e832ef 100644 --- a/platforms/jetson/pwm_pin.go +++ b/platforms/jetson/pwm_pin.go @@ -73,7 +73,7 @@ func (p *PWMPin) SetPolarity(bool) error { } // Period returns the cached PWM period for pin -func (p *PWMPin) Period() (period uint32, err error) { +func (p *PWMPin) Period() (uint32, error) { if p.period == 0 { return p.period, errors.New("Jetson PWM pin period not set") } diff --git a/platforms/joystick/joystick_adaptor.go b/platforms/joystick/joystick_adaptor.go index fba07f6bd..38de67587 100644 --- a/platforms/joystick/joystick_adaptor.go +++ b/platforms/joystick/joystick_adaptor.go @@ -4,9 +4,9 @@ import ( "fmt" "strconv" - "gobot.io/x/gobot/v2" - js "github.com/0xcafed00d/joystick" + + "gobot.io/x/gobot/v2" ) // Adaptor represents a connection to a joystick @@ -25,12 +25,12 @@ func NewAdaptor(id string) *Adaptor { connect: func(j *Adaptor) error { i, err := strconv.Atoi(id) if err != nil { - return fmt.Errorf("Invalid joystick ID: %v", err) + return fmt.Errorf("invalid joystick ID: %v", err) } joy, err := js.Open(i) if err != nil { - return fmt.Errorf("No joystick available: %v", err) + return fmt.Errorf("no joystick available: %v", err) } j.id = id diff --git a/platforms/joystick/joystick_adaptor_test.go b/platforms/joystick/joystick_adaptor_test.go index c638bd201..8ae984dd0 100644 --- a/platforms/joystick/joystick_adaptor_test.go +++ b/platforms/joystick/joystick_adaptor_test.go @@ -14,7 +14,7 @@ var _ gobot.Adaptor = (*Adaptor)(nil) func initTestAdaptor() *Adaptor { a := NewAdaptor("6") - a.connect = func(j *Adaptor) (err error) { + a.connect = func(j *Adaptor) error { j.joystick = &testJoystick{} return nil } @@ -34,7 +34,7 @@ func TestAdaptorConnect(t *testing.T) { a = NewAdaptor("6") err := a.Connect() - assert.True(t, strings.HasPrefix(err.Error(), "No joystick available")) + require.ErrorContains(t, err, "no joystick available") } func TestAdaptorFinalize(t *testing.T) { diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index c313f362d..3af42505e 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -7,6 +7,7 @@ import ( "time" js "github.com/0xcafed00d/joystick" + "gobot.io/x/gobot/v2" ) @@ -106,6 +107,7 @@ func (j *Driver) Connection() gobot.Connection { return j.connection } // adaptor returns joystick adaptor func (j *Driver) adaptor() *Adaptor { + //nolint:forcetypeassert // ok here return j.Connection().(*Adaptor) } @@ -196,9 +198,9 @@ func (j *Driver) initEvents() { } // Halt stops joystick driver -func (j *Driver) Halt() (err error) { +func (j *Driver) Halt() error { j.halt <- true - return + return nil } func (j *Driver) handleButtons(state js.State) error { diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index 87996fc28..48965d3db 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package joystick import ( @@ -5,12 +6,11 @@ import ( "testing" "time" + js "github.com/0xcafed00d/joystick" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" - - js "github.com/0xcafed00d/joystick" ) var _ gobot.Driver = (*Driver)(nil) @@ -18,7 +18,7 @@ var _ gobot.Driver = (*Driver)(nil) func initTestDriver(config string) (*Driver, *testJoystick) { a := NewAdaptor("6") tj := &testJoystick{} - a.connect = func(j *Adaptor) (err error) { + a.connect = func(j *Adaptor) error { j.joystick = tj return nil } @@ -220,5 +220,5 @@ func TestDriverHandleEventDS4(t *testing.T) { func TestDriverInvalidConfig(t *testing.T) { d, _ := initTestDriver("./configs/doesnotexist") err := d.Start() - assert.Contains(t, err.Error(), "loadfile error") + require.ErrorContains(t, err, "loadfile error") } diff --git a/platforms/keyboard/keyboard.go b/platforms/keyboard/keyboard.go index 8ad037d90..3ee0bb311 100644 --- a/platforms/keyboard/keyboard.go +++ b/platforms/keyboard/keyboard.go @@ -148,7 +148,7 @@ func Parse(input bytes) KeyEvent { } // fetches original state, sets up TTY for raw (unbuffered) input -func configure() (err error) { +func configure() error { state, err := stty("-g") if err != nil { return err @@ -158,24 +158,20 @@ func configure() (err error) { // -echo: terminal doesn't echo typed characters back to the terminal // -icanon: terminal doesn't interpret special characters (like backspace) - if _, err := stty("-echo", "-icanon"); err != nil { - return err - } + _, err = stty("-echo", "-icanon") - return + return err } // restores the TTY to the original state -func restore() (err error) { - if _, err = stty("echo"); err != nil { - return +func restore() error { + if _, err := stty("echo"); err != nil { + return err } - if _, err = stty(originalState); err != nil { - return - } + _, err := stty(originalState) - return + return err } func stty(args ...string) (string, error) { diff --git a/platforms/keyboard/keyboard_driver_test.go b/platforms/keyboard/keyboard_driver_test.go index 0d3500ac1..dada390ea 100644 --- a/platforms/keyboard/keyboard_driver_test.go +++ b/platforms/keyboard/keyboard_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -14,7 +15,7 @@ var _ gobot.Driver = (*Driver)(nil) func initTestKeyboardDriver() *Driver { d := NewDriver() - d.connect = func(k *Driver) (err error) { + d.connect = func(k *Driver) error { k.stdin = &os.File{} return nil } diff --git a/platforms/leap/leap_motion_adaptor.go b/platforms/leap/leap_motion_adaptor.go index e78ae8054..78e2fa26f 100644 --- a/platforms/leap/leap_motion_adaptor.go +++ b/platforms/leap/leap_motion_adaptor.go @@ -3,9 +3,9 @@ package leap import ( "io" - "gobot.io/x/gobot/v2" - "golang.org/x/net/websocket" + + "gobot.io/x/gobot/v2" ) // Adaptor is the Gobot Adaptor connection to the Leap Motion @@ -38,15 +38,15 @@ func (l *Adaptor) SetName(n string) { l.name = n } func (l *Adaptor) Port() string { return l.port } // Connect returns true if connection to leap motion is established successfully -func (l *Adaptor) Connect() (err error) { - ws, e := l.connect(l.Port()) - if e != nil { - return e +func (l *Adaptor) Connect() error { + ws, err := l.connect(l.Port()) + if err != nil { + return err } l.ws = ws - return + return nil } // Finalize ends connection to leap motion -func (l *Adaptor) Finalize() (err error) { return } +func (l *Adaptor) Finalize() error { return nil } diff --git a/platforms/leap/leap_motion_adaptor_test.go b/platforms/leap/leap_motion_adaptor_test.go index b16018480..9f2d473d9 100644 --- a/platforms/leap/leap_motion_adaptor_test.go +++ b/platforms/leap/leap_motion_adaptor_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/leap/leap_motion_driver.go b/platforms/leap/leap_motion_driver.go index f420d475f..c7b8effb1 100644 --- a/platforms/leap/leap_motion_driver.go +++ b/platforms/leap/leap_motion_driver.go @@ -5,8 +5,9 @@ import ( "io" "log" - "gobot.io/x/gobot/v2" "golang.org/x/net/websocket" + + "gobot.io/x/gobot/v2" ) const ( @@ -39,6 +40,7 @@ func NewDriver(a *Adaptor) *Driver { connection: a, Eventer: gobot.NewEventer(), receive: func(ws io.ReadWriteCloser, msg *[]byte) { + //nolint:forcetypeassert // ok here if err := websocket.Message.Receive(ws.(*websocket.Conn), msg); err != nil { panic(err) } @@ -62,6 +64,7 @@ func (l *Driver) Connection() gobot.Connection { return l.connection } // adaptor returns leap motion adaptor func (l *Driver) adaptor() *Adaptor { + //nolint:forcetypeassert // ok here return l.Connection().(*Adaptor) } diff --git a/platforms/leap/leap_motion_driver_test.go b/platforms/leap/leap_motion_driver_test.go index 7d6a43f8c..f7ecb0f5b 100644 --- a/platforms/leap/leap_motion_driver_test.go +++ b/platforms/leap/leap_motion_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/mavlink/common/common.go b/platforms/mavlink/common/common.go index 4f8133186..2b3dbca7a 100644 --- a/platforms/mavlink/common/common.go +++ b/platforms/mavlink/common/common.go @@ -1,3 +1,4 @@ +//nolint:dupl,gocritic,lll // seems to be useful here package mavlink // diff --git a/platforms/mavlink/common/mavlink.go b/platforms/mavlink/common/mavlink.go index 2d794e8c3..ae99c4dbd 100644 --- a/platforms/mavlink/common/mavlink.go +++ b/platforms/mavlink/common/mavlink.go @@ -80,28 +80,36 @@ func ReadMAVLinkPacket(r io.Reader) (*MAVLinkPacket, error) { } // CraftMAVLinkPacket returns a new MAVLinkPacket from a MAVLinkMessage -func CraftMAVLinkPacket(SystemID uint8, ComponentID uint8, Message MAVLinkMessage) *MAVLinkPacket { +func CraftMAVLinkPacket(systemID uint8, cComponentID uint8, mMessage MAVLinkMessage) *MAVLinkPacket { return NewMAVLinkPacket( 0xFE, - Message.Len(), + mMessage.Len(), generateSequence(), - SystemID, - ComponentID, - Message.Id(), - Message.Pack(), + systemID, + cComponentID, + mMessage.Id(), + mMessage.Pack(), ) } // NewMAVLinkPacket returns a new MAVLinkPacket -func NewMAVLinkPacket(Protocol uint8, Length uint8, Sequence uint8, SystemID uint8, ComponentID uint8, MessageID uint8, Data []uint8) *MAVLinkPacket { +func NewMAVLinkPacket( + pProtocol uint8, + lLength uint8, + sSequence uint8, + sSystemID uint8, + cComponentID uint8, + mMessageID uint8, + dData []uint8, +) *MAVLinkPacket { m := &MAVLinkPacket{ - Protocol: Protocol, - Length: Length, - Sequence: Sequence, - SystemID: SystemID, - ComponentID: ComponentID, - MessageID: MessageID, - Data: Data, + Protocol: pProtocol, + Length: lLength, + Sequence: sSequence, + SystemID: sSystemID, + ComponentID: cComponentID, + MessageID: mMessageID, + Data: dData, } m.Checksum = crcCalculate(m) return m @@ -158,7 +166,7 @@ func read(r io.Reader, length int) ([]byte, error) { buf := []byte{} for length > 0 { tmp := make([]byte, length) - i, err := r.Read(tmp[:]) + i, err := r.Read(tmp) if err != nil { return nil, err } diff --git a/platforms/mavlink/mavlink_adaptor.go b/platforms/mavlink/mavlink_adaptor.go index ee0ae4116..4a1792677 100644 --- a/platforms/mavlink/mavlink_adaptor.go +++ b/platforms/mavlink/mavlink_adaptor.go @@ -4,6 +4,7 @@ import ( "io" "go.bug.st/serial" + "gobot.io/x/gobot/v2" common "gobot.io/x/gobot/v2/platforms/mavlink/common" ) @@ -40,19 +41,19 @@ func (m *Adaptor) SetName(n string) { m.name = n } func (m *Adaptor) Port() string { return m.port } // Connect returns true if connection to device is successful -func (m *Adaptor) Connect() (err error) { - if sp, e := m.connect(m.Port()); e != nil { - return e - } else { - m.sp = sp +func (m *Adaptor) Connect() error { + sp, err := m.connect(m.Port()) + if err != nil { + return err } - return + m.sp = sp + + return nil } // Finalize returns true if connection to devices is closed successfully -func (m *Adaptor) Finalize() (err error) { - err = m.sp.Close() - return +func (m *Adaptor) Finalize() error { + return m.sp.Close() } func (m *Adaptor) ReadMAVLinkPacket() (*common.MAVLinkPacket, error) { diff --git a/platforms/mavlink/mavlink_adaptor_test.go b/platforms/mavlink/mavlink_adaptor_test.go index 2c71068e0..da18a6c93 100644 --- a/platforms/mavlink/mavlink_adaptor_test.go +++ b/platforms/mavlink/mavlink_adaptor_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -15,7 +16,9 @@ var _ gobot.Adaptor = (*Adaptor)(nil) type nullReadWriteCloser struct{} -var payload = []byte{0xFE, 0x09, 0x4E, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x51, 0x04, 0x03, 0x1C, 0x7F} +var payload = []byte{ + 0xFE, 0x09, 0x4E, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x51, 0x04, 0x03, 0x1C, 0x7F, +} var testAdaptorRead = func(p []byte) (int, error) { return len(p), nil diff --git a/platforms/mavlink/mavlink_driver.go b/platforms/mavlink/mavlink_driver.go index d4330633d..7a361615d 100644 --- a/platforms/mavlink/mavlink_driver.go +++ b/platforms/mavlink/mavlink_driver.go @@ -59,6 +59,7 @@ func (m *Driver) SetName(n string) { m.name = n } // adaptor returns driver associated adaptor func (m *Driver) adaptor() BaseAdaptor { + //nolint:forcetypeassert // ok here return m.Connection().(BaseAdaptor) } @@ -86,10 +87,10 @@ func (m *Driver) Start() error { } // Halt returns true if device is halted successfully -func (m *Driver) Halt() (err error) { return } +func (m *Driver) Halt() error { return nil } // SendPacket sends a packet to mavlink device -func (m *Driver) SendPacket(packet *common.MAVLinkPacket) (err error) { - _, err = m.adaptor().Write(packet.Pack()) +func (m *Driver) SendPacket(packet *common.MAVLinkPacket) error { + _, err := m.adaptor().Write(packet.Pack()) return err } diff --git a/platforms/mavlink/mavlink_driver_test.go b/platforms/mavlink/mavlink_driver_test.go index a357181d4..abc0a675e 100644 --- a/platforms/mavlink/mavlink_driver_test.go +++ b/platforms/mavlink/mavlink_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package mavlink import ( @@ -8,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" common "gobot.io/x/gobot/v2/platforms/mavlink/common" ) diff --git a/platforms/mavlink/mavlink_udp_adaptor.go b/platforms/mavlink/mavlink_udp_adaptor.go index f4cb22e50..47d7a169a 100644 --- a/platforms/mavlink/mavlink_udp_adaptor.go +++ b/platforms/mavlink/mavlink_udp_adaptor.go @@ -61,7 +61,7 @@ func (m *UDPAdaptor) close() error { } // Finalize returns true if connection to devices is closed successfully -func (m *UDPAdaptor) Finalize() (err error) { +func (m *UDPAdaptor) Finalize() error { return m.close() } diff --git a/platforms/mavlink/mavlink_udp_adaptor_test.go b/platforms/mavlink/mavlink_udp_adaptor_test.go index 513eca2db..c5bf6e515 100644 --- a/platforms/mavlink/mavlink_udp_adaptor_test.go +++ b/platforms/mavlink/mavlink_udp_adaptor_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" mavlink "gobot.io/x/gobot/v2/platforms/mavlink/common" ) diff --git a/platforms/megapi/megapi_adaptor.go b/platforms/megapi/megapi_adaptor.go index bdbf61063..fb8767e44 100644 --- a/platforms/megapi/megapi_adaptor.go +++ b/platforms/megapi/megapi_adaptor.go @@ -5,6 +5,7 @@ import ( "time" "go.bug.st/serial" + "gobot.io/x/gobot/v2" ) @@ -20,7 +21,7 @@ type Adaptor struct { finalizeChannel chan struct{} } -// NewAdaptor returns a new MegaPi Adaptor with specified serial port used to talk to the MegaPi with a baud rate of 115200 +// NewAdaptor returns a new Adaptor with specified serial port used to talk to the MegaPi with a baud rate of 115200 func NewAdaptor(device string) *Adaptor { c := &serial.Mode{BaudRate: 115200} return &Adaptor{ diff --git a/platforms/megapi/motor_driver.go b/platforms/megapi/motor_driver.go index 1efce6f9a..ff6709cdf 100644 --- a/platforms/megapi/motor_driver.go +++ b/platforms/megapi/motor_driver.go @@ -31,67 +31,67 @@ func NewMotorDriver(megaPi *Adaptor, port byte) *MotorDriver { } // Name returns the name of this motor -func (m *MotorDriver) Name() string { - return m.name +func (d *MotorDriver) Name() string { + return d.name } // SetName sets the name of this motor -func (m *MotorDriver) SetName(n string) { - m.name = n +func (d *MotorDriver) SetName(n string) { + d.name = n } // Start implements the Driver interface -func (m *MotorDriver) Start() error { - m.syncRoot.Lock() - defer m.syncRoot.Unlock() - m.halted = false - return m.speedHelper(0) +func (d *MotorDriver) Start() error { + d.syncRoot.Lock() + defer d.syncRoot.Unlock() + d.halted = false + return d.speedHelper(0) } // Halt terminates the Driver interface -func (m *MotorDriver) Halt() error { - m.syncRoot.Lock() - defer m.syncRoot.Unlock() - m.halted = true - return m.speedHelper(0) +func (d *MotorDriver) Halt() error { + d.syncRoot.Lock() + defer d.syncRoot.Unlock() + d.halted = true + return d.speedHelper(0) } // Connection returns the Connection associated with the Driver -func (m *MotorDriver) Connection() gobot.Connection { - return gobot.Connection(m.megaPi) +func (d *MotorDriver) Connection() gobot.Connection { + return gobot.Connection(d.megaPi) } // Speed sets the motors speed to the specified value -func (m *MotorDriver) Speed(speed int16) error { - m.syncRoot.Lock() - defer m.syncRoot.Unlock() - if m.halted { +func (d *MotorDriver) Speed(speed int16) error { + d.syncRoot.Lock() + defer d.syncRoot.Unlock() + if d.halted { return nil } - return m.speedHelper(speed) + return d.speedHelper(speed) } // there is some sort of bug on the hardware such that you cannot // send the exact same speed to 2 different motors consecutively // hence we ensure we always alternate speeds -func (m *MotorDriver) speedHelper(speed int16) error { - if err := m.sendSpeed(speed - 1); err != nil { +func (d *MotorDriver) speedHelper(speed int16) error { + if err := d.sendSpeed(speed - 1); err != nil { return err } - return m.sendSpeed(speed) + return d.sendSpeed(speed) } // sendSpeed sets the motors speed to the specified value -func (m *MotorDriver) sendSpeed(speed int16) error { +func (d *MotorDriver) sendSpeed(speed int16) error { bufOut := new(bytes.Buffer) // byte sequence: 0xff, 0x55, id, action, device, port - bufOut.Write([]byte{0xff, 0x55, 0x6, 0x0, 0x2, 0xa, m.port}) + bufOut.Write([]byte{0xff, 0x55, 0x6, 0x0, 0x2, 0xa, d.port}) if err := binary.Write(bufOut, binary.LittleEndian, speed); err != nil { return err } bufOut.Write([]byte{0xa}) - m.megaPi.writeBytesChannel <- bufOut.Bytes() + d.megaPi.writeBytesChannel <- bufOut.Bytes() return nil } diff --git a/platforms/microbit/accelerometer_driver.go b/platforms/microbit/accelerometer_driver.go index 97b26ad89..76dda8fc3 100644 --- a/platforms/microbit/accelerometer_driver.go +++ b/platforms/microbit/accelerometer_driver.go @@ -62,6 +62,7 @@ func (b *AccelerometerDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *AccelerometerDriver) adaptor() ble.BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(ble.BLEConnector) } diff --git a/platforms/microbit/accelerometer_driver_test.go b/platforms/microbit/accelerometer_driver_test.go index 312edc23d..33ea547a5 100644 --- a/platforms/microbit/accelerometer_driver_test.go +++ b/platforms/microbit/accelerometer_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert,dupl // ok here package microbit import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/microbit/button_driver.go b/platforms/microbit/button_driver.go index 3fc779329..35a17bbfb 100644 --- a/platforms/microbit/button_driver.go +++ b/platforms/microbit/button_driver.go @@ -52,6 +52,7 @@ func (b *ButtonDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *ButtonDriver) adaptor() ble.BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(ble.BLEConnector) } diff --git a/platforms/microbit/button_driver_test.go b/platforms/microbit/button_driver_test.go index 6af815e8d..be92c0ed7 100644 --- a/platforms/microbit/button_driver_test.go +++ b/platforms/microbit/button_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/microbit/helpers_test.go b/platforms/microbit/helpers_test.go index 8c94a9615..acf446f2d 100644 --- a/platforms/microbit/helpers_test.go +++ b/platforms/microbit/helpers_test.go @@ -19,30 +19,30 @@ type bleTestClientAdaptor struct { testWriteCharacteristic func(string, []byte) error } -func (t *bleTestClientAdaptor) Connect() (err error) { return } -func (t *bleTestClientAdaptor) Reconnect() (err error) { return } -func (t *bleTestClientAdaptor) Disconnect() (err error) { return } -func (t *bleTestClientAdaptor) Finalize() (err error) { return } +func (t *bleTestClientAdaptor) Connect() error { return nil } +func (t *bleTestClientAdaptor) Reconnect() error { return nil } +func (t *bleTestClientAdaptor) Disconnect() error { return nil } +func (t *bleTestClientAdaptor) Finalize() error { return nil } func (t *bleTestClientAdaptor) Name() string { return t.name } func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } func (t *bleTestClientAdaptor) Address() string { return t.address } func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) (data []byte, err error) { +func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testReadCharacteristic(cUUID) } -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) (err error) { +func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.testWriteCharacteristic(cUUID, data) } -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) (err error) { +func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { t.testSubscribe = f - return + return nil } func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { @@ -51,7 +51,7 @@ func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data t.testReadCharacteristic = f } -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) (err error)) { +func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { t.mtx.Lock() defer t.mtx.Unlock() t.testWriteCharacteristic = f @@ -66,11 +66,11 @@ func (t *bleTestClientAdaptor) TestReceiveNotification(data []byte, err error) { func NewBleTestAdaptor() *bleTestClientAdaptor { return &bleTestClientAdaptor{ address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) (data []byte, e error) { - return + testReadCharacteristic: func(cUUID string) ([]byte, error) { + return nil, nil }, - testWriteCharacteristic: func(cUUID string, data []byte) (e error) { - return + testWriteCharacteristic: func(cUUID string, data []byte) error { + return nil }, testSubscribe: func([]byte, error) {}, } diff --git a/platforms/microbit/io_pin_driver.go b/platforms/microbit/io_pin_driver.go index e9e4e51d6..b57a11027 100644 --- a/platforms/microbit/io_pin_driver.go +++ b/platforms/microbit/io_pin_driver.go @@ -58,6 +58,7 @@ func (b *IOPinDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *IOPinDriver) adaptor() ble.BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(ble.BLEConnector) } @@ -74,7 +75,7 @@ func (b *IOPinDriver) Start() error { func (b *IOPinDriver) Halt() error { return nil } // ReadAllPinData reads and returns the pin data for all pins -func (b *IOPinDriver) ReadAllPinData() (pins []PinData) { +func (b *IOPinDriver) ReadAllPinData() []PinData { c, _ := b.adaptor().ReadCharacteristic(pinDataCharacteristic) buf := bytes.NewBuffer(c) pinsData := make([]PinData, buf.Len()/2) diff --git a/platforms/microbit/io_pin_driver_test.go b/platforms/microbit/io_pin_driver_test.go index 21794606d..db8b3e158 100644 --- a/platforms/microbit/io_pin_driver_test.go +++ b/platforms/microbit/io_pin_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" diff --git a/platforms/microbit/led_driver.go b/platforms/microbit/led_driver.go index 80aca8cd8..83a42afe4 100644 --- a/platforms/microbit/led_driver.go +++ b/platforms/microbit/led_driver.go @@ -44,106 +44,90 @@ func (b *LEDDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *LEDDriver) adaptor() ble.BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(ble.BLEConnector) } // Start tells driver to get ready to do work -func (b *LEDDriver) Start() (err error) { - return -} +func (b *LEDDriver) Start() error { return nil } // Halt stops LED driver (void) -func (b *LEDDriver) Halt() (err error) { - return -} +func (b *LEDDriver) Halt() error { return nil } // ReadMatrix read the current LED matrix state -func (b *LEDDriver) ReadMatrix() (data []byte, err error) { - data, err = b.adaptor().ReadCharacteristic(ledMatrixStateCharacteristic) - return +func (b *LEDDriver) ReadMatrix() ([]byte, error) { + return b.adaptor().ReadCharacteristic(ledMatrixStateCharacteristic) } // WriteMatrix writes an array of 5 bytes to set the LED matrix -func (b *LEDDriver) WriteMatrix(data []byte) (err error) { - err = b.adaptor().WriteCharacteristic(ledMatrixStateCharacteristic, data) - return +func (b *LEDDriver) WriteMatrix(data []byte) error { + return b.adaptor().WriteCharacteristic(ledMatrixStateCharacteristic, data) } // WriteText writes a text message to the Microbit LED matrix -func (b *LEDDriver) WriteText(msg string) (err error) { - err = b.adaptor().WriteCharacteristic(ledTextCharacteristic, []byte(msg)) - return err +func (b *LEDDriver) WriteText(msg string) error { + return b.adaptor().WriteCharacteristic(ledTextCharacteristic, []byte(msg)) } -func (b *LEDDriver) ReadScrollingDelay() (delay uint16, err error) { - return +func (b *LEDDriver) ReadScrollingDelay() (uint16, error) { + return 0, nil } -func (b *LEDDriver) WriteScrollingDelay(delay uint16) (err error) { +func (b *LEDDriver) WriteScrollingDelay(delay uint16) error { buf := []byte{byte(delay)} - err = b.adaptor().WriteCharacteristic(ledScrollingDelayCharacteristic, buf) - return + return b.adaptor().WriteCharacteristic(ledScrollingDelayCharacteristic, buf) } // Blank clears the LEDs on the Microbit -func (b *LEDDriver) Blank() (err error) { +func (b *LEDDriver) Blank() error { buf := []byte{0x00, 0x00, 0x00, 0x00, 0x00} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } // Solid turns on all of the Microbit LEDs -func (b *LEDDriver) Solid() (err error) { +func (b *LEDDriver) Solid() error { buf := []byte{0x1F, 0x1F, 0x1F, 0x1F, 0x1F} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } // UpRightArrow displays an arrow pointing upwards and to the right on the Microbit LEDs -func (b *LEDDriver) UpRightArrow() (err error) { +func (b *LEDDriver) UpRightArrow() error { buf := []byte{0x0F, 0x03, 0x05, 0x09, 0x10} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } // UpLeftArrow displays an arrow pointing upwards and to the left on the Microbit LEDs -func (b *LEDDriver) UpLeftArrow() (err error) { +func (b *LEDDriver) UpLeftArrow() error { buf := []byte{0x1E, 0x18, 0x14, 0x12, 0x01} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } // DownRightArrow displays an arrow pointing down and to the right on the Microbit LEDs -func (b *LEDDriver) DownRightArrow() (err error) { +func (b *LEDDriver) DownRightArrow() error { buf := []byte{0x10, 0x09, 0x05, 0x03, 0x0F} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } // DownLeftArrow displays an arrow pointing down and to the left on the Microbit LEDs -func (b *LEDDriver) DownLeftArrow() (err error) { +func (b *LEDDriver) DownLeftArrow() error { buf := []byte{0x01, 0x12, 0x14, 0x18, 0x1E} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } // Dimond displays a dimond on the Microbit LEDs -func (b *LEDDriver) Dimond() (err error) { +func (b *LEDDriver) Dimond() error { buf := []byte{0x04, 0x0A, 0x11, 0x0A, 0x04} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } // Smile displays a smile on the Microbit LEDs -func (b *LEDDriver) Smile() (err error) { +func (b *LEDDriver) Smile() error { buf := []byte{0x0A, 0x0A, 0x00, 0x11, 0x0E} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } // Wink displays a wink on the Microbit LEDs -func (b *LEDDriver) Wink() (err error) { +func (b *LEDDriver) Wink() error { buf := []byte{0x08, 0x0B, 0x00, 0x11, 0x0E} - err = b.WriteMatrix(buf) - return + return b.WriteMatrix(buf) } diff --git a/platforms/microbit/led_driver_test.go b/platforms/microbit/led_driver_test.go index 5be9376a7..a59039dfb 100644 --- a/platforms/microbit/led_driver_test.go +++ b/platforms/microbit/led_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/microbit/magnetometer_driver.go b/platforms/microbit/magnetometer_driver.go index c398eddc8..fa89d7403 100644 --- a/platforms/microbit/magnetometer_driver.go +++ b/platforms/microbit/magnetometer_driver.go @@ -62,6 +62,7 @@ func (b *MagnetometerDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *MagnetometerDriver) adaptor() ble.BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(ble.BLEConnector) } diff --git a/platforms/microbit/magnetometer_driver_test.go b/platforms/microbit/magnetometer_driver_test.go index 53a48f5f1..5a7d31f1f 100644 --- a/platforms/microbit/magnetometer_driver_test.go +++ b/platforms/microbit/magnetometer_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert,dupl // ok here package microbit import ( @@ -7,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/microbit/temperature_driver.go b/platforms/microbit/temperature_driver.go index 7daf96077..e8eaab283 100644 --- a/platforms/microbit/temperature_driver.go +++ b/platforms/microbit/temperature_driver.go @@ -49,6 +49,7 @@ func (b *TemperatureDriver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *TemperatureDriver) adaptor() ble.BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(ble.BLEConnector) } diff --git a/platforms/microbit/temperature_driver_test.go b/platforms/microbit/temperature_driver_test.go index a24c0f2cb..3d4a81db9 100644 --- a/platforms/microbit/temperature_driver_test.go +++ b/platforms/microbit/temperature_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/mqtt/mqtt_adaptor.go b/platforms/mqtt/mqtt_adaptor.go index 24b412445..3e93efe46 100644 --- a/platforms/mqtt/mqtt_adaptor.go +++ b/platforms/mqtt/mqtt_adaptor.go @@ -6,9 +6,9 @@ import ( "fmt" "os" - "gobot.io/x/gobot/v2" - paho "github.com/eclipse/paho.mqtt.golang" + + "gobot.io/x/gobot/v2" ) // ErrNilClient is returned when a client action can't be taken because the struct has no client @@ -78,7 +78,8 @@ func (a *Adaptor) SetAutoReconnect(val bool) { a.autoReconnect = val } // CleanSession returns the MQTT CleanSession setting func (a *Adaptor) CleanSession() bool { return a.cleanSession } -// SetCleanSession sets the MQTT CleanSession setting. Should be false if reconnect is enabled. Otherwise all subscriptions will be lost +// SetCleanSession sets the MQTT CleanSession setting. Should be false if reconnect is enabled. +// Otherwise all subscriptions will be lost func (a *Adaptor) SetCleanSession(val bool) { a.cleanSession = val } // UseSSL returns the MQTT server SSL preference diff --git a/platforms/mqtt/mqtt_adaptor_test.go b/platforms/mqtt/mqtt_adaptor_test.go index 9a60e4470..04e93bdd2 100644 --- a/platforms/mqtt/mqtt_adaptor_test.go +++ b/platforms/mqtt/mqtt_adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -74,14 +75,14 @@ func TestMqttAdaptorConnectError(t *testing.T) { a := NewAdaptor("tcp://localhost:1884", "client") err := a.Connect() - assert.Contains(t, err.Error(), "connection refused") + require.ErrorContains(t, err, "connection refused") } func TestMqttAdaptorConnectSSLError(t *testing.T) { a := NewAdaptor("tcp://localhost:1884", "client") a.SetUseSSL(true) err := a.Connect() - assert.Contains(t, err.Error(), "connection refused") + require.ErrorContains(t, err, "connection refused") } func TestMqttAdaptorConnectWithAuthError(t *testing.T) { diff --git a/platforms/mqtt/mqtt_driver.go b/platforms/mqtt/mqtt_driver.go index 68335f951..6747096b3 100644 --- a/platforms/mqtt/mqtt_driver.go +++ b/platforms/mqtt/mqtt_driver.go @@ -47,6 +47,7 @@ func (m *Driver) Connection() gobot.Connection { } func (m *Driver) adaptor() *Adaptor { + //nolint:forcetypeassert // ok here return m.Connection().(*Adaptor) } @@ -68,6 +69,7 @@ func (m *Driver) SetTopic(topic string) { m.topic = topic } // Publish a message to the current device topic func (m *Driver) Publish(data interface{}) bool { + //nolint:forcetypeassert // ok here message := data.([]byte) return m.adaptor().Publish(m.topic, message) } diff --git a/platforms/mqtt/mqtt_driver_test.go b/platforms/mqtt/mqtt_driver_test.go index 8ee028ea5..99aaa5ad6 100644 --- a/platforms/mqtt/mqtt_driver_test.go +++ b/platforms/mqtt/mqtt_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/nanopi/nanopi_adaptor.go b/platforms/nanopi/nanopi_adaptor.go index 46b67c85d..ff298762f 100644 --- a/platforms/nanopi/nanopi_adaptor.go +++ b/platforms/nanopi/nanopi_adaptor.go @@ -5,6 +5,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -167,14 +168,14 @@ func (c *Adaptor) translatePWMPin(id string) (string, int, error) { return path, pinInfo.channel, nil } -func (p pwmPinDefinition) findPWMDir(sys *system.Accesser) (dir string, err error) { +func (p pwmPinDefinition) findPWMDir(sys *system.Accesser) (string, error) { items, _ := sys.Find(p.dir, p.dirRegexp) if len(items) == 0 { return "", fmt.Errorf("No path found for PWM directory pattern, '%s' in path '%s'. See README.md for activation", p.dirRegexp, p.dir) } - dir = items[0] + dir := items[0] info, err := sys.Stat(dir) if err != nil { return "", fmt.Errorf("Error (%v) on access '%s'", err, dir) @@ -183,5 +184,5 @@ func (p pwmPinDefinition) findPWMDir(sys *system.Accesser) (dir string, err erro return "", fmt.Errorf("The item '%s' is not a directory, which is not expected", dir) } - return + return dir, nil } diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index 46a36bf08..bfae8fdd0 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -188,7 +189,7 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestFinalizeErrorAfterPWM(t *testing.T) { @@ -200,7 +201,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestSpiDefaultValues(t *testing.T) { @@ -232,7 +233,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateSpiBusNumber(t *testing.T) { diff --git a/platforms/nats/nats_adaptor.go b/platforms/nats/nats_adaptor.go index 122cdad9e..1fea0f359 100644 --- a/platforms/nats/nats_adaptor.go +++ b/platforms/nats/nats_adaptor.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/nats-io/nats.go" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/nats/nats_adaptor_test.go b/platforms/nats/nats_adaptor_test.go index 92023cdf0..a2c4bb0c5 100644 --- a/platforms/nats/nats_adaptor_test.go +++ b/platforms/nats/nats_adaptor_test.go @@ -9,6 +9,7 @@ import ( "github.com/nats-io/nats.go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -92,7 +93,8 @@ func TestNatsAdapterSetsClientCerts(t *testing.T) { } func TestNatsAdapterSetsClientCertsWithUserInfo(t *testing.T) { - a := initTestNatsAdaptorTLS(nats.ClientCert("test_certs/client-cert.pem", "test_certs/client-key.pem"), nats.UserInfo("test", "testwd")) + a := initTestNatsAdaptorTLS(nats.ClientCert("test_certs/client-cert.pem", "test_certs/client-key.pem"), + nats.UserInfo("test", "testwd")) assert.Equal(t, "tls://localhost:4242", a.Host) _ = a.Connect() cert, err := a.client.Opts.TLSCertCB() diff --git a/platforms/nats/nats_driver.go b/platforms/nats/nats_driver.go index 36fab63a1..e4aa7bfd7 100644 --- a/platforms/nats/nats_driver.go +++ b/platforms/nats/nats_driver.go @@ -44,6 +44,7 @@ func (m *Driver) Connection() gobot.Connection { } func (m *Driver) adaptor() *Adaptor { + //nolint:forcetypeassert // ok here return m.Connection().(*Adaptor) } @@ -65,6 +66,7 @@ func (m *Driver) SetTopic(topic string) { m.topic = topic } // Publish a message to the current device topic func (m *Driver) Publish(data interface{}) bool { + //nolint:forcetypeassert // ok here message := data.([]byte) return m.adaptor().Publish(m.topic, message) } diff --git a/platforms/nats/nats_driver_test.go b/platforms/nats/nats_driver_test.go index d35b1d9e4..8b70aeaca 100644 --- a/platforms/nats/nats_driver_test.go +++ b/platforms/nats/nats_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/neurosky/neurosky_adaptor.go b/platforms/neurosky/neurosky_adaptor.go index 874362da9..a0bac066f 100644 --- a/platforms/neurosky/neurosky_adaptor.go +++ b/platforms/neurosky/neurosky_adaptor.go @@ -47,7 +47,6 @@ func (n *Adaptor) Connect() error { } // Finalize returns true if device finalization is successful -func (n *Adaptor) Finalize() (err error) { - err = n.sp.Close() - return +func (n *Adaptor) Finalize() error { + return n.sp.Close() } diff --git a/platforms/neurosky/neurosky_adaptor_test.go b/platforms/neurosky/neurosky_adaptor_test.go index 6f36be7fb..e80ca31e5 100644 --- a/platforms/neurosky/neurosky_adaptor_test.go +++ b/platforms/neurosky/neurosky_adaptor_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/neurosky/neurosky_driver.go b/platforms/neurosky/neurosky_driver.go index 1ebe5198f..893f28bdb 100644 --- a/platforms/neurosky/neurosky_driver.go +++ b/platforms/neurosky/neurosky_driver.go @@ -115,6 +115,7 @@ func (n *Driver) SetName(name string) { n.name = name } // adaptor returns neurosky adaptor func (n *Driver) adaptor() *Adaptor { + //nolint:forcetypeassert // ok here return n.Connection().(*Adaptor) } @@ -124,7 +125,7 @@ func (n *Driver) Start() error { go func() { for { buff := make([]byte, 1024) - _, err := n.adaptor().sp.Read(buff[:]) + _, err := n.adaptor().sp.Read(buff) if err != nil { n.Publish(n.Event("error"), err) } else { diff --git a/platforms/neurosky/neurosky_driver_test.go b/platforms/neurosky/neurosky_driver_test.go index a3c86b048..00dd62a78 100644 --- a/platforms/neurosky/neurosky_driver_test.go +++ b/platforms/neurosky/neurosky_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package neurosky import ( @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/opencv/camera_driver.go b/platforms/opencv/camera_driver.go index e83aa5f8c..9a4e8136c 100644 --- a/platforms/opencv/camera_driver.go +++ b/platforms/opencv/camera_driver.go @@ -21,7 +21,7 @@ type CameraDriver struct { name string camera capture Source interface{} - start func(*CameraDriver) (err error) + start func(*CameraDriver) error gobot.Eventer } @@ -32,7 +32,7 @@ func NewCameraDriver(source interface{}) *CameraDriver { name: "Camera", Eventer: gobot.NewEventer(), Source: source, - start: func(c *CameraDriver) (err error) { + start: func(c *CameraDriver) error { switch v := c.Source.(type) { case string: c.camera, _ = gocv.VideoCaptureFile(v) @@ -60,7 +60,7 @@ func (c *CameraDriver) SetName(n string) { c.name = n } func (c *CameraDriver) Connection() gobot.Connection { return nil } // Start initializes camera by grabbing frames -func (c *CameraDriver) Start() (err error) { +func (c *CameraDriver) Start() error { if err := c.start(c); err != nil { return err } @@ -76,4 +76,4 @@ func (c *CameraDriver) Start() (err error) { } // Halt stops camera driver -func (c *CameraDriver) Halt() (err error) { return } +func (c *CameraDriver) Halt() error { return nil } diff --git a/platforms/opencv/camera_driver_test.go b/platforms/opencv/camera_driver_test.go index 5b4adda1a..9a475bcc9 100644 --- a/platforms/opencv/camera_driver_test.go +++ b/platforms/opencv/camera_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -14,7 +15,7 @@ var _ gobot.Driver = (*CameraDriver)(nil) func initTestCameraDriver() *CameraDriver { d := NewCameraDriver("") - d.start = func(c *CameraDriver) (err error) { + d.start = func(c *CameraDriver) error { d.camera = &testCapture{} return nil } diff --git a/platforms/opencv/utils_test.go b/platforms/opencv/utils_test.go index 924dd53d7..775f2df60 100644 --- a/platforms/opencv/utils_test.go +++ b/platforms/opencv/utils_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gocv.io/x/gocv" ) diff --git a/platforms/opencv/window_driver.go b/platforms/opencv/window_driver.go index 7d6eb2fc5..a1130e521 100644 --- a/platforms/opencv/window_driver.go +++ b/platforms/opencv/window_driver.go @@ -37,13 +37,13 @@ func (w *WindowDriver) SetName(n string) { w.name = n } func (w *WindowDriver) Connection() gobot.Connection { return nil } // Start starts window thread and driver -func (w *WindowDriver) Start() (err error) { +func (w *WindowDriver) Start() error { w.start(w) return } // Halt returns true if camera is halted successfully -func (w *WindowDriver) Halt() (err error) { return } +func (w *WindowDriver) Halt() error { return } // ShowImage displays image in window func (w *WindowDriver) ShowImage(img gocv.Mat) { diff --git a/platforms/opencv/window_driver_test.go b/platforms/opencv/window_driver_test.go index ae7ba808e..36bebcf90 100644 --- a/platforms/opencv/window_driver_test.go +++ b/platforms/opencv/window_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gocv.io/x/gocv" ) diff --git a/platforms/parrot/ardrone/ardrone_adaptor.go b/platforms/parrot/ardrone/ardrone_adaptor.go index 336de7ff4..a1b727b1b 100644 --- a/platforms/parrot/ardrone/ardrone_adaptor.go +++ b/platforms/parrot/ardrone/ardrone_adaptor.go @@ -2,6 +2,7 @@ package ardrone import ( client "github.com/hybridgroup/go-ardrone/client" + "gobot.io/x/gobot/v2" ) @@ -54,14 +55,14 @@ func (a *Adaptor) Name() string { return a.name } func (a *Adaptor) SetName(n string) { a.name = n } // Connect establishes a connection to the ardrone -func (a *Adaptor) Connect() (err error) { +func (a *Adaptor) Connect() error { d, err := a.connect(a) if err != nil { return err } a.drone = d - return + return nil } // Finalize terminates the connection to the ardrone -func (a *Adaptor) Finalize() (err error) { return } +func (a *Adaptor) Finalize() error { return nil } diff --git a/platforms/parrot/ardrone/ardrone_adaptor_test.go b/platforms/parrot/ardrone/ardrone_adaptor_test.go index c8eb5c59c..aa67acb08 100644 --- a/platforms/parrot/ardrone/ardrone_adaptor_test.go +++ b/platforms/parrot/ardrone/ardrone_adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/parrot/ardrone/ardrone_driver.go b/platforms/parrot/ardrone/ardrone_driver.go index f5e279337..df7c1a5bb 100644 --- a/platforms/parrot/ardrone/ardrone_driver.go +++ b/platforms/parrot/ardrone/ardrone_driver.go @@ -42,17 +42,18 @@ func (a *Driver) Connection() gobot.Connection { return a.connection } // adaptor returns ardrone adaptor func (a *Driver) adaptor() *Adaptor { + //nolint:forcetypeassert // ok here return a.Connection().(*Adaptor) } // Start starts the Driver -func (a *Driver) Start() (err error) { - return +func (a *Driver) Start() error { + return nil } // Halt halts the Driver -func (a *Driver) Halt() (err error) { - return +func (a *Driver) Halt() error { + return nil } // TakeOff makes the drone start flying, and publishes `flying` event diff --git a/platforms/parrot/ardrone/ardrone_driver_test.go b/platforms/parrot/ardrone/ardrone_driver_test.go index 9664cd71f..2cdaf57e8 100644 --- a/platforms/parrot/ardrone/ardrone_driver_test.go +++ b/platforms/parrot/ardrone/ardrone_driver_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/parrot/bebop/bebop_adaptor_test.go b/platforms/parrot/bebop/bebop_adaptor_test.go index c5c2dd039..966341709 100644 --- a/platforms/parrot/bebop/bebop_adaptor_test.go +++ b/platforms/parrot/bebop/bebop_adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -14,7 +15,7 @@ var _ gobot.Adaptor = (*Adaptor)(nil) func initTestBebopAdaptor() *Adaptor { a := NewAdaptor() - a.connect = func(b *Adaptor) (err error) { + a.connect = func(b *Adaptor) error { b.drone = &testDrone{} return nil } diff --git a/platforms/parrot/bebop/bebop_driver.go b/platforms/parrot/bebop/bebop_driver.go index b0d1c0f4f..8abed2ef4 100644 --- a/platforms/parrot/bebop/bebop_driver.go +++ b/platforms/parrot/bebop/bebop_driver.go @@ -38,17 +38,18 @@ func (a *Driver) Connection() gobot.Connection { return a.connection } // adaptor returns ardrone adaptor func (a *Driver) adaptor() *Adaptor { + //nolint:forcetypeassert // ok here return a.Connection().(*Adaptor) } // Start starts the Bebop Driver -func (a *Driver) Start() (err error) { - return +func (a *Driver) Start() error { + return nil } // Halt halts the Bebop Driver -func (a *Driver) Halt() (err error) { - return +func (a *Driver) Halt() error { + return nil } // TakeOff makes the drone start flying @@ -131,7 +132,8 @@ func (a *Driver) StopRecording() error { return a.adaptor().drone.StopRecording() } -// HullProtection tells the drone if the hull/prop protectors are attached. This is needed to adjust flight characteristics of the Bebop. +// HullProtection tells the drone if the hull/prop protectors are attached. This is needed to adjust +// flight characteristics of the Bebop. func (a *Driver) HullProtection(protect bool) error { return a.adaptor().drone.HullProtection(protect) } diff --git a/platforms/parrot/bebop/bebop_driver_test.go b/platforms/parrot/bebop/bebop_driver_test.go index 6685eb650..8e98891f8 100644 --- a/platforms/parrot/bebop/bebop_driver_test.go +++ b/platforms/parrot/bebop/bebop_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/parrot/bebop/client/client.go b/platforms/parrot/bebop/client/client.go index 9d54c183b..08451c1b4 100644 --- a/platforms/parrot/bebop/client/client.go +++ b/platforms/parrot/bebop/client/client.go @@ -108,7 +108,7 @@ func NewNetworkFrame(buf []byte) NetworkFrame { } func networkFrameGenerator() func(*bytes.Buffer, byte, byte) *bytes.Buffer { - //func networkFrameGenerator() func(*bytes.Buffer, byte, byte) NetworkFrame { + // func networkFrameGenerator() func(*bytes.Buffer, byte, byte) NetworkFrame { // // ARNETWORKAL_Frame_t // diff --git a/platforms/parrot/minidrone/helpers_test.go b/platforms/parrot/minidrone/helpers_test.go index 1f860b4e3..48106b64d 100644 --- a/platforms/parrot/minidrone/helpers_test.go +++ b/platforms/parrot/minidrone/helpers_test.go @@ -17,30 +17,30 @@ type bleTestClientAdaptor struct { testWriteCharacteristic func(string, []byte) error } -func (t *bleTestClientAdaptor) Connect() (err error) { return } -func (t *bleTestClientAdaptor) Reconnect() (err error) { return } -func (t *bleTestClientAdaptor) Disconnect() (err error) { return } -func (t *bleTestClientAdaptor) Finalize() (err error) { return } +func (t *bleTestClientAdaptor) Connect() error { return nil } +func (t *bleTestClientAdaptor) Reconnect() error { return nil } +func (t *bleTestClientAdaptor) Disconnect() error { return nil } +func (t *bleTestClientAdaptor) Finalize() error { return nil } func (t *bleTestClientAdaptor) Name() string { return t.name } func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } func (t *bleTestClientAdaptor) Address() string { return t.address } func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) (data []byte, err error) { +func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testReadCharacteristic(cUUID) } -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) (err error) { +func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.testWriteCharacteristic(cUUID, data) } -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) (err error) { +func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { // TODO: implement this... - return + return nil } func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { @@ -49,7 +49,7 @@ func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data t.testReadCharacteristic = f } -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) (err error)) { +func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { t.mtx.Lock() defer t.mtx.Unlock() t.testWriteCharacteristic = f @@ -58,11 +58,11 @@ func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data func NewBleTestAdaptor() *bleTestClientAdaptor { return &bleTestClientAdaptor{ address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) (data []byte, e error) { - return + testReadCharacteristic: func(cUUID string) ([]byte, error) { + return nil, nil }, - testWriteCharacteristic: func(cUUID string, data []byte) (e error) { - return + testWriteCharacteristic: func(cUUID string, data []byte) error { + return nil }, } } diff --git a/platforms/parrot/minidrone/minidrone_driver.go b/platforms/parrot/minidrone/minidrone_driver.go index 926ea0bdb..904fe842d 100644 --- a/platforms/parrot/minidrone/minidrone_driver.go +++ b/platforms/parrot/minidrone/minidrone_driver.go @@ -147,6 +147,7 @@ func (b *Driver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *Driver) adaptor() ble.BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(ble.BLEConnector) } @@ -194,7 +195,9 @@ func (b *Driver) Init() error { // GenerateAllStates sets up all the default states aka settings on the drone func (b *Driver) GenerateAllStates() error { b.stepsfa0b++ - buf := []byte{0x04, byte(b.stepsfa0b), 0x00, 0x04, 0x01, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2D, 0x31, 0x30, 0x2D, 0x32, 0x38, 0x00} + buf := []byte{ + 0x04, byte(b.stepsfa0b), 0x00, 0x04, 0x01, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2D, 0x31, 0x30, 0x2D, 0x32, 0x38, 0x00, + } return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) } diff --git a/platforms/parrot/minidrone/minidrone_driver_test.go b/platforms/parrot/minidrone/minidrone_driver_test.go index ec65a3ff5..cd6bb4e06 100644 --- a/platforms/parrot/minidrone/minidrone_driver_test.go +++ b/platforms/parrot/minidrone/minidrone_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/particle/adaptor.go b/platforms/particle/adaptor.go index 365621a2c..406586e88 100644 --- a/platforms/particle/adaptor.go +++ b/platforms/particle/adaptor.go @@ -10,6 +10,7 @@ import ( "strconv" "github.com/donovanhide/eventsource" + "gobot.io/x/gobot/v2" ) @@ -74,6 +75,7 @@ func (s *Adaptor) AnalogRead(pin string) (int, error) { resp, err := s.request("POST", url, params) if err == nil { + //nolint:forcetypeassert // ok here return int(resp["return_value"].(float64)), nil } @@ -119,6 +121,7 @@ func (s *Adaptor) DigitalRead(pin string) (int, error) { return -1, err } + //nolint:forcetypeassert // ok here return int(resp["return_value"].(float64)), nil } @@ -147,7 +150,7 @@ func (s *Adaptor) ServoWrite(pin string, angle byte) error { // * name - Event name to subscribe for, leave blank to subscribe to all events. // // A new event is emitted as a particle.Event struct -func (s *Adaptor) EventStream(source string, name string) (event *gobot.Event, err error) { +func (s *Adaptor) EventStream(source string, name string) (*gobot.Event, error) { var url string switch source { @@ -158,13 +161,12 @@ func (s *Adaptor) EventStream(source string, name string) (event *gobot.Event, e case "device": url = fmt.Sprintf("%s/events/%s?access_token=%s", s.deviceURL(), name, s.AccessToken) default: - err = errors.New("source param should be: all, devices or device") - return + return nil, errors.New("source param should be: all, devices or device") } events, _, err := eventSource(url) if err != nil { - return + return nil, err } go func() { @@ -175,17 +177,19 @@ func (s *Adaptor) EventStream(source string, name string) (event *gobot.Event, e } } }() - return + + return nil, nil //nolint:nilnil // seems ok here } // Variable returns a core variable value as a string -func (s *Adaptor) Variable(name string) (result string, err error) { +func (s *Adaptor) Variable(name string) (string, error) { url := fmt.Sprintf("%v/%s?access_token=%s", s.deviceURL(), name, s.AccessToken) resp, err := s.request("GET", url, nil) if err != nil { - return + return "", err } + var result string switch val := resp["result"].(type) { case bool: result = strconv.FormatBool(val) @@ -195,7 +199,7 @@ func (s *Adaptor) Variable(name string) (result string, err error) { result = val } - return + return result, nil } // Function executes a core function and @@ -214,6 +218,7 @@ func (s *Adaptor) Function(name string, args string) (int, error) { return -1, err } + //nolint:forcetypeassert // ok here return int(resp["return_value"].(float64)), nil } @@ -224,7 +229,7 @@ func (s *Adaptor) setAPIServer(server string) { // deviceURL constructs device url to make requests from Particle cloud api func (s *Adaptor) deviceURL() string { - if len(s.APIServer) <= 0 { + if len(s.APIServer) == 0 { s.setAPIServer("https://api.particle.io") } return fmt.Sprintf("%v/v1/devices/%v", s.APIServer, s.DeviceID) @@ -240,9 +245,11 @@ func (s *Adaptor) pinLevel(level byte) string { // request makes request to Particle cloud server, return err != nil if there is // any issue with the request. -func (s *Adaptor) request(method string, url string, params url.Values) (m map[string]interface{}, err error) { +// +//nolint:bodyclose,noctx // not changed yet +func (s *Adaptor) request(method string, url string, params url.Values) (map[string]interface{}, error) { var resp *http.Response - + var err error if method == "POST" { resp, err = http.PostForm(url, params) //nolint:gosec // accepted, because local function and no exposed routing } else if method == "GET" { @@ -250,25 +257,29 @@ func (s *Adaptor) request(method string, url string, params url.Values) (m map[s } if err != nil { - return + return nil, err } buf, err := io.ReadAll(resp.Body) if err != nil { - return + return nil, err } + var m map[string]interface{} if err := json.Unmarshal(buf, &m); err != nil { return m, err } if resp.Status != "200 OK" { - err = fmt.Errorf("%v: error communicating to the Particle cloud", resp.Status) - } else if _, ok := m["error"]; ok { - err = errors.New(m["error"].(string)) + return m, fmt.Errorf("%v: error communicating to the Particle cloud", resp.Status) + } + + if _, ok := m["error"]; ok { + //nolint:forcetypeassert // ok here + return m, errors.New(m["error"].(string)) } - return + return m, nil } func (s *Adaptor) servoPinOpen(pin string) error { diff --git a/platforms/particle/adaptor_test.go b/platforms/particle/adaptor_test.go index 20b5c632d..ee79d51ec 100644 --- a/platforms/particle/adaptor_test.go +++ b/platforms/particle/adaptor_test.go @@ -11,6 +11,7 @@ import ( "github.com/donovanhide/eventsource" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -20,7 +21,9 @@ func createTestServer(handler func(w http.ResponseWriter, r *http.Request)) *htt return httptest.NewServer(http.HandlerFunc(handler)) } -func getDummyResponseForPath(path string, dummyResponse string, t *testing.T) *httptest.Server { +func getDummyResponseForPath(t *testing.T, path string, dummyResponse string) *httptest.Server { + t.Helper() + dummyData := []byte(dummyResponse) return createTestServer(func(w http.ResponseWriter, r *http.Request) { @@ -32,7 +35,14 @@ func getDummyResponseForPath(path string, dummyResponse string, t *testing.T) *h }) } -func getDummyResponseForPathWithParams(path string, params []string, dummyResponse string, t *testing.T) *httptest.Server { +func getDummyResponseForPathWithParams( + t *testing.T, + path string, + params []string, + dummyResponse string, +) *httptest.Server { + t.Helper() + dummyData := []byte(dummyResponse) return createTestServer(func(w http.ResponseWriter, r *http.Request) { @@ -104,7 +114,7 @@ func TestAdaptorAnalogRead(t *testing.T) { params := []string{"A1"} a := initTestAdaptor() - testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/analogread", params, response, t) + testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/analogread", params, response) a.setAPIServer(testServer.URL) defer testServer.Close() @@ -131,7 +141,7 @@ func TestAdaptorPwmWrite(t *testing.T) { params := []string{"A1,1"} a := initTestAdaptor() - testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/analogwrite", params, response, t) + testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/analogwrite", params, response) defer testServer.Close() a.setAPIServer(testServer.URL) @@ -143,7 +153,7 @@ func TestAdaptorAnalogWrite(t *testing.T) { params := []string{"A1,1"} a := initTestAdaptor() - testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/analogwrite", params, response, t) + testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/analogwrite", params, response) defer testServer.Close() a.setAPIServer(testServer.URL) @@ -156,7 +166,7 @@ func TestAdaptorDigitalWrite(t *testing.T) { params := []string{"D7,HIGH"} a := initTestAdaptor() - testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/digitalwrite", params, response, t) + testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/digitalwrite", params, response) a.setAPIServer(testServer.URL) _ = a.DigitalWrite("D7", 1) @@ -165,7 +175,7 @@ func TestAdaptorDigitalWrite(t *testing.T) { // When LOW params = []string{"D7,LOW"} - testServer = getDummyResponseForPathWithParams("/"+a.DeviceID+"/digitalwrite", params, response, t) + testServer = getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/digitalwrite", params, response) defer testServer.Close() a.setAPIServer(testServer.URL) @@ -177,7 +187,7 @@ func TestAdaptorServoOpen(t *testing.T) { params := []string{"1"} a := initTestAdaptor() - testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/servoOpen", params, response, t) + testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/servoOpen", params, response) defer testServer.Close() a.setAPIServer(testServer.URL) @@ -189,7 +199,7 @@ func TestAdaptorServoWrite(t *testing.T) { params := []string{"1,128"} a := initTestAdaptorWithServo() - testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/servoSet", params, response, t) + testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/servoSet", params, response) defer testServer.Close() a.setAPIServer(testServer.URL) @@ -202,7 +212,7 @@ func TestAdaptorDigitalRead(t *testing.T) { params := []string{"D7"} a := initTestAdaptor() - testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/digitalread", params, response, t) + testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/digitalread", params, response) a.setAPIServer(testServer.URL) @@ -213,7 +223,7 @@ func TestAdaptorDigitalRead(t *testing.T) { // When LOW response = `{"return_value": 0}` - testServer = getDummyResponseForPathWithParams("/"+a.DeviceID+"/digitalread", params, response, t) + testServer = getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/digitalread", params, response) a.setAPIServer(testServer.URL) defer testServer.Close() @@ -240,7 +250,7 @@ func TestAdaptorFunction(t *testing.T) { response := `{"return_value": 1}` a := initTestAdaptor() - testServer := getDummyResponseForPath("/"+a.DeviceID+"/hello", response, t) + testServer := getDummyResponseForPath(t, "/"+a.DeviceID+"/hello", response) a.setAPIServer(testServer.URL) @@ -250,7 +260,7 @@ func TestAdaptorFunction(t *testing.T) { // When not existent response = `{"ok": false, "error": "timeout"}` - testServer = getDummyResponseForPath("/"+a.DeviceID+"/hello", response, t) + testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/hello", response) a.setAPIServer(testServer.URL) @@ -265,7 +275,7 @@ func TestAdaptorVariable(t *testing.T) { response := `{"result": "1"}` a := initTestAdaptor() - testServer := getDummyResponseForPath("/"+a.DeviceID+"/variable_name", response, t) + testServer := getDummyResponseForPath(t, "/"+a.DeviceID+"/variable_name", response) a.setAPIServer(testServer.URL) @@ -275,7 +285,7 @@ func TestAdaptorVariable(t *testing.T) { // When float response = `{"result": 1.1}` - testServer = getDummyResponseForPath("/"+a.DeviceID+"/variable_name", response, t) + testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/variable_name", response) a.setAPIServer(testServer.URL) @@ -285,7 +295,7 @@ func TestAdaptorVariable(t *testing.T) { // When int response = `{"result": 1}` - testServer = getDummyResponseForPath("/"+a.DeviceID+"/variable_name", response, t) + testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/variable_name", response) a.setAPIServer(testServer.URL) @@ -295,7 +305,7 @@ func TestAdaptorVariable(t *testing.T) { // When bool response = `{"result": true}` - testServer = getDummyResponseForPath("/"+a.DeviceID+"/variable_name", response, t) + testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/variable_name", response) a.setAPIServer(testServer.URL) @@ -305,7 +315,7 @@ func TestAdaptorVariable(t *testing.T) { // When not existent response = `{"ok": false, "error": "Variable not found"}` - testServer = getDummyResponseForPath("/"+a.DeviceID+"/not_existent", response, t) + testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/not_existent", response) a.setAPIServer(testServer.URL) diff --git a/platforms/pebble/doc.go b/platforms/pebble/doc.go index 7c6654555..686eb837a 100644 --- a/platforms/pebble/doc.go +++ b/platforms/pebble/doc.go @@ -10,7 +10,8 @@ installed on Pebble watch. Then install running: Example: -Before running the example, make sure configuration settings match with your program. In the example, api host is your computer IP, robot name is 'pebble' and robot api port is 8080 +Before running the example, make sure configuration settings match with your program. In the example, api host is +your computer IP, robot name is 'pebble' and robot api port is 8080 package main diff --git a/platforms/pebble/pebble_adaptor.go b/platforms/pebble/pebble_adaptor.go index 2555c91df..8dbac9073 100644 --- a/platforms/pebble/pebble_adaptor.go +++ b/platforms/pebble/pebble_adaptor.go @@ -15,11 +15,11 @@ func (a *Adaptor) Name() string { return a.name } func (a *Adaptor) SetName(n string) { a.name = n } // Connect returns true if connection to pebble is established successfully -func (a *Adaptor) Connect() (err error) { - return +func (a *Adaptor) Connect() error { + return nil } // Finalize returns true if connection to pebble is finalized successfully -func (a *Adaptor) Finalize() (err error) { - return +func (a *Adaptor) Finalize() error { + return nil } diff --git a/platforms/pebble/pebble_adaptor_test.go b/platforms/pebble/pebble_adaptor_test.go index 03e3eb64f..995fb27f2 100644 --- a/platforms/pebble/pebble_adaptor_test.go +++ b/platforms/pebble/pebble_adaptor_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/pebble/pebble_driver.go b/platforms/pebble/pebble_driver.go index 406a95119..345b9beaa 100644 --- a/platforms/pebble/pebble_driver.go +++ b/platforms/pebble/pebble_driver.go @@ -37,11 +37,12 @@ func NewDriver(adaptor *Adaptor) *Driver { p.AddEvent("accel") p.AddEvent("tap") + //nolint:forcetypeassert // ok here p.AddCommand("publish_event", func(params map[string]interface{}) interface{} { p.PublishEvent(params["name"].(string), params["data"].(string)) return nil }) - + //nolint:forcetypeassert // ok here p.AddCommand("send_notification", func(params map[string]interface{}) interface{} { p.SendNotification(params["message"].(string)) return nil @@ -58,10 +59,10 @@ func (d *Driver) SetName(n string) { d.name = n } func (d *Driver) Connection() gobot.Connection { return d.connection } // Start returns true if driver is initialized correctly -func (d *Driver) Start() (err error) { return } +func (d *Driver) Start() error { return nil } // Halt returns true if driver is halted successfully -func (d *Driver) Halt() (err error) { return } +func (d *Driver) Halt() error { return nil } // PublishEvent publishes event with specified name and data in gobot func (d *Driver) PublishEvent(name string, data string) { diff --git a/platforms/pebble/pebble_driver_test.go b/platforms/pebble/pebble_driver_test.go index 2087f1477..1c6d1ae4a 100644 --- a/platforms/pebble/pebble_driver_test.go +++ b/platforms/pebble/pebble_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/raspi/pwm_pin.go b/platforms/raspi/pwm_pin.go index 05f49a952..70aa59452 100644 --- a/platforms/raspi/pwm_pin.go +++ b/platforms/raspi/pwm_pin.go @@ -54,7 +54,7 @@ func (p *PWMPin) Polarity() (bool, error) { } // SetPolarity does not do anything when using PiBlaster -func (p *PWMPin) SetPolarity(bool) (err error) { +func (p *PWMPin) SetPolarity(bool) error { return nil } @@ -106,7 +106,7 @@ func (p *PWMPin) SetDutyCycle(duty uint32) error { return nil } -func (p *PWMPin) writeValue(data string) (err error) { +func (p *PWMPin) writeValue(data string) error { fi, err := p.sys.OpenFile(p.path, os.O_WRONLY|os.O_APPEND, 0o644) defer fi.Close() //nolint:staticcheck // for historical reasons @@ -115,5 +115,5 @@ func (p *PWMPin) writeValue(data string) (err error) { } _, err = fi.WriteString(data) - return + return err } diff --git a/platforms/raspi/pwm_pin_test.go b/platforms/raspi/pwm_pin_test.go index c2bfa6155..f25cd0c08 100644 --- a/platforms/raspi/pwm_pin_test.go +++ b/platforms/raspi/pwm_pin_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/system" ) diff --git a/platforms/raspi/raspi_adaptor.go b/platforms/raspi/raspi_adaptor.go index 2d915d550..f87608c36 100644 --- a/platforms/raspi/raspi_adaptor.go +++ b/platforms/raspi/raspi_adaptor.go @@ -8,6 +8,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -139,7 +140,7 @@ func (c *Adaptor) PWMPin(id string) (gobot.PWMPinner, error) { } // PwmWrite writes a PWM signal to the specified pin -func (c *Adaptor) PwmWrite(pin string, val byte) (err error) { +func (c *Adaptor) PwmWrite(pin string, val byte) error { c.mutex.Lock() defer c.mutex.Unlock() @@ -153,7 +154,7 @@ func (c *Adaptor) PwmWrite(pin string, val byte) (err error) { } // ServoWrite writes a servo signal to the specified pin -func (c *Adaptor) ServoWrite(pin string, angle byte) (err error) { +func (c *Adaptor) ServoWrite(pin string, angle byte) error { c.mutex.Lock() defer c.mutex.Unlock() @@ -184,14 +185,14 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { } func (c *Adaptor) getPinTranslatorFunction() func(string) (string, int, error) { - return func(pin string) (chip string, line int, err error) { + return func(pin string) (string, int, error) { + var line int if val, ok := pins[pin][c.readRevision()]; ok { line = val } else if val, ok := pins[pin]["*"]; ok { line = val } else { - err = errors.New("Not a valid pin") - return + return "", 0, errors.New("Not a valid pin") } // TODO: Pi1 model B has only this single "gpiochip0", a change of the translator is needed, // to support different chips with different revisions @@ -210,11 +211,12 @@ func (c *Adaptor) readRevision() string { if strings.Contains(v, "Revision") { s := strings.Split(v, " ") version, _ := strconv.ParseInt("0x"+s[len(s)-1], 0, 64) - if version <= 3 { + switch { + case version <= 3: c.revision = "1" - } else if version <= 15 { + case version <= 15: c.revision = "2" - } else { + default: c.revision = "3" } } diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index cd78959c8..4fd330ecb 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -272,7 +273,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateSpiBusNumber(t *testing.T) { diff --git a/platforms/rockpi/rockpi_adaptor.go b/platforms/rockpi/rockpi_adaptor.go index 321b7a688..13418f86c 100644 --- a/platforms/rockpi/rockpi_adaptor.go +++ b/platforms/rockpi/rockpi_adaptor.go @@ -6,6 +6,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -40,7 +41,7 @@ type Adaptor struct { // // Optional parameters: // -// adaptors.WithGpiodAccess(): use character device gpiod driver instead of the default sysfs (does NOT work on RockPi4C+!) +// adaptors.WithGpiodAccess(): use character device gpiod driver instead of the default sysfs (NOT work on RockPi4C+!) // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# // adaptors.WithGpiosActiveLow(pin's): invert the pin behavior func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { @@ -124,14 +125,14 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { } func (c *Adaptor) getPinTranslatorFunction() func(string) (string, int, error) { - return func(pin string) (chip string, line int, err error) { + return func(pin string) (string, int, error) { + var line int if val, ok := pins[pin][c.readRevision()]; ok { line = val } else if val, ok := pins[pin]["*"]; ok { line = val } else { - err = errors.New("Not a valid pin") - return + return "", 0, errors.New("Not a valid pin") } return "", line, nil } diff --git a/platforms/rockpi/rockpi_adaptor_test.go b/platforms/rockpi/rockpi_adaptor_test.go index 9d1d590e8..617cee981 100644 --- a/platforms/rockpi/rockpi_adaptor_test.go +++ b/platforms/rockpi/rockpi_adaptor_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2/system" ) diff --git a/platforms/sphero/bb8/bb8_driver_test.go b/platforms/sphero/bb8/bb8_driver_test.go index 05c3f425d..b0ec1c1b9 100644 --- a/platforms/sphero/bb8/bb8_driver_test.go +++ b/platforms/sphero/bb8/bb8_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/sphero/bb8/helpers_test.go b/platforms/sphero/bb8/helpers_test.go index da6f58245..9738f6987 100644 --- a/platforms/sphero/bb8/helpers_test.go +++ b/platforms/sphero/bb8/helpers_test.go @@ -18,30 +18,30 @@ type bleTestClientAdaptor struct { testWriteCharacteristic func(string, []byte) error } -func (t *bleTestClientAdaptor) Connect() (err error) { return } -func (t *bleTestClientAdaptor) Reconnect() (err error) { return } -func (t *bleTestClientAdaptor) Disconnect() (err error) { return } -func (t *bleTestClientAdaptor) Finalize() (err error) { return } +func (t *bleTestClientAdaptor) Connect() error { return nil } +func (t *bleTestClientAdaptor) Reconnect() error { return nil } +func (t *bleTestClientAdaptor) Disconnect() error { return nil } +func (t *bleTestClientAdaptor) Finalize() error { return nil } func (t *bleTestClientAdaptor) Name() string { return t.name } func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } func (t *bleTestClientAdaptor) Address() string { return t.address } func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) (data []byte, err error) { +func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testReadCharacteristic(cUUID) } -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) (err error) { +func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.testWriteCharacteristic(cUUID, data) } -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) (err error) { +func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { // TODO: implement this... - return + return nil } func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { @@ -50,7 +50,7 @@ func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data t.testReadCharacteristic = f } -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) (err error)) { +func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { t.mtx.Lock() defer t.mtx.Unlock() t.testWriteCharacteristic = f @@ -59,11 +59,11 @@ func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data func NewBleTestAdaptor() *bleTestClientAdaptor { return &bleTestClientAdaptor{ address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) (data []byte, e error) { - return + testReadCharacteristic: func(cUUID string) ([]byte, error) { + return nil, nil }, - testWriteCharacteristic: func(cUUID string, data []byte) (e error) { - return + testWriteCharacteristic: func(cUUID string, data []byte) error { + return nil }, } } diff --git a/platforms/sphero/ollie/helpers_test.go b/platforms/sphero/ollie/helpers_test.go index e78091a01..031c4f922 100644 --- a/platforms/sphero/ollie/helpers_test.go +++ b/platforms/sphero/ollie/helpers_test.go @@ -18,30 +18,30 @@ type bleTestClientAdaptor struct { testWriteCharacteristic func(string, []byte) error } -func (t *bleTestClientAdaptor) Connect() (err error) { return } -func (t *bleTestClientAdaptor) Reconnect() (err error) { return } -func (t *bleTestClientAdaptor) Disconnect() (err error) { return } -func (t *bleTestClientAdaptor) Finalize() (err error) { return } +func (t *bleTestClientAdaptor) Connect() error { return nil } +func (t *bleTestClientAdaptor) Reconnect() error { return nil } +func (t *bleTestClientAdaptor) Disconnect() error { return nil } +func (t *bleTestClientAdaptor) Finalize() error { return nil } func (t *bleTestClientAdaptor) Name() string { return t.name } func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } func (t *bleTestClientAdaptor) Address() string { return t.address } func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) (data []byte, err error) { +func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testReadCharacteristic(cUUID) } -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) (err error) { +func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.testWriteCharacteristic(cUUID, data) } -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) (err error) { +func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { // TODO: implement this... - return + return nil } func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { @@ -50,7 +50,7 @@ func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data t.testReadCharacteristic = f } -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) (err error)) { +func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { t.mtx.Lock() defer t.mtx.Unlock() t.testWriteCharacteristic = f @@ -59,11 +59,11 @@ func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data func NewBleTestAdaptor() *bleTestClientAdaptor { return &bleTestClientAdaptor{ address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) (data []byte, e error) { - return + testReadCharacteristic: func(cUUID string) ([]byte, error) { + return nil, nil }, - testWriteCharacteristic: func(cUUID string, data []byte) (e error) { - return + testWriteCharacteristic: func(cUUID string, data []byte) error { + return nil }, } } diff --git a/platforms/sphero/ollie/ollie_driver.go b/platforms/sphero/ollie/ollie_driver.go index 4ef37d836..d544d3a66 100644 --- a/platforms/sphero/ollie/ollie_driver.go +++ b/platforms/sphero/ollie/ollie_driver.go @@ -117,6 +117,7 @@ func (b *Driver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor func (b *Driver) adaptor() ble.BLEConnector { + //nolint:forcetypeassert // ok here return b.Connection().(ble.BLEConnector) } @@ -426,25 +427,21 @@ func (b *Driver) handleLocatorDetected(data []uint8) { } func (b *Driver) handleCollisionDetected(data []uint8) { - if len(data) == ResponsePacketMaxSize { + switch len(data) { + case ResponsePacketMaxSize: // Check if this is the header of collision response. (i.e. first part of data) // Collision response is 22 bytes long. (individual packet size is maxed at 20) - switch data[1] { - case 0xFE: - if data[2] == 0x07 { - // response code 7 is for a detected collision - if len(b.collisionResponse) == 0 { - b.collisionResponse = append(b.collisionResponse, data...) - } - } + if data[1] == 0xFE && data[2] == 0x07 && len(b.collisionResponse) == 0 { + // response code 7 is for a detected collision + b.collisionResponse = append(b.collisionResponse, data...) } - } else if len(data) == CollisionResponseSize-ResponsePacketMaxSize { + case CollisionResponseSize - ResponsePacketMaxSize: // if this is the remaining part of the collision response, // then make sure the header and first part of data is already received if len(b.collisionResponse) == ResponsePacketMaxSize { b.collisionResponse = append(b.collisionResponse, data...) } - } else { + default: return // not collision event } diff --git a/platforms/sphero/ollie/ollie_driver_test.go b/platforms/sphero/ollie/ollie_driver_test.go index 5294bb569..b736c0d82 100644 --- a/platforms/sphero/ollie/ollie_driver_test.go +++ b/platforms/sphero/ollie/ollie_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package ollie import ( @@ -8,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/sphero" ) diff --git a/platforms/sphero/sphero_adaptor.go b/platforms/sphero/sphero_adaptor.go index 762662a46..d71f10666 100644 --- a/platforms/sphero/sphero_adaptor.go +++ b/platforms/sphero/sphero_adaptor.go @@ -3,9 +3,9 @@ package sphero import ( "io" - "gobot.io/x/gobot/v2" - "go.bug.st/serial" + + "gobot.io/x/gobot/v2" ) // Adaptor represents a Connection to a Sphero @@ -41,21 +41,21 @@ func (a *Adaptor) Port() string { return a.port } func (a *Adaptor) SetPort(p string) { a.port = p } // Connect initiates a connection to the Sphero. Returns true on successful connection. -func (a *Adaptor) Connect() (err error) { - sp, e := a.connect(a.Port()) - if e != nil { - return e +func (a *Adaptor) Connect() error { + sp, err := a.connect(a.Port()) + if err != nil { + return err } a.sp = sp a.connected = true - return + return nil } // Reconnect attempts to reconnect to the Sphero. If the Sphero has an active connection // it will first close that connection and then establish a new connection. // Returns true on Successful reconnection -func (a *Adaptor) Reconnect() (err error) { +func (a *Adaptor) Reconnect() error { if a.connected { if err := a.Disconnect(); err != nil { return err @@ -67,8 +67,8 @@ func (a *Adaptor) Reconnect() (err error) { // Disconnect terminates the connection to the Sphero. Returns true on successful disconnect. func (a *Adaptor) Disconnect() error { if a.connected { - if e := a.sp.Close(); e != nil { - return e + if err := a.sp.Close(); err != nil { + return err } a.connected = false } diff --git a/platforms/sphero/sphero_adaptor_test.go b/platforms/sphero/sphero_adaptor_test.go index f9e4f3c89..a364e14c0 100644 --- a/platforms/sphero/sphero_adaptor_test.go +++ b/platforms/sphero/sphero_adaptor_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/sphero/sphero_driver.go b/platforms/sphero/sphero_driver.go index b2e9d48ae..81963422e 100644 --- a/platforms/sphero/sphero_driver.go +++ b/platforms/sphero/sphero_driver.go @@ -70,6 +70,7 @@ func NewSpheroDriver(a *Adaptor) *SpheroDriver { s.AddEvent(Collision) s.AddEvent(SensorData) + //nolint:forcetypeassert // ok here s.AddCommand("SetRGB", func(params map[string]interface{}) interface{} { r := uint8(params["r"].(float64)) g := uint8(params["g"].(float64)) @@ -78,6 +79,7 @@ func NewSpheroDriver(a *Adaptor) *SpheroDriver { return nil }) + //nolint:forcetypeassert // ok here s.AddCommand("Roll", func(params map[string]interface{}) interface{} { speed := uint8(params["speed"].(float64)) heading := uint16(params["heading"].(float64)) @@ -98,30 +100,31 @@ func NewSpheroDriver(a *Adaptor) *SpheroDriver { return s.ReadLocator() }) + //nolint:forcetypeassert // ok here s.AddCommand("SetBackLED", func(params map[string]interface{}) interface{} { level := uint8(params["level"].(float64)) s.SetBackLED(level) return nil }) - + //nolint:forcetypeassert // ok here s.AddCommand("SetRotationRate", func(params map[string]interface{}) interface{} { level := uint8(params["level"].(float64)) s.SetRotationRate(level) return nil }) - + //nolint:forcetypeassert // ok here s.AddCommand("SetHeading", func(params map[string]interface{}) interface{} { heading := uint16(params["heading"].(float64)) s.SetHeading(heading) return nil }) - + //nolint:forcetypeassert // ok here s.AddCommand("SetStabilization", func(params map[string]interface{}) interface{} { on := params["enable"].(bool) s.SetStabilization(on) return nil }) - + //nolint:forcetypeassert // ok here s.AddCommand("SetDataStreaming", func(params map[string]interface{}) interface{} { N := uint16(params["N"].(float64)) M := uint16(params["M"].(float64)) @@ -132,7 +135,7 @@ func NewSpheroDriver(a *Adaptor) *SpheroDriver { s.SetDataStreaming(DataStreamingConfig{N: N, M: M, Mask2: Mask2, Pcnt: Pcnt, Mask: Mask}) return nil }) - + //nolint:forcetypeassert // ok here s.AddCommand("ConfigureLocator", func(params map[string]interface{}) interface{} { Flags := uint8(params["Flags"].(float64)) X := int16(params["X"].(float64)) @@ -156,6 +159,7 @@ func (s *SpheroDriver) SetName(n string) { s.name = n } func (s *SpheroDriver) Connection() gobot.Connection { return s.connection } func (s *SpheroDriver) adaptor() *Adaptor { + //nolint:forcetypeassert // ok here return s.Connection().(*Adaptor) } @@ -167,7 +171,7 @@ func (s *SpheroDriver) adaptor() *Adaptor { // Collision sphero.CollisionPacket - On Collision Detected // SensorData sphero.DataStreamingPacket - On Data Streaming event // Error error- On error while processing asynchronous response -func (s *SpheroDriver) Start() (err error) { +func (s *SpheroDriver) Start() error { go func() { for { packet := <-s.packetChannel @@ -223,19 +227,19 @@ func (s *SpheroDriver) Start() (err error) { s.ConfigureCollisionDetection(DefaultCollisionConfig()) s.enableStopOnDisconnect() - return + return nil } // Halt halts the SpheroDriver and sends a SpheroDriver.Stop command to the Sphero. // Returns true on successful halt. -func (s *SpheroDriver) Halt() (err error) { +func (s *SpheroDriver) Halt() error { if s.adaptor().connected { gobot.Every(10*time.Millisecond, func() { s.Stop() }) time.Sleep(1 * time.Second) } - return + return nil } // SetRGB sets the Sphero to the given r, g, and b values @@ -414,7 +418,7 @@ func (s *SpheroDriver) craftPacket(body []uint8, did byte, cid byte) *packet { / return packet } -func (s *SpheroDriver) write(packet *packet) (err error) { +func (s *SpheroDriver) write(packet *packet) error { s.mtx.Lock() defer s.mtx.Unlock() buf := append(packet.header, packet.body...) @@ -422,11 +426,13 @@ func (s *SpheroDriver) write(packet *packet) (err error) { length, err := s.adaptor().sp.Write(buf) if err != nil { return err - } else if length != len(buf) { + } + + if length != len(buf) { return errors.New("Not enough bytes written") } s.seq++ - return + return nil } func (s *SpheroDriver) calculateChecksum(packet *packet) uint8 { diff --git a/platforms/sphero/sphero_driver_test.go b/platforms/sphero/sphero_driver_test.go index 728bf3063..4004d083f 100644 --- a/platforms/sphero/sphero_driver_test.go +++ b/platforms/sphero/sphero_driver_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package sphero import ( @@ -8,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/sphero/sphero_packets.go b/platforms/sphero/sphero_packets.go index efac784c2..33b17c9e8 100644 --- a/platforms/sphero/sphero_packets.go +++ b/platforms/sphero/sphero_packets.go @@ -37,7 +37,8 @@ func DefaultCollisionConfig() CollisionConfig { } // CollisionConfig provides configuration for the collision detection alogorithm. -// For more information refer to the official api specification https://github.com/orbotix/DeveloperResources/blob/master/docs/Collision%20detection%201.2.pdf. +// For more information refer to the official api specification +// https://github.com/orbotix/DeveloperResources/blob/master/docs/Collision%20detection%201.2.pdf. type CollisionConfig struct { // Detection method type to use. Methods 01h and 02h are supported as // of FW ver 1.42. Use 00h to completely disable this service. @@ -73,7 +74,8 @@ type CollisionPacket struct { Timestamp uint32 } -// DefaultDataStreamingConfig returns a DataStreamingConfig with a sampling rate of 40hz, 1 sample frame per package, unlimited streaming, and will stream all available sensor information +// DefaultDataStreamingConfig returns a DataStreamingConfig with a sampling rate of 40hz, 1 sample frame per package, +// unlimited streaming, and will stream all available sensor information func DefaultDataStreamingConfig() DataStreamingConfig { return DataStreamingConfig{ N: 10, @@ -85,7 +87,8 @@ func DefaultDataStreamingConfig() DataStreamingConfig { } // DataStreamingConfig provides configuration for Sensor Data Streaming. -// For more information refer to the official api specification https://github.com/orbotix/DeveloperResources/blob/master/docs/Sphero_API_1.50.pdf page 28 +// For more information refer to the official api specification +// https://github.com/orbotix/DeveloperResources/blob/master/docs/Sphero_API_1.50.pdf page 28 type DataStreamingConfig struct { // Divisor of the maximum sensor sampling rate N uint16 diff --git a/platforms/sphero/sprkplus/helpers_test.go b/platforms/sphero/sprkplus/helpers_test.go index af6455f8a..b26be641e 100644 --- a/platforms/sphero/sprkplus/helpers_test.go +++ b/platforms/sphero/sprkplus/helpers_test.go @@ -18,30 +18,30 @@ type bleTestClientAdaptor struct { testWriteCharacteristic func(string, []byte) error } -func (t *bleTestClientAdaptor) Connect() (err error) { return } -func (t *bleTestClientAdaptor) Reconnect() (err error) { return } -func (t *bleTestClientAdaptor) Disconnect() (err error) { return } -func (t *bleTestClientAdaptor) Finalize() (err error) { return } +func (t *bleTestClientAdaptor) Connect() error { return nil } +func (t *bleTestClientAdaptor) Reconnect() error { return nil } +func (t *bleTestClientAdaptor) Disconnect() error { return nil } +func (t *bleTestClientAdaptor) Finalize() error { return nil } func (t *bleTestClientAdaptor) Name() string { return t.name } func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } func (t *bleTestClientAdaptor) Address() string { return t.address } func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) (data []byte, err error) { +func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { t.mtx.Lock() defer t.mtx.Unlock() return t.testReadCharacteristic(cUUID) } -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) (err error) { +func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { t.mtx.Lock() defer t.mtx.Unlock() return t.testWriteCharacteristic(cUUID, data) } -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) (err error) { +func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { // TODO: implement this... - return + return nil } func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { @@ -50,7 +50,7 @@ func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data t.testReadCharacteristic = f } -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) (err error)) { +func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { t.mtx.Lock() defer t.mtx.Unlock() t.testWriteCharacteristic = f @@ -59,11 +59,11 @@ func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data func NewBleTestAdaptor() *bleTestClientAdaptor { return &bleTestClientAdaptor{ address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) (data []byte, e error) { - return + testReadCharacteristic: func(cUUID string) ([]byte, error) { + return nil, nil }, - testWriteCharacteristic: func(cUUID string, data []byte) (e error) { - return + testWriteCharacteristic: func(cUUID string, data []byte) error { + return nil }, } } diff --git a/platforms/sphero/sprkplus/sprkplus_driver_test.go b/platforms/sphero/sprkplus/sprkplus_driver_test.go index a050e505a..67742a13a 100644 --- a/platforms/sphero/sprkplus/sprkplus_driver_test.go +++ b/platforms/sphero/sprkplus/sprkplus_driver_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/platforms/tinkerboard/adaptor.go b/platforms/tinkerboard/adaptor.go index 8b1208a65..63f8a451d 100644 --- a/platforms/tinkerboard/adaptor.go +++ b/platforms/tinkerboard/adaptor.go @@ -5,6 +5,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" @@ -154,14 +155,14 @@ func (c *Adaptor) translatePWMPin(id string) (string, int, error) { return path, pinInfo.channel, nil } -func (p pwmPinDefinition) findPWMDir(sys *system.Accesser) (dir string, err error) { +func (p pwmPinDefinition) findPWMDir(sys *system.Accesser) (string, error) { items, _ := sys.Find(p.dir, p.dirRegexp) if len(items) == 0 { return "", fmt.Errorf("No path found for PWM directory pattern, '%s' in path '%s'. See README.md for activation", p.dirRegexp, p.dir) } - dir = items[0] + dir := items[0] info, err := sys.Stat(dir) if err != nil { return "", fmt.Errorf("Error (%v) on access '%s'", err, dir) @@ -170,5 +171,5 @@ func (p pwmPinDefinition) findPWMDir(sys *system.Accesser) (dir string, err erro return "", fmt.Errorf("The item '%s' is not a directory, which is not expected", dir) } - return + return dir, nil } diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 4835b66a3..f00374fde 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -188,7 +189,7 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestFinalizeErrorAfterPWM(t *testing.T) { @@ -200,7 +201,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestSpiDefaultValues(t *testing.T) { @@ -232,7 +233,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateSpiBusNumber(t *testing.T) { diff --git a/platforms/upboard/up2/adaptor.go b/platforms/upboard/up2/adaptor.go index 5f0360b00..d4a80660c 100644 --- a/platforms/upboard/up2/adaptor.go +++ b/platforms/upboard/up2/adaptor.go @@ -7,6 +7,7 @@ import ( "sync" multierror "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index 82faaa203..0c8c0f348 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" @@ -119,7 +120,7 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestFinalizeErrorAfterPWM(t *testing.T) { @@ -132,7 +133,7 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.WithWriteError = true err := a.Finalize() - assert.Contains(t, err.Error(), "write error") + require.ErrorContains(t, err, "write error") } func TestSpiDefaultValues(t *testing.T) { @@ -194,7 +195,7 @@ func TestI2cFinalizeWithErrors(t *testing.T) { // act err = a.Finalize() // assert - assert.Contains(t, err.Error(), "close error") + require.ErrorContains(t, err, "close error") } func Test_validateI2cBusNumber(t *testing.T) { diff --git a/robot.go b/robot.go index 647cd8b77..6547bbfa4 100644 --- a/robot.go +++ b/robot.go @@ -71,7 +71,11 @@ func (r *Robots) Len() int { func (r *Robots) Start(args ...interface{}) error { autoRun := true if args[0] != nil { - autoRun = args[0].(bool) + var ok bool + if autoRun, ok = args[0].(bool); !ok { + // we treat this as false + autoRun = false + } } for _, robot := range *r { if err := robot.Start(autoRun); err != nil { @@ -122,23 +126,23 @@ func NewRobot(v ...interface{}) *Robot { } for i := range v { - switch v[i].(type) { + switch val := v[i].(type) { case string: - r.Name = v[i].(string) + r.Name = val case []Connection: log.Println("Initializing connections...") - for _, connection := range v[i].([]Connection) { + for _, connection := range val { c := r.AddConnection(connection) log.Println("Initializing connection", c.Name(), "...") } case []Device: log.Println("Initializing devices...") - for _, device := range v[i].([]Device) { + for _, device := range val { d := r.AddDevice(device) log.Println("Initializing device", d.Name(), "...") } case func(): - r.Work = v[i].(func()) + r.Work = val } } @@ -158,7 +162,11 @@ func NewRobot(v ...interface{}) *Robot { // connections and devices on first error. func (r *Robot) Start(args ...interface{}) error { if len(args) > 0 && args[0] != nil { - r.AutoRun = args[0].(bool) + var ok bool + if r.AutoRun, ok = args[0].(bool); !ok { + // we treat this as false + r.AutoRun = false + } } log.Println("Starting Robot", r.Name, "...") if err := r.Connections().Start(); err != nil { @@ -216,7 +224,7 @@ func (r *Robot) Stop() error { // Running returns if the Robot is currently started or not func (r *Robot) Running() bool { - return r.running.Load().(bool) + return r.running.Load().(bool) //nolint:forcetypeassert // no error return value, so there is no better way } // Devices returns all devices associated with this Robot. diff --git a/robot_work.go b/robot_work.go index b3a4e4ac7..11f74ea90 100644 --- a/robot_work.go +++ b/robot_work.go @@ -47,7 +47,7 @@ type RobotWork struct { id uuid.UUID kind string tickCount int - ctx context.Context + ctx context.Context //nolint:containedctx // done by intention cancelFunc context.CancelFunc function func() ticker *time.Ticker diff --git a/system/digitalpin_access_test.go b/system/digitalpin_access_test.go index beda36d0c..92db6f9df 100644 --- a/system/digitalpin_access_test.go +++ b/system/digitalpin_access_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package system import ( diff --git a/system/digitalpin_config.go b/system/digitalpin_config.go index 76e880283..f41227887 100644 --- a/system/digitalpin_config.go +++ b/system/digitalpin_config.go @@ -243,6 +243,8 @@ func (d *digitalPinConfig) SetEventHandlerForEdge( // the adaptor. E.g. sysfs driver in gobot has not implemented edge detection yet. The function is only useful // together with SetEventHandlerForEdge() and its corresponding With*() functions. // The function is intended to use by WithPinPollForEdgeDetection(). +// +//nolint:nonamedreturns // useful here func (d *digitalPinConfig) SetPollForEdgeDetection( pollInterval time.Duration, pollQuitChan chan struct{}, diff --git a/system/digitalpin_config_test.go b/system/digitalpin_config_test.go index c14d6fb5b..82a63c9fe 100644 --- a/system/digitalpin_config_test.go +++ b/system/digitalpin_config_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" ) diff --git a/system/digitalpin_gpiod.go b/system/digitalpin_gpiod.go index c161dc00f..7ebe9f85c 100644 --- a/system/digitalpin_gpiod.go +++ b/system/digitalpin_gpiod.go @@ -8,6 +8,7 @@ import ( "time" "github.com/warthog618/gpiod" + "gobot.io/x/gobot/v2" ) diff --git a/system/digitalpin_gpiod_test.go b/system/digitalpin_gpiod_test.go index a6e086202..226db6576 100644 --- a/system/digitalpin_gpiod_test.go +++ b/system/digitalpin_gpiod_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -257,7 +258,7 @@ func TestWriteGpiod(t *testing.T) { // assert if tc.wantErr != nil { for _, want := range tc.wantErr { - assert.Contains(t, err.Error(), want) + require.ErrorContains(t, err, want) } } else { require.NoError(t, err) @@ -292,7 +293,7 @@ func TestReadGpiod(t *testing.T) { // assert if tc.wantErr != nil { for _, want := range tc.wantErr { - assert.Contains(t, err.Error(), want) + require.ErrorContains(t, err, want) } } else { require.NoError(t, err) diff --git a/system/digitalpin_mock.go b/system/digitalpin_mock.go index 440df69ea..c85fa345a 100644 --- a/system/digitalpin_mock.go +++ b/system/digitalpin_mock.go @@ -37,8 +37,8 @@ func (d *digitalPinMock) Write(b int) error { } // Read reads the given value from character device -func (d *digitalPinMock) Read() (n int, err error) { - return 0, err +func (d *digitalPinMock) Read() (int, error) { + return 0, nil } // Export sets the pin as exported with the configured direction diff --git a/system/digitalpin_sysfs.go b/system/digitalpin_sysfs.go index 7829befe4..9c0e89c8c 100644 --- a/system/digitalpin_sysfs.go +++ b/system/digitalpin_sysfs.go @@ -89,9 +89,9 @@ func (d *digitalPinSysfs) Unexport() error { err = writeFile(unexport, []byte(d.pin)) if err != nil { - // If EINVAL then the pin is reserved in the system and can't be unexported - e, ok := err.(*os.PathError) - if !ok || e.Err != Syscall_EINVAL { + // If EINVAL then the pin is reserved in the system and can't be unexported, we suppress the error + var pathError *os.PathError + if !(errors.As(err, &pathError) && errors.Is(err, Syscall_EINVAL)) { return err } } @@ -123,9 +123,9 @@ func (d *digitalPinSysfs) reconfigure() error { err = writeFile(exportFile, []byte(d.pin)) if err != nil { - // If EBUSY then the pin has already been exported - e, ok := err.(*os.PathError) - if !ok || e.Err != Syscall_EBUSY { + // If EBUSY then the pin has already been exported, we suppress the error + var pathError *os.PathError + if !(errors.As(err, &pathError) && errors.Is(err, Syscall_EBUSY)) { return err } } @@ -196,11 +196,9 @@ func (d *digitalPinSysfs) reconfigure() error { err = startEdgePolling(d.label, d.Read, d.pollInterval, d.edge, d.edgeEventHandler, d.pollQuitChan) } } - } else { + } else if d.drive != digitalPinDrivePushPull && systemSysfsDebug { // configure drive (unsupported) - if d.drive != digitalPinDrivePushPull && systemSysfsDebug { - log.Printf("drive options (%d) are not supported by sysfs\n", d.drive) - } + log.Printf("drive options (%d) are not supported by sysfs\n", d.drive) } if err != nil { diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index 6efa8117f..6f6473ac9 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -387,7 +388,9 @@ func TestDigitalPinSysfs(t *testing.T) { } err = pin.Unexport() - require.ErrorContains(t, err.(*os.PathError).Err, "write error") + var pathError *os.PathError + require.ErrorAs(t, err, &pathError) + require.ErrorContains(t, err, "write error") } func TestDigitalPinUnexportErrorSysfs(t *testing.T) { diff --git a/system/fs.go b/system/fs.go index 2bdfd365d..829dc6ef6 100644 --- a/system/fs.go +++ b/system/fs.go @@ -10,7 +10,7 @@ import ( type nativeFilesystem struct{} // openFile calls os.OpenFile(). -func (fs *nativeFilesystem) openFile(name string, flag int, perm os.FileMode) (file File, err error) { +func (fs *nativeFilesystem) openFile(name string, flag int, perm os.FileMode) (File, error) { return os.OpenFile(name, flag, perm) } diff --git a/system/fs_mock.go b/system/fs_mock.go index f7f1a5f1f..d91c4383e 100644 --- a/system/fs_mock.go +++ b/system/fs_mock.go @@ -42,7 +42,7 @@ var ( ) // Write writes string(b) to f.Contents -func (f *MockFile) Write(b []byte) (n int, err error) { +func (f *MockFile) Write(b []byte) (int, error) { if f.fs.WithWriteError { return 0, errWrite } @@ -50,24 +50,24 @@ func (f *MockFile) Write(b []byte) (n int, err error) { } // Seek seeks to a specific offset in a file -func (f *MockFile) Seek(offset int64, whence int) (ret int64, err error) { +func (f *MockFile) Seek(offset int64, whence int) (int64, error) { return offset, nil } // WriteString writes s to f.Contents -func (f *MockFile) WriteString(s string) (ret int, err error) { +func (f *MockFile) WriteString(s string) (int, error) { f.Contents = s f.Seq = f.fs.next() return len(s), nil } // Sync implements the File interface Sync function -func (f *MockFile) Sync() (err error) { +func (f *MockFile) Sync() error { return nil } // Read copies b bytes from f.Contents -func (f *MockFile) Read(b []byte) (n int, err error) { +func (f *MockFile) Read(b []byte) (int, error) { if f.fs.WithReadError { return 0, errRead } @@ -83,7 +83,7 @@ func (f *MockFile) Read(b []byte) (n int, err error) { } // ReadAt calls MockFile.Read -func (f *MockFile) ReadAt(b []byte, off int64) (n int, err error) { +func (f *MockFile) ReadAt(b []byte, off int64) (int, error) { return f.Read(b) } @@ -119,7 +119,7 @@ func newMockFilesystem(items []string) *MockFilesystem { } // OpenFile opens file name from fs.Files, if the file does not exist it returns an os.PathError -func (fs *MockFilesystem) openFile(name string, _ int, _ os.FileMode) (file File, err error) { +func (fs *MockFilesystem) openFile(name string, _ int, _ os.FileMode) (File, error) { f, ok := fs.Files[name] if ok { f.Opened = true diff --git a/system/i2c_device.go b/system/i2c_device.go index 3b635e03d..8c8e9f077 100644 --- a/system/i2c_device.go +++ b/system/i2c_device.go @@ -111,7 +111,7 @@ func (d *i2cDevice) ReadByte(address int) (byte, error) { } // ReadByteData reads a byte from the given register of an i2c device. -func (d *i2cDevice) ReadByteData(address int, reg uint8) (val uint8, err error) { +func (d *i2cDevice) ReadByteData(address int, reg uint8) (uint8, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -120,12 +120,12 @@ func (d *i2cDevice) ReadByteData(address int, reg uint8) (val uint8, err error) } var data uint8 = 0xFD // set value for debugging purposes - err = d.smbusAccess(address, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, unsafe.Pointer(&data)) + err := d.smbusAccess(address, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, unsafe.Pointer(&data)) return data, err } // ReadWordData reads a 16 bit value starting from the given register of an i2c device. -func (d *i2cDevice) ReadWordData(address int, reg uint8) (val uint16, err error) { +func (d *i2cDevice) ReadWordData(address int, reg uint8) (uint16, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -134,7 +134,7 @@ func (d *i2cDevice) ReadWordData(address int, reg uint8) (val uint16, err error) } var data uint16 = 0xFFFE // set value for debugging purposes - err = d.smbusAccess(address, I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, unsafe.Pointer(&data)) + err := d.smbusAccess(address, I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, unsafe.Pointer(&data)) return data, err } @@ -241,7 +241,7 @@ func (d *i2cDevice) WriteBytes(address int, data []byte) error { } // Read implements direct I2C read operations. -func (d *i2cDevice) Read(address int, b []byte) (n int, err error) { +func (d *i2cDevice) Read(address int, b []byte) (int, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -249,7 +249,7 @@ func (d *i2cDevice) Read(address int, b []byte) (n int, err error) { } // Write implements the io.ReadWriteCloser method by direct I2C write operations. -func (d *i2cDevice) Write(address int, b []byte) (n int, err error) { +func (d *i2cDevice) Write(address int, b []byte) (int, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -288,8 +288,8 @@ func (d *i2cDevice) writeBytes(address int, data []byte) error { return nil } -func (d *i2cDevice) write(address int, b []byte) (n int, err error) { - if err = d.setAddress(address); err != nil { +func (d *i2cDevice) write(address int, b []byte) (int, error) { + if err := d.setAddress(address); err != nil { return 0, err } if err := d.openFileLazy("Write"); err != nil { @@ -309,8 +309,8 @@ func (d *i2cDevice) readAndCheckCount(address int, data []byte) error { return nil } -func (d *i2cDevice) read(address int, b []byte) (n int, err error) { - if err = d.setAddress(address); err != nil { +func (d *i2cDevice) read(address int, b []byte) (int, error) { + if err := d.setAddress(address); err != nil { return 0, err } if err := d.openFileLazy("Read"); err != nil { @@ -378,7 +378,7 @@ func (d *i2cDevice) setAddress(address int) error { return nil } -func (d *i2cDevice) syscallIoctl(signal uintptr, payload unsafe.Pointer, address int, sender string) (err error) { +func (d *i2cDevice) syscallIoctl(signal uintptr, payload unsafe.Pointer, address int, sender string) error { if err := d.openFileLazy(sender); err != nil { return err } @@ -389,12 +389,13 @@ func (d *i2cDevice) syscallIoctl(signal uintptr, payload unsafe.Pointer, address return nil } -func (d *i2cDevice) openFileLazy(sender string) (err error) { //nolint:unparam // useful for debugging +func (d *i2cDevice) openFileLazy(sender string) error { //nolint:unparam // useful for debugging // lazy initialization // note: "os.ModeExclusive" is undefined without create the file. This means for the existing character device, // a second open will not return an error e.g. due to a busy resource, so most likely "os.ModeExclusive" is not really // helpful and we drop it to the default "0" used by normal Open(). if d.file == nil { + var err error if d.file, err = d.fs.openFile(d.location, os.O_RDWR, 0); err != nil { return err } diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index 78e59823d..b7b473885 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) @@ -18,6 +19,7 @@ func getSyscallFuncImpl( // bit 0: error on function query // bit 1: error on set address // bit 2: error on command + //nolint:nonamedreturns // useful here return func(trap, a1, a2 uintptr, a3 unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) { // function query if (trap == Syscall_SYS_IOCTL) && (a2 == I2C_FUNCS) { diff --git a/system/pwmpin_sysfs.go b/system/pwmpin_sysfs.go index 2980a977f..a038e469f 100644 --- a/system/pwmpin_sysfs.go +++ b/system/pwmpin_sysfs.go @@ -2,6 +2,7 @@ package system import ( "bytes" + "errors" "fmt" "os" "path" @@ -47,9 +48,9 @@ func newPWMPinSysfs(fs filesystem, path string, pin int, polNormIdent string, po func (p *pwmPinSysFs) Export() error { _, err := p.write(p.fs, p.pwmExportPath(), []byte(p.pin)) if err != nil { - // If EBUSY then the pin has already been exported - e, ok := err.(*os.PathError) - if !ok || e.Err != Syscall_EBUSY { + // If EBUSY then the pin has already been exported, we suppress the error + var pathError *os.PathError + if !(errors.As(err, &pathError) && errors.Is(err, Syscall_EBUSY)) { return fmt.Errorf(pwmPinErrorPattern, "Export", p.pin, err) } } diff --git a/system/pwmpin_sysfs_test.go b/system/pwmpin_sysfs_test.go index c0ba78967..b4c1f82c9 100644 --- a/system/pwmpin_sysfs_test.go +++ b/system/pwmpin_sysfs_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2" ) diff --git a/system/spi_access.go b/system/spi_access.go index 5b1feb482..d7fdd1bef 100644 --- a/system/spi_access.go +++ b/system/spi_access.go @@ -12,7 +12,10 @@ type gpioSpiAccess struct { cfg spiGpioConfig } -func (*periphioSpiAccess) createDevice(busNum, chipNum, mode, bits int, maxSpeed int64) (gobot.SpiSystemDevicer, error) { +func (*periphioSpiAccess) createDevice( + busNum, chipNum, mode, bits int, + maxSpeed int64, +) (gobot.SpiSystemDevicer, error) { return newSpiPeriphIo(busNum, chipNum, mode, bits, maxSpeed) } @@ -24,7 +27,10 @@ func (psa *periphioSpiAccess) isSupported() bool { return true } -func (gsa *gpioSpiAccess) createDevice(busNum, chipNum, mode, bits int, maxSpeed int64) (gobot.SpiSystemDevicer, error) { +func (gsa *gpioSpiAccess) createDevice( + busNum, chipNum, mode, bits int, + maxSpeed int64, +) (gobot.SpiSystemDevicer, error) { return newSpiGpio(gsa.cfg, maxSpeed) } diff --git a/system/spi_gpio.go b/system/spi_gpio.go index 68c7c0016..5a21ff7d2 100644 --- a/system/spi_gpio.go +++ b/system/spi_gpio.go @@ -5,6 +5,7 @@ import ( "time" "github.com/hashicorp/go-multierror" + "gobot.io/x/gobot/v2" ) diff --git a/system/spi_mock.go b/system/spi_mock.go index f78bb41a6..b4c63b14d 100644 --- a/system/spi_mock.go +++ b/system/spi_mock.go @@ -17,7 +17,10 @@ type MockSpiAccess struct { sysdev *spiMock } -func (spi *MockSpiAccess) createDevice(busNum, chipNum, mode, bits int, maxSpeed int64) (gobot.SpiSystemDevicer, error) { +func (spi *MockSpiAccess) createDevice( + busNum, chipNum, mode, bits int, + maxSpeed int64, +) (gobot.SpiSystemDevicer, error) { spi.busNum = busNum spi.chipNum = chipNum spi.mode = mode diff --git a/system/syscall.go b/system/syscall.go index b90b1e976..41f29441a 100644 --- a/system/syscall.go +++ b/system/syscall.go @@ -29,6 +29,8 @@ type nativeSyscall struct{} // detect this problem and this unpack procedure would cause unpredictable results. // So the decision was taken to give the address here as a separate parameter, although it is not used in every call. // Note also, that the size of the address variable at Kernel side is u16, therefore uint16 is used here. +// +//nolint:nonamedreturns // useful here func (sys *nativeSyscall) syscall( trap uintptr, f File, diff --git a/system/syscall_mock.go b/system/syscall_mock.go index 1be3ffeba..1f77f2d11 100644 --- a/system/syscall_mock.go +++ b/system/syscall_mock.go @@ -17,6 +17,8 @@ type mockSyscall struct { } // Syscall calls the user defined implementation, used for tests, implements the SystemCaller interface +// +//nolint:nonamedreturns // useful here func (sys *mockSyscall) syscall( trap uintptr, f File, diff --git a/system/system.go b/system/system.go index 30ae3f39e..6e53fe144 100644 --- a/system/system.go +++ b/system/system.go @@ -13,7 +13,7 @@ const systemDebug = false type File interface { Write(b []byte) (n int, err error) WriteString(s string) (ret int, err error) - Sync() (err error) + Sync() error Read(b []byte) (n int, err error) ReadAt(b []byte, off int64) (n int, err error) Seek(offset int64, whence int) (ret int64, err error) diff --git a/system/system_test.go b/system/system_test.go index b29bd52d3..0edeab0da 100644 --- a/system/system_test.go +++ b/system/system_test.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // ok here package system import ( diff --git a/utils.go b/utils.go index 5223c7160..36e58bb8d 100644 --- a/utils.go +++ b/utils.go @@ -46,11 +46,12 @@ func FromScale(input, min, max float64) float64 { // If input is greater than max then ToScale returns max func ToScale(input, min, max float64) float64 { i := input*(math.Max(min, max)-math.Min(min, max)) + math.Min(min, max) - if i < math.Min(min, max) { + switch { + case i < math.Min(min, max): return math.Min(min, max) - } else if i > math.Max(min, max) { + case i > math.Max(min, max): return math.Max(min, max) - } else { + default: return i } } From 39808451cfb932b28fb08d45deeedc05c34882f1 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Thu, 23 Nov 2023 19:01:42 +0100 Subject: [PATCH 30/57] aio(all): introduce functional options (#1039) --- drivers/aio/aio.go | 32 --- drivers/aio/aio_driver.go | 119 ++++++++ drivers/aio/aio_driver_test.go | 69 +++++ drivers/aio/analog_actuator_driver.go | 132 +++++---- drivers/aio/analog_actuator_driver_test.go | 204 +++++++++----- drivers/aio/analog_sensor_driver.go | 175 +++++++----- drivers/aio/analog_sensor_driver_test.go | 257 ++++++++++++------ drivers/aio/grove_drivers.go | 101 +++---- drivers/aio/grove_drivers_test.go | 147 +++++++--- .../aio/grove_temperature_sensor_driver.go | 36 ++- .../grove_temperature_sensor_driver_test.go | 76 ++++-- drivers/aio/helpers_test.go | 48 +++- drivers/aio/temperature_sensor_driver.go | 39 +-- drivers/aio/temperature_sensor_driver_test.go | 104 ++++--- drivers/gpio/buzzer_driver_test.go | 6 +- drivers/gpio/direct_pin_driver_test.go | 18 +- drivers/gpio/gpio_driver_test.go | 4 +- drivers/gpio/hd44780_driver_test.go | 18 +- drivers/gpio/led_driver_test.go | 10 +- drivers/gpio/rgb_led_driver_test.go | 10 +- drivers/gpio/servo_driver_test.go | 8 +- drivers/i2c/ads1x15_driver_1015_test.go | 12 +- drivers/i2c/ads1x15_driver_1115_test.go | 12 +- drivers/i2c/yl40_driver.go | 28 +- ...lebone_led_brightness_with_analog_input.go | 3 +- examples/edison_grove_light_sensor.go | 3 +- examples/edison_grove_piezo_vibration.go | 3 +- examples/edison_grove_rotary_sensor.go | 3 +- examples/edison_grove_sound_sensor.go | 3 +- examples/edison_grove_temperature_sensor.go | 2 +- ...edison_led_brightness_with_analog_input.go | 3 +- examples/firmata_grove_sound_sensor.go | 3 +- examples/firmata_integration.go | 2 +- ...irmata_led_brightness_with_analog_input.go | 3 +- examples/gopigo3_grove_light_sensor.go | 3 +- examples/joule_grove_rotary_sensor.go | 3 +- .../joule_led_brightness_with_analog_input.go | 3 +- examples/raspi_grove_pi_rotary.go | 3 +- examples/raspi_grove_rotary_sensor.go | 3 +- examples/wifi_firmata_analog_input.go | 3 +- 40 files changed, 1140 insertions(+), 571 deletions(-) delete mode 100644 drivers/aio/aio.go create mode 100644 drivers/aio/aio_driver.go create mode 100644 drivers/aio/aio_driver_test.go diff --git a/drivers/aio/aio.go b/drivers/aio/aio.go deleted file mode 100644 index 3915ec65b..000000000 --- a/drivers/aio/aio.go +++ /dev/null @@ -1,32 +0,0 @@ -package aio - -import ( - "errors" -) - -// ErrAnalogReadUnsupported is error resulting when a driver attempts to use -// hardware capabilities which a connection does not support -var ErrAnalogReadUnsupported = errors.New("AnalogRead is not supported by this platform") - -const ( - // Error event - Error = "error" - // Data event - Data = "data" - // Value event - Value = "value" - // Vibration event - Vibration = "vibration" -) - -// AnalogReader interface represents an Adaptor which has AnalogRead capabilities -type AnalogReader interface { - // gobot.Adaptor - AnalogRead(pin string) (val int, err error) -} - -// AnalogWriter interface represents an Adaptor which has AnalogWrite capabilities -type AnalogWriter interface { - // gobot.Adaptor - AnalogWrite(pin string, val int) error -} diff --git a/drivers/aio/aio_driver.go b/drivers/aio/aio_driver.go new file mode 100644 index 000000000..2f99bd364 --- /dev/null +++ b/drivers/aio/aio_driver.go @@ -0,0 +1,119 @@ +package aio + +import ( + "log" + "sync" + + "gobot.io/x/gobot/v2" +) + +const ( + // Error event + Error = "error" + // Data event + Data = "data" + // Value event + Value = "value" + // Vibration event + Vibration = "vibration" +) + +// AnalogReader interface represents an Adaptor which has AnalogRead capabilities +type AnalogReader interface { + // gobot.Adaptor + AnalogRead(pin string) (val int, err error) +} + +// AnalogWriter interface represents an Adaptor which has AnalogWrite capabilities +type AnalogWriter interface { + // gobot.Adaptor + AnalogWrite(pin string, val int) error +} + +// optionApplier needs to be implemented by each configurable option type +type optionApplier interface { + apply(cfg *configuration) +} + +// configuration contains all changeable attributes of the driver. +type configuration struct { + name string +} + +// nameOption is the type for applying another name to the configuration +type nameOption string + +// Driver implements the interface gobot.Driver. +type driver struct { + driverCfg *configuration + connection interface{} + afterStart func() error + beforeHalt func() error + gobot.Commander + mutex *sync.Mutex // e.g. used to prevent data race between cyclic and single shot write/read to values and scaler +} + +// newDriver creates a new basic analog gobot driver. +func newDriver(a interface{}, name string) *driver { + d := driver{ + driverCfg: &configuration{name: gobot.DefaultName(name)}, + connection: a, + afterStart: func() error { return nil }, + beforeHalt: func() error { return nil }, + Commander: gobot.NewCommander(), + mutex: &sync.Mutex{}, + } + + return &d +} + +// WithName is used to replace the default name of the driver. +func WithName(name string) optionApplier { + return nameOption(name) +} + +// Name returns the name of the driver. +func (d *driver) Name() string { + return d.driverCfg.name +} + +// SetName sets the name of the driver. +// Deprecated: Please use option [aio.WithName] instead. +func (d *driver) SetName(name string) { + WithName(name).apply(d.driverCfg) +} + +// Connection returns the connection of the driver. +func (d *driver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.driverCfg.name) + return nil +} + +// Start initializes the driver. +func (d *driver) Start() error { + d.mutex.Lock() + defer d.mutex.Unlock() + + // currently there is nothing to do here for the driver + + return d.afterStart() +} + +// Halt halts the driver. +func (d *driver) Halt() error { + d.mutex.Lock() + defer d.mutex.Unlock() + + // currently there is nothing to do after halt for the driver + + return d.beforeHalt() +} + +// apply change the name in the configuration. +func (o nameOption) apply(c *configuration) { + c.name = string(o) +} diff --git a/drivers/aio/aio_driver_test.go b/drivers/aio/aio_driver_test.go new file mode 100644 index 000000000..10fdc47a0 --- /dev/null +++ b/drivers/aio/aio_driver_test.go @@ -0,0 +1,69 @@ +package aio + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2" +) + +var _ gobot.Driver = (*driver)(nil) + +func initTestDriver() *driver { + a := newAioTestAdaptor() + d := newDriver(a, "AIO_BASIC") + return d +} + +func Test_newDriver(t *testing.T) { + // arrange + const name = "mybot" + a := newAioTestAdaptor() + // act + d := newDriver(a, name) + // assert + assert.IsType(t, &driver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), name)) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) +} + +func Test_applyWithName(t *testing.T) { + // arrange + const name = "mybot" + cfg := configuration{name: "oldname"} + // act + WithName(name).apply(&cfg) + // assert + assert.Equal(t, name, cfg.name) +} + +func TestStart(t *testing.T) { + // arrange + d := initTestDriver() + // act, assert + require.NoError(t, d.Start()) + // arrange after start function + d.afterStart = func() error { return fmt.Errorf("after start error") } + // act, assert + require.EqualError(t, d.Start(), "after start error") +} + +func TestHalt(t *testing.T) { + // arrange + d := initTestDriver() + // act, assert + require.NoError(t, d.Halt()) + // arrange after start function + d.beforeHalt = func() error { return fmt.Errorf("before halt error") } + // act, assert + require.EqualError(t, d.Halt(), "before halt error") +} diff --git a/drivers/aio/analog_actuator_driver.go b/drivers/aio/analog_actuator_driver.go index bc6a3eb88..ef2f6d780 100644 --- a/drivers/aio/analog_actuator_driver.go +++ b/drivers/aio/analog_actuator_driver.go @@ -1,39 +1,63 @@ package aio import ( - "log" + "fmt" "strconv" - - "gobot.io/x/gobot/v2" ) +// actuatorOptionApplier needs to be implemented by each configurable option type +type actuatorOptionApplier interface { + apply(cfg *actuatorConfiguration) +} + +// actuatorConfiguration contains all changeable attributes of the driver. +type actuatorConfiguration struct { + scale func(input float64) (value int) +} + +// actuatorScaleOption is the type for applying another scaler to the configuration +type actuatorScaleOption struct { + scaler func(input float64) (value int) +} + // AnalogActuatorDriver represents an analog actuator type AnalogActuatorDriver struct { - name string - pin string - connection AnalogWriter - gobot.Eventer - gobot.Commander - scale func(input float64) (value int) + *driver + pin string + actuatorCfg *actuatorConfiguration lastValue float64 lastRawValue int } -// NewAnalogActuatorDriver returns a new AnalogActuatorDriver given by an AnalogWriter and pin. +// NewAnalogActuatorDriver returns a new driver for analog actuator, given by an AnalogWriter and pin. // The driver supports customizable scaling from given float64 value to written int. // The default scaling is 1:1. An adjustable linear scaler is provided by the driver. // +// Supported options: +// +// "WithName" +// "WithActuatorScaler" +// // Adds the following API Commands: // // "Write" - See AnalogActuator.Write -// "RawWrite" - See AnalogActuator.RawWrite -func NewAnalogActuatorDriver(a AnalogWriter, pin string) *AnalogActuatorDriver { +// "WriteRaw" - See AnalogActuator.WriteRaw +func NewAnalogActuatorDriver(a AnalogWriter, pin string, opts ...interface{}) *AnalogActuatorDriver { d := &AnalogActuatorDriver{ - name: gobot.DefaultName("AnalogActuator"), - connection: a, - pin: pin, - Commander: gobot.NewCommander(), - scale: func(input float64) int { return int(input) }, + driver: newDriver(a, "AnalogActuator"), + pin: pin, + actuatorCfg: &actuatorConfiguration{scale: func(input float64) int { return int(input) }}, + } + + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case actuatorOptionApplier: + o.apply(d.actuatorCfg) + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } } d.AddCommand("Write", func(params map[string]interface{}) interface{} { @@ -44,55 +68,66 @@ func NewAnalogActuatorDriver(a AnalogWriter, pin string) *AnalogActuatorDriver { return d.Write(val) }) - d.AddCommand("RawWrite", func(params map[string]interface{}) interface{} { + d.AddCommand("WriteRaw", func(params map[string]interface{}) interface{} { val, _ := strconv.Atoi(params["val"].(string)) - return d.RawWrite(val) + return d.WriteRaw(val) }) return d } -// Start starts driver -func (a *AnalogActuatorDriver) Start() error { return nil } - -// Halt is for halt -func (a *AnalogActuatorDriver) Halt() error { return nil } +// WithActuatorScaler substitute the default 1:1 return value function by a new scaling function +func WithActuatorScaler(scaler func(input float64) (value int)) actuatorOptionApplier { + return actuatorScaleOption{scaler: scaler} +} -// Name returns the drivers name -func (a *AnalogActuatorDriver) Name() string { return a.name } +// SetScaler substitute the default 1:1 return value function by a new scaling function +// If the scaler is not changed after initialization, prefer to use [aio.WithActuatorScaler] instead. +func (a *AnalogActuatorDriver) SetScaler(scaler func(float64) int) { + a.mutex.Lock() + defer a.mutex.Unlock() -// SetName sets the drivers name -func (a *AnalogActuatorDriver) SetName(n string) { a.name = n } + WithActuatorScaler(scaler).apply(a.actuatorCfg) +} // Pin returns the drivers pin func (a *AnalogActuatorDriver) Pin() string { return a.pin } -// Connection returns the drivers Connection -func (a *AnalogActuatorDriver) Connection() gobot.Connection { - if conn, ok := a.connection.(gobot.Connection); ok { - return conn - } +// Write writes the given value to the actuator +func (a *AnalogActuatorDriver) Write(val float64) error { + a.mutex.Lock() + defer a.mutex.Unlock() - log.Printf("%s has no gobot connection\n", a.name) + rawValue := a.actuatorCfg.scale(val) + if err := a.WriteRaw(rawValue); err != nil { + return err + } + a.lastValue = val return nil } // RawWrite write the given raw value to the actuator +// Deprecated: Please use [aio.WriteRaw] instead. func (a *AnalogActuatorDriver) RawWrite(val int) error { - a.lastRawValue = val - return a.connection.AnalogWrite(a.Pin(), val) + return a.WriteRaw(val) } -// SetScaler substitute the default 1:1 return value function by a new scaling function -func (a *AnalogActuatorDriver) SetScaler(scaler func(float64) int) { - a.scale = scaler +// WriteRaw write the given raw value to the actuator +func (a *AnalogActuatorDriver) WriteRaw(val int) error { + writer, ok := a.connection.(AnalogWriter) + if !ok { + return fmt.Errorf("AnalogWrite is not supported by the platform '%s'", a.Connection().Name()) + } + if err := writer.AnalogWrite(a.Pin(), val); err != nil { + return err + } + a.lastRawValue = val + return nil } -// Write writes the given value to the actuator -func (a *AnalogActuatorDriver) Write(val float64) error { - a.lastValue = val - rawValue := a.scale(val) - return a.RawWrite(rawValue) +// Value returns the last written value +func (a *AnalogActuatorDriver) Value() float64 { + return a.lastValue } // RawValue returns the last written raw value @@ -100,9 +135,12 @@ func (a *AnalogActuatorDriver) RawValue() int { return a.lastRawValue } -// Value returns the last written value -func (a *AnalogActuatorDriver) Value() float64 { - return a.lastValue +func (o actuatorScaleOption) String() string { + return "scaler option for analog actuators" +} + +func (o actuatorScaleOption) apply(cfg *actuatorConfiguration) { + cfg.scale = o.scaler } // AnalogActuatorLinearScaler creates a linear scaler function from the given values. diff --git a/drivers/aio/analog_actuator_driver_test.go b/drivers/aio/analog_actuator_driver_test.go index 88e3d22ce..3abe91f3f 100644 --- a/drivers/aio/analog_actuator_driver_test.go +++ b/drivers/aio/analog_actuator_driver_test.go @@ -1,106 +1,164 @@ +//nolint:forcetypeassert // ok here package aio import ( "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestAnalogActuatorDriver(t *testing.T) { +func TestNewAnalogActuatorDriver(t *testing.T) { + // arrange + const pin = "47" a := newAioTestAdaptor() - d := NewAnalogActuatorDriver(a, "47") - - assert.NotNil(t, d.Connection()) - assert.Equal(t, "47", d.Pin()) - - err := d.RawWrite(100) - require.NoError(t, err) - assert.Len(t, a.written, 1) - assert.Equal(t, 100, a.written[0]) - - err = d.Write(247.0) - require.NoError(t, err) - assert.Len(t, a.written, 2) - assert.Equal(t, 247, a.written[1]) - assert.Equal(t, 247, d.RawValue()) - assert.InDelta(t, 247.0, d.Value(), 0.0) + // act + d := NewAnalogActuatorDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &AnalogActuatorDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "AnalogActuator")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: actuator attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + require.NotNil(t, d.actuatorCfg) + assert.NotNil(t, d.actuatorCfg.scale) } -func TestAnalogActuatorDriverWithScaler(t *testing.T) { - // commands - a := newAioTestAdaptor() - d := NewAnalogActuatorDriver(a, "7") - d.SetScaler(func(input float64) int { return int((input + 3) / 2.5) }) - - err := d.Command("RawWrite")(map[string]interface{}{"val": "100"}) - assert.Nil(t, err) - assert.Len(t, a.written, 1) - assert.Equal(t, 100, a.written[0]) - - err = d.Command("Write")(map[string]interface{}{"val": "247.0"}) - assert.Nil(t, err) - assert.Len(t, a.written, 2) - assert.Equal(t, 100, a.written[1]) +func TestNewAnalogActuatorDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + myName := "relay 1" + myScaler := func(input float64) int { return int(2 * input) } + panicFunc := func() { + NewAnalogActuatorDriver(newAioTestAdaptor(), "1", WithName("crazy"), WithSensorCyclicRead(10*time.Millisecond)) + } + // act + d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1", WithName(myName), WithActuatorScaler(myScaler)) + // assert + assert.Equal(t, myName, d.Name()) + assert.Equal(t, 3, d.actuatorCfg.scale(1.5)) + assert.PanicsWithValue(t, "'read interval option for analog sensors' can not be applied on 'crazy'", panicFunc) } -func TestAnalogActuatorDriverLinearScaler(t *testing.T) { +func TestAnalogActuatorWriteRaw(t *testing.T) { tests := map[string]struct { - fromMin float64 - fromMax float64 - input float64 - want int + inputVal int + simulateWriteErr bool + wantWritten int + wantErr string }{ - "byte_range_min": {fromMin: 0, fromMax: 255, input: 0, want: 0}, - "byte_range_max": {fromMin: 0, fromMax: 255, input: 255, want: 255}, - "signed_percent_range_min": {fromMin: -100, fromMax: 100, input: -100, want: 0}, - "signed_percent_range_mid": {fromMin: -100, fromMax: 100, input: 0, want: 127}, - "signed_percent_range_max": {fromMin: -100, fromMax: 100, input: 100, want: 255}, - "voltage_range_min": {fromMin: 0, fromMax: 5.1, input: 0, want: 0}, - "voltage_range_nearmin": {fromMin: 0, fromMax: 5.1, input: 0.02, want: 1}, - "voltage_range_mid": {fromMin: 0, fromMax: 5.1, input: 2.55, want: 127}, - "voltage_range_nearmax": {fromMin: 0, fromMax: 5.1, input: 5.08, want: 254}, - "voltage_range_max": {fromMin: 0, fromMax: 5.1, input: 5.1, want: 255}, - "upscale": {fromMin: 0, fromMax: 24, input: 12, want: 127}, - "below_min": {fromMin: -10, fromMax: 10, input: -11, want: 0}, - "exceed_max": {fromMin: 0, fromMax: 20, input: 21, want: 255}, + "write_raw": {inputVal: 100, wantWritten: 100}, + "error_write": {inputVal: 12345, wantWritten: 12345, simulateWriteErr: true, wantErr: "write error"}, } - a := newAioTestAdaptor() - d := NewAnalogActuatorDriver(a, "7") - - for name, tt := range tests { + for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - d.SetScaler(AnalogActuatorLinearScaler(tt.fromMin, tt.fromMax, 0, 255)) - a.written = []int{} // reset previous write + const pin = "47" + a := newAioTestAdaptor() + d := NewAnalogActuatorDriver(a, pin) + a.simulateWriteError = tc.simulateWriteErr + a.written = nil // reset previous writes // act - err := d.Write(tt.input) + err := d.WriteRaw(tc.inputVal) // assert - require.NoError(t, err) - assert.Len(t, a.written, 1) - assert.Equal(t, tt.want, a.written[0]) + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + assert.Empty(t, a.written) + } else { + require.NoError(t, err) + assert.Len(t, a.written, 1) + assert.Equal(t, pin, a.written[0].pin) + assert.Equal(t, tc.wantWritten, a.written[0].val) + } }) } } -func TestAnalogActuatorDriverStart(t *testing.T) { +func TestAnalogActuatorWriteRaw_AnalogWriteNotSupported(t *testing.T) { + // arrange d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - require.NoError(t, d.Start()) + d.connection = &aioTestBareAdaptor{} + // act & assert + require.EqualError(t, d.WriteRaw(3), "AnalogWrite is not supported by the platform 'bare'") } -func TestAnalogActuatorDriverHalt(t *testing.T) { - d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - require.NoError(t, d.Halt()) -} +func TestAnalogActuatorWrite_SetScaler(t *testing.T) { + tests := map[string]struct { + fromMin float64 + fromMax float64 + input float64 + wantWritten int + }{ + "byte_range_min": {fromMin: 0, fromMax: 255, input: 0, wantWritten: 0}, + "byte_range_max": {fromMin: 0, fromMax: 255, input: 255, wantWritten: 255}, + "signed_percent_range_min": {fromMin: -100, fromMax: 100, input: -100, wantWritten: 0}, + "signed_percent_range_mid": {fromMin: -100, fromMax: 100, input: 0, wantWritten: 127}, + "signed_percent_range_max": {fromMin: -100, fromMax: 100, input: 100, wantWritten: 255}, + "voltage_range_min": {fromMin: 0, fromMax: 5.1, input: 0, wantWritten: 0}, + "voltage_range_nearmin": {fromMin: 0, fromMax: 5.1, input: 0.02, wantWritten: 1}, + "voltage_range_mid": {fromMin: 0, fromMax: 5.1, input: 2.55, wantWritten: 127}, + "voltage_range_nearmax": {fromMin: 0, fromMax: 5.1, input: 5.08, wantWritten: 254}, + "voltage_range_max": {fromMin: 0, fromMax: 5.1, input: 5.1, wantWritten: 255}, + "upscale": {fromMin: 0, fromMax: 24, input: 12, wantWritten: 127}, + "below_min": {fromMin: -10, fromMax: 10, input: -11, wantWritten: 0}, + "exceed_max": {fromMin: 0, fromMax: 20, input: 21, wantWritten: 255}, + } -func TestAnalogActuatorDriverDefaultName(t *testing.T) { - d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - assert.True(t, strings.HasPrefix(d.Name(), "AnalogActuator")) + const pin = "7" + a := newAioTestAdaptor() + d := NewAnalogActuatorDriver(a, pin) + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d.SetScaler(AnalogActuatorLinearScaler(tc.fromMin, tc.fromMax, 0, 255)) + a.written = nil // reset previous writes + // act + err := d.Write(tc.input) + // assert + require.NoError(t, err) + assert.Len(t, a.written, 1) + assert.Equal(t, pin, a.written[0].pin) + assert.Equal(t, tc.wantWritten, a.written[0].val) + }) + } } -func TestAnalogActuatorDriverSetName(t *testing.T) { - d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) +func TestAnalogActuatorCommands_WithActuatorScaler(t *testing.T) { + // arrange + const pin = "8" + a := newAioTestAdaptor() + d := NewAnalogActuatorDriver(a, pin, WithActuatorScaler(func(input float64) int { return int((input + 3) / 2.5) })) + a.written = nil // reset previous writes + // act & assert: WriteRaw + err := d.Command("WriteRaw")(map[string]interface{}{"val": "100"}) + assert.Nil(t, err) + assert.Len(t, a.written, 1) + assert.Equal(t, pin, a.written[0].pin) + assert.Equal(t, 100, a.written[0].val) + assert.Equal(t, 100, d.RawValue()) + assert.InDelta(t, 0.0, d.Value(), 0.0) + // act & assert: Write + err = d.Command("Write")(map[string]interface{}{"val": "247.0"}) + assert.Nil(t, err) + assert.Len(t, a.written, 2) + assert.Equal(t, pin, a.written[1].pin) + assert.Equal(t, 100, a.written[1].val) + assert.Equal(t, 100, d.RawValue()) + assert.InDelta(t, 247.0, d.Value(), 0.0) + // arrange & act & assert: Write with error + a.simulateWriteError = true + err = d.Command("Write")(map[string]interface{}{"val": "247.0"}) + require.EqualError(t, err.(error), "write error") } diff --git a/drivers/aio/analog_sensor_driver.go b/drivers/aio/analog_sensor_driver.go index 7e9059ad3..37a7fefbb 100644 --- a/drivers/aio/analog_sensor_driver.go +++ b/drivers/aio/analog_sensor_driver.go @@ -1,56 +1,79 @@ package aio import ( - "log" - "sync" + "fmt" "time" "gobot.io/x/gobot/v2" ) +// sensorOptionApplier needs to be implemented by each configurable option type +type sensorOptionApplier interface { + apply(cfg *sensorConfiguration) +} + +// sensorConfiguration contains all changeable attributes of the driver. +type sensorConfiguration struct { + readInterval time.Duration + scale func(input int) (value float64) +} + +// sensorReadIntervalOption is the type for applying another read interval to the configuration +type sensorReadIntervalOption time.Duration + +// sensorScaleOption is the type for applying another scaler to the configuration +type sensorScaleOption struct { + scaler func(input int) (value float64) +} + // AnalogSensorDriver represents an Analog Sensor type AnalogSensorDriver struct { - name string - pin string - halt chan bool - interval time.Duration - connection AnalogReader + *driver + sensorCfg *sensorConfiguration + pin string + halt chan bool gobot.Eventer - gobot.Commander - rawValue int - value float64 - scale func(input int) (value float64) - mutex *sync.Mutex // to prevent data race between cyclic and single shot write/read to values and scaler + lastRawValue int + lastValue float64 } -// NewAnalogSensorDriver returns a new AnalogSensorDriver with a polling interval of -// 10 Milliseconds given an AnalogReader and pin. -// The driver supports customizable scaling from read int value to returned float64. +// NewAnalogSensorDriver returns a new driver for analog sensors, given an AnalogReader and pin. +// The driver supports cyclic reading and customizable scaling from read int value to returned float64. // The default scaling is 1:1. An adjustable linear scaler is provided by the driver. // -// Optionally accepts: +// Supported options: // -// time.Duration: Interval at which the AnalogSensor is polled for new information +// "WithName" +// "WithSensorCyclicRead" +// "WithSensorScaler" // // Adds the following API Commands: // // "Read" - See AnalogDriverSensor.Read // "ReadRaw" - See AnalogDriverSensor.ReadRaw -func NewAnalogSensorDriver(a AnalogReader, pin string, v ...time.Duration) *AnalogSensorDriver { +func NewAnalogSensorDriver(a AnalogReader, pin string, opts ...interface{}) *AnalogSensorDriver { d := &AnalogSensorDriver{ - name: gobot.DefaultName("AnalogSensor"), - connection: a, - pin: pin, - Eventer: gobot.NewEventer(), - Commander: gobot.NewCommander(), - interval: 10 * time.Millisecond, - halt: make(chan bool), - scale: func(input int) float64 { return float64(input) }, - mutex: &sync.Mutex{}, + driver: newDriver(a, "AnalogSensor"), + sensorCfg: &sensorConfiguration{scale: func(input int) float64 { return float64(input) }}, + pin: pin, + Eventer: gobot.NewEventer(), + halt: make(chan bool), } - - if len(v) > 0 { - d.interval = v[0] + d.afterStart = d.initialize + d.beforeHalt = d.shutdown + + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case sensorOptionApplier: + o.apply(d.sensorCfg) + case time.Duration: + // TODO this is only for backward compatibility and will be removed after version 2.x + d.sensorCfg.readInterval = o + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } } d.AddEvent(Data) @@ -70,21 +93,40 @@ func NewAnalogSensorDriver(a AnalogReader, pin string, v ...time.Duration) *Anal return d } -// Start starts the AnalogSensorDriver and reads the sensor at the given interval. +// WithSensorCyclicRead add a asynchronous cyclic reading functionality to the sensor with the given read interval. +func WithSensorCyclicRead(interval time.Duration) sensorOptionApplier { + return sensorReadIntervalOption(interval) +} + +// WithSensorScaler substitute the default 1:1 return value function by a new scaling function +func WithSensorScaler(scaler func(input int) (value float64)) sensorOptionApplier { + return sensorScaleOption{scaler: scaler} +} + +// SetScaler substitute the default 1:1 return value function by a new scaling function +// If the scaler is not changed after initialization, prefer to use [aio.WithSensorScaler] instead. +func (a *AnalogSensorDriver) SetScaler(scaler func(int) float64) { + a.mutex.Lock() + defer a.mutex.Unlock() + + WithSensorScaler(scaler).apply(a.sensorCfg) +} + +// initialize the AnalogSensorDriver and if the cyclic reading is active, reads the sensor at the given interval. // Emits the Events: // // Data int - Event is emitted on change and represents the current raw reading from the sensor. // Value float64 - Event is emitted on change and represents the current reading from the sensor. // Error error - Event is emitted on error reading from the sensor. -func (a *AnalogSensorDriver) Start() error { - if a.interval == 0 { +func (a *AnalogSensorDriver) initialize() error { + if a.sensorCfg.readInterval == 0 { // cyclic reading deactivated return nil } oldRawValue := 0 oldValue := 0.0 go func() { - timer := time.NewTimer(a.interval) + timer := time.NewTimer(a.sensorCfg.readInterval) timer.Stop() for { rawValue, value, err := a.analogRead() @@ -101,7 +143,7 @@ func (a *AnalogSensorDriver) Start() error { } } - timer.Reset(a.interval) + timer.Reset(a.sensorCfg.readInterval) select { case <-timer.C: case <-a.halt: @@ -113,9 +155,9 @@ func (a *AnalogSensorDriver) Start() error { return nil } -// Halt stops polling the analog sensor for new information -func (a *AnalogSensorDriver) Halt() error { - if a.interval == 0 { +// shutdown stops polling the analog sensor for new information +func (a *AnalogSensorDriver) shutdown() error { + if a.sensorCfg.readInterval == 0 { // cyclic reading deactivated return nil } @@ -123,25 +165,9 @@ func (a *AnalogSensorDriver) Halt() error { return nil } -// Name returns the AnalogSensorDrivers name -func (a *AnalogSensorDriver) Name() string { return a.name } - -// SetName sets the AnalogSensorDrivers name -func (a *AnalogSensorDriver) SetName(n string) { a.name = n } - // Pin returns the AnalogSensorDrivers pin func (a *AnalogSensorDriver) Pin() string { return a.pin } -// Connection returns the AnalogSensorDrivers Connection -func (a *AnalogSensorDriver) Connection() gobot.Connection { - if conn, ok := a.connection.(gobot.Connection); ok { - return conn - } - - log.Printf("%s has no gobot connection\n", a.name) - return nil -} - // Read returns the current reading from the sensor, scaled by the current scaler func (a *AnalogSensorDriver) Read() (float64, error) { _, value, err := a.analogRead() @@ -154,20 +180,12 @@ func (a *AnalogSensorDriver) ReadRaw() (int, error) { return rawValue, err } -// SetScaler substitute the default 1:1 return value function by a new scaling function -func (a *AnalogSensorDriver) SetScaler(scaler func(int) float64) { - a.mutex.Lock() - defer a.mutex.Unlock() - - a.scale = scaler -} - // Value returns the last read value from the sensor func (a *AnalogSensorDriver) Value() float64 { a.mutex.Lock() defer a.mutex.Unlock() - return a.value + return a.lastValue } // RawValue returns the last read raw value from the sensor @@ -175,7 +193,7 @@ func (a *AnalogSensorDriver) RawValue() int { a.mutex.Lock() defer a.mutex.Unlock() - return a.rawValue + return a.lastRawValue } // analogRead performs an reading from the sensor and sets the internal attributes and returns the raw and scaled value @@ -183,14 +201,35 @@ func (a *AnalogSensorDriver) analogRead() (int, float64, error) { a.mutex.Lock() defer a.mutex.Unlock() - rawValue, err := a.connection.AnalogRead(a.Pin()) + reader, ok := a.connection.(AnalogReader) + if !ok { + return 0, 0, fmt.Errorf("AnalogRead is not supported by the platform '%s'", a.Connection().Name()) + } + + rawValue, err := reader.AnalogRead(a.Pin()) if err != nil { return 0, 0, err } - a.rawValue = rawValue - a.value = a.scale(a.rawValue) - return a.rawValue, a.value, nil + a.lastRawValue = rawValue + a.lastValue = a.sensorCfg.scale(a.lastRawValue) + return a.lastRawValue, a.lastValue, nil +} + +func (o sensorReadIntervalOption) String() string { + return "read interval option for analog sensors" +} + +func (o sensorScaleOption) String() string { + return "scaler option for analog sensors" +} + +func (o sensorReadIntervalOption) apply(cfg *sensorConfiguration) { + cfg.readInterval = time.Duration(o) +} + +func (o sensorScaleOption) apply(cfg *sensorConfiguration) { + cfg.scale = o.scaler } // AnalogSensorLinearScaler creates a linear scaler function from the given values. diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index 3f782e3b9..ddb004984 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -2,7 +2,7 @@ package aio import ( - "errors" + "fmt" "strings" "testing" "time" @@ -15,48 +15,104 @@ import ( var _ gobot.Driver = (*AnalogSensorDriver)(nil) -func TestAnalogSensorDriver(t *testing.T) { +func TestNewAnalogSensorDriver(t *testing.T) { + // arrange + const pin = "5" a := newAioTestAdaptor() - d := NewAnalogSensorDriver(a, "1") - assert.NotNil(t, d.Connection()) - - // default interval - assert.Equal(t, 10*time.Millisecond, d.interval) - - // commands - a = newAioTestAdaptor() - d = NewAnalogSensorDriver(a, "42", 30*time.Second) - d.SetScaler(func(input int) float64 { return 2.5*float64(input) - 3 }) - assert.Equal(t, "42", d.Pin()) - assert.Equal(t, 30*time.Second, d.interval) + // act + d := NewAnalogSensorDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &AnalogSensorDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "AnalogSensor")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: sensor attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + assert.NotNil(t, d.halt) + assert.NotNil(t, d.Eventer) + require.NotNil(t, d.sensorCfg) + assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) + assert.NotNil(t, d.sensorCfg.scale) +} - a.analogReadFunc = func() (int, error) { - return 100, nil +func TestNewAnalogSensorDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "voltage 1" + cycReadDur = 10 * time.Millisecond + ) + panicFunc := func() { + NewAnalogSensorDriver(newAioTestAdaptor(), "1", WithName("crazy"), WithActuatorScaler(func(float64) int { return 0 })) } + // act + d := NewAnalogSensorDriver(newAioTestAdaptor(), "1", WithName(myName), WithSensorCyclicRead(cycReadDur)) + // assert + assert.Equal(t, cycReadDur, d.sensorCfg.readInterval) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} - ret := d.Command("ReadRaw")(nil).(map[string]interface{}) - assert.Equal(t, 100, ret["val"].(int)) - assert.Nil(t, ret["err"]) - - ret = d.Command("Read")(nil).(map[string]interface{}) - assert.InDelta(t, 247.0, ret["val"].(float64), 0.0) - assert.Nil(t, ret["err"]) +func TestAnalogSensor_WithSensorScaler(t *testing.T) { + // arrange + myScaler := func(input int) float64 { return float64(input) / 2 } + cfg := sensorConfiguration{} + // act + WithSensorScaler(myScaler).apply(&cfg) + // assert + assert.InDelta(t, 1.5, cfg.scale(3), 0.0) +} - // refresh value on read - a = newAioTestAdaptor() - d = NewAnalogSensorDriver(a, "3") - a.analogReadFunc = func() (int, error) { - return 150, nil +func TestAnalogSensorDriverReadRaw(t *testing.T) { + tests := map[string]struct { + simulateReadErr bool + wantVal int + wantErr string + }{ + "read_raw": {wantVal: analogReadReturnValue}, + "error_read": {wantVal: 0, simulateReadErr: true, wantErr: "read error"}, } - assert.InDelta(t, 0.0, d.Value(), 0.0) - val, err := d.Read() - require.NoError(t, err) - assert.InDelta(t, 150.0, val, 0.0) - assert.InDelta(t, 150.0, d.Value(), 0.0) - assert.Equal(t, 150, d.RawValue()) + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + const pin = "47" + a := newAioTestAdaptor() + d := NewAnalogSensorDriver(a, pin) + a.simulateReadError = tc.simulateReadErr + a.written = nil // reset previous writes + // act + got, err := d.ReadRaw() + // assert + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + assert.Empty(t, a.written) + } else { + require.NoError(t, err) + } + assert.Equal(t, tc.wantVal, got) + }) + } +} + +func TestAnalogSensorDriverReadRaw_AnalogWriteNotSupported(t *testing.T) { + // arrange + d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") + d.connection = &aioTestBareAdaptor{} + // act & assert + got, err := d.ReadRaw() + require.EqualError(t, err, "AnalogRead is not supported by the platform 'bare'") + assert.Equal(t, 0, got) } -func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { +func TestAnalogSensorRead_SetScaler(t *testing.T) { // the input scales per default from 0...255 tests := map[string]struct { toMin float64 @@ -76,98 +132,113 @@ func TestAnalogSensorDriverWithLinearScaler(t *testing.T) { } a := newAioTestAdaptor() d := NewAnalogSensorDriver(a, "7") - for name, tt := range tests { + for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - d.SetScaler(AnalogSensorLinearScaler(0, 255, tt.toMin, tt.toMax)) + d.SetScaler(AnalogSensorLinearScaler(0, 255, tc.toMin, tc.toMax)) a.analogReadFunc = func() (int, error) { - return tt.input, nil + return tc.input, nil } // act got, err := d.Read() // assert require.NoError(t, err) - assert.InDelta(t, tt.want, got, 0.0) + assert.InDelta(t, tc.want, got, 0.0) }) } } -func TestAnalogSensorDriverStart(t *testing.T) { - sem := make(chan bool, 1) +func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) { + // arrange a := newAioTestAdaptor() - d := NewAnalogSensorDriver(a, "1") + d := NewAnalogSensorDriver(a, "1", WithSensorCyclicRead(10*time.Millisecond)) d.SetScaler(func(input int) float64 { return float64(input * input) }) + semData := make(chan bool) + semDone := make(chan bool) + nextVal := make(chan int) + readTimeout := 1 * time.Second + a.analogReadFunc = func() (int, error) { + val := 100 + var err error + select { + case val = <-nextVal: + if val < 0 { + err = fmt.Errorf("analog read error") + } + return val, err + default: + return val, nil + } + } - // expect data to be received + // arrange: expect raw value to be received _ = d.Once(d.Event(Data), func(data interface{}) { assert.Equal(t, 100, data.(int)) - sem <- true + semData <- true }) - _ = d.Once(d.Event(Value), func(data interface{}) { - assert.InDelta(t, 10000.0, data.(float64), 0.0) - sem <- true + // arrange: expect scaled value to be received + _ = d.Once(d.Event(Value), func(value interface{}) { + assert.InDelta(t, 10000.0, value.(float64), 0.0) + <-semData // wait for data is finished + semDone <- true + nextVal <- -1 // arrange: error in read function }) - // send data - a.analogReadFunc = func() (int, error) { - return 100, nil - } - + // act (start cyclic reading) require.NoError(t, d.Start()) + // assert: both events within timeout select { - case <-sem: - case <-time.After(1 * time.Second): + case <-semDone: + case <-time.After(readTimeout): t.Errorf("AnalogSensor Event \"Data\" was not published") } - // expect error to be received - _ = d.Once(d.Event(Error), func(data interface{}) { - assert.Equal(t, "read error", data.(error).Error()) - sem <- true + // arrange: for error to be received + _ = d.Once(d.Event(Error), func(err interface{}) { + assert.Equal(t, "analog read error", err.(error).Error()) + semDone <- true }) - // send error - a.analogReadFunc = func() (int, error) { - return 0, errors.New("read error") - } - + // assert: error select { - case <-sem: - case <-time.After(1 * time.Second): + case <-semDone: + case <-time.After(readTimeout): t.Errorf("AnalogSensor Event \"Error\" was not published") } - // send a halt message + // arrange: for halt message _ = d.Once(d.Event(Data), func(data interface{}) { - sem <- true + semData <- true }) - _ = d.Once(d.Event(Value), func(data interface{}) { - sem <- true + _ = d.Once(d.Event(Value), func(value interface{}) { + semDone <- true }) - a.analogReadFunc = func() (int, error) { - return 200, nil - } - + // act: send a halt message d.halt <- true + // assert: no event select { - case <-sem: - t.Errorf("AnalogSensor Event should not published") - case <-time.After(1 * time.Second): + case <-semData: + t.Errorf("AnalogSensor Event for data should not published") + case <-semDone: + t.Errorf("AnalogSensor Event for value should not published") + case <-time.After(readTimeout): } } -func TestAnalogSensorDriverHalt(t *testing.T) { - d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") +func TestAnalogSensorHalt_WithSensorCyclicRead(t *testing.T) { + // arrange + d := NewAnalogSensorDriver(newAioTestAdaptor(), "1", WithSensorCyclicRead(10*time.Millisecond)) done := make(chan struct{}) go func() { <-d.halt close(done) }() + // act & assert require.NoError(t, d.Halt()) select { case <-done: @@ -176,13 +247,25 @@ func TestAnalogSensorDriverHalt(t *testing.T) { } } -func TestAnalogSensorDriverDefaultName(t *testing.T) { - d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") - assert.True(t, strings.HasPrefix(d.Name(), "AnalogSensor")) -} - -func TestAnalogSensorDriverSetName(t *testing.T) { - d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) +func TestAnalogSensorCommands_WithSensorScaler(t *testing.T) { + // arrange + a := newAioTestAdaptor() + d := NewAnalogSensorDriver(a, "42", WithSensorScaler(func(input int) float64 { return 2.5*float64(input) - 3 })) + var readReturn int + a.analogReadFunc = func() (int, error) { + readReturn += 100 + return readReturn, nil + } + // act & assert: ReadRaw + ret := d.Command("ReadRaw")(nil).(map[string]interface{}) + assert.Equal(t, 100, ret["val"].(int)) + assert.Nil(t, ret["err"]) + assert.Equal(t, 100, d.RawValue()) + assert.InDelta(t, 247.0, d.Value(), 0.0) + // act & assert: Read + ret = d.Command("Read")(nil).(map[string]interface{}) + assert.InDelta(t, 497.0, ret["val"].(float64), 0.0) + assert.Nil(t, ret["err"]) + assert.Equal(t, 200, d.RawValue()) + assert.InDelta(t, 497.0, d.Value(), 0.0) } diff --git a/drivers/aio/grove_drivers.go b/drivers/aio/grove_drivers.go index 8d4783420..70feb84e9 100644 --- a/drivers/aio/grove_drivers.go +++ b/drivers/aio/grove_drivers.go @@ -1,28 +1,23 @@ package aio -import ( - "time" -) +import "gobot.io/x/gobot/v2" // 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. +// NewGroveRotaryDriver returns a new driver for grove rotary dial, 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...), +// Supported options: see [aio.NewAnalogSensorDriver] +// Adds the following API Commands: see [aio.NewAnalogSensorDriver] +func NewGroveRotaryDriver(a AnalogReader, pin string, opts ...interface{}) *GroveRotaryDriver { + d := GroveRotaryDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, pin, opts...), } + d.driverCfg.name = gobot.DefaultName("GroveRotary") + + return &d } // GroveLightSensorDriver represents an analog light sensor @@ -31,78 +26,66 @@ type GroveLightSensorDriver struct { *AnalogSensorDriver } -// NewGroveLightSensorDriver returns a new GroveLightSensorDriver with a polling interval of -// 10 Milliseconds given an AnalogReader and pin. -// -// Optionally accepts: +// NewGroveLightSensorDriver returns a new driver for grove light sensor, given an AnalogReader and pin. // -// 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...), +// Supported options: see [aio.NewAnalogSensorDriver] +// Adds the following API Commands: see [aio.NewAnalogSensorDriver] +func NewGroveLightSensorDriver(a AnalogReader, pin string, opts ...interface{}) *GroveLightSensorDriver { + d := GroveLightSensorDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, pin, opts...), } + d.driverCfg.name = gobot.DefaultName("GroveLightSensor") + + return &d } -// GrovePiezoVibrationSensorDriver represents an analog vibration sensor -// with a Grove connector +// 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. +// NewGrovePiezoVibrationSensorDriver returns a new driver for grove piezo vibration sensor, 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 +// Supported options: see [aio.NewAnalogSensorDriver] +// Adds the following API Commands: see [aio.NewAnalogSensorDriver] func NewGrovePiezoVibrationSensorDriver( a AnalogReader, pin string, - v ...time.Duration, + opts ...interface{}, ) *GrovePiezoVibrationSensorDriver { - sensor := &GrovePiezoVibrationSensorDriver{ - AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), + d := &GrovePiezoVibrationSensorDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, pin, opts...), } + d.driverCfg.name = gobot.DefaultName("GrovePiezoVibrationSensor") - sensor.AddEvent(Vibration) + d.AddEvent(Vibration) - if err := sensor.On(sensor.Event(Data), func(data interface{}) { + if err := d.On(d.Event(Data), func(data interface{}) { if data.(int) > 1000 { //nolint:forcetypeassert // no error return value, so there is no better way - sensor.Publish(sensor.Event(Vibration), data) + d.Publish(d.Event(Vibration), data) } }); err != nil { panic(err) } - return sensor + return d } -// GroveSoundSensorDriver represents a analog sound sensor -// with a Grove connector +// 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. +// NewGroveSoundSensorDriver returns a new driver for grove sound sensor, 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...), +// Supported options: see [aio.NewAnalogSensorDriver] +// Adds the following API Commands: see [aio.NewAnalogSensorDriver] +func NewGroveSoundSensorDriver(a AnalogReader, pin string, opts ...interface{}) *GroveSoundSensorDriver { + d := GroveSoundSensorDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, pin, opts...), } + d.driverCfg.name = gobot.DefaultName("GroveSoundSensor") + + return &d } diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go index a58502fd1..69cf35c93 100644 --- a/drivers/aio/grove_drivers_test.go +++ b/drivers/aio/grove_drivers_test.go @@ -4,6 +4,7 @@ package aio import ( "errors" "reflect" + "strings" "sync/atomic" "testing" "time" @@ -14,42 +15,125 @@ import ( "gobot.io/x/gobot/v2" ) -type DriverAndPinner interface { +type groveDriverTestDriverAndEventer interface { gobot.Driver - gobot.Pinner + gobot.Eventer } -type DriverAndEventer interface { - gobot.Driver - gobot.Eventer +func TestNewGroveRotaryDriver(t *testing.T) { + // arrange + a := newAioTestAdaptor() + pin := "456" + // act + d := NewGroveRotaryDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &GroveRotaryDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "GroveRotary")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: sensor attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + assert.NotNil(t, d.halt) + assert.NotNil(t, d.Eventer) + require.NotNil(t, d.sensorCfg) + assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) + assert.NotNil(t, d.sensorCfg.scale) } -func TestDriverDefaults(t *testing.T) { - testAdaptor := newAioTestAdaptor() +func TestNewGroveLightSensorDriver(t *testing.T) { + // arrange + a := newAioTestAdaptor() pin := "456" + // act + d := NewGroveLightSensorDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &GroveLightSensorDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "GroveLightSensor")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: sensor attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + assert.NotNil(t, d.halt) + assert.NotNil(t, d.Eventer) + require.NotNil(t, d.sensorCfg) + assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) + assert.NotNil(t, d.sensorCfg.scale) +} - drivers := []DriverAndPinner{ - NewGroveSoundSensorDriver(testAdaptor, pin), - NewGroveLightSensorDriver(testAdaptor, pin), - NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), - NewGroveRotaryDriver(testAdaptor, pin), - } +func TestNewGrovePiezoVibrationSensorDriver(t *testing.T) { + // arrange + a := newAioTestAdaptor() + pin := "456" + // act + d := NewGrovePiezoVibrationSensorDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &GrovePiezoVibrationSensorDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "GrovePiezoVibrationSensor")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: sensor attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + assert.NotNil(t, d.halt) + assert.NotNil(t, d.Eventer) + require.NotNil(t, d.sensorCfg) + assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) + assert.NotNil(t, d.sensorCfg.scale) +} - for _, driver := range drivers { - assert.Equal(t, testAdaptor, driver.Connection()) - assert.Equal(t, pin, driver.Pin()) - } +func TestNewGroveSoundSensorDriver(t *testing.T) { + // arrange + a := newAioTestAdaptor() + pin := "456" + // act + d := NewGroveSoundSensorDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &GroveSoundSensorDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "GroveSoundSensor")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: sensor attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + assert.NotNil(t, d.halt) + assert.NotNil(t, d.Eventer) + require.NotNil(t, d.sensorCfg) + assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) + assert.NotNil(t, d.sensorCfg.scale) } -func TestAnalogDriverHalt(t *testing.T) { +func TestGroveDriverHalt_WithSensorCyclicRead(t *testing.T) { + // arrange testAdaptor := newAioTestAdaptor() pin := "456" - drivers := []DriverAndEventer{ - NewGroveSoundSensorDriver(testAdaptor, pin), - NewGroveLightSensorDriver(testAdaptor, pin), - NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), - NewGroveRotaryDriver(testAdaptor, pin), + drivers := []groveDriverTestDriverAndEventer{ + NewGroveSoundSensorDriver(testAdaptor, pin, WithSensorCyclicRead(10*time.Millisecond)), + NewGroveLightSensorDriver(testAdaptor, pin, WithSensorCyclicRead(10*time.Millisecond)), + NewGrovePiezoVibrationSensorDriver(testAdaptor, pin, WithSensorCyclicRead(10*time.Millisecond)), + NewGroveRotaryDriver(testAdaptor, pin, WithSensorCyclicRead(10*time.Millisecond)), } for _, driver := range drivers { @@ -73,15 +157,16 @@ func TestAnalogDriverHalt(t *testing.T) { } } -func TestDriverPublishesError(t *testing.T) { +func TestGroveDriverWithSensorCyclicReadPublishesError(t *testing.T) { + // arrange testAdaptor := newAioTestAdaptor() pin := "456" - drivers := []DriverAndEventer{ - NewGroveSoundSensorDriver(testAdaptor, pin), - NewGroveLightSensorDriver(testAdaptor, pin), - NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), - NewGroveRotaryDriver(testAdaptor, pin), + drivers := []groveDriverTestDriverAndEventer{ + NewGroveSoundSensorDriver(testAdaptor, pin, WithSensorCyclicRead(10*time.Millisecond)), + NewGroveLightSensorDriver(testAdaptor, pin, WithSensorCyclicRead(10*time.Millisecond)), + NewGrovePiezoVibrationSensorDriver(testAdaptor, pin, WithSensorCyclicRead(10*time.Millisecond)), + NewGroveRotaryDriver(testAdaptor, pin, WithSensorCyclicRead(10*time.Millisecond)), } for _, driver := range drivers { @@ -102,7 +187,7 @@ func TestDriverPublishesError(t *testing.T) { select { case <-sem: case <-time.After(time.Second): - t.Errorf("%s Event \"Error\" was not published", getType(driver)) + t.Errorf("%s Event \"Error\" was not published", groveGetType(driver)) } // Cleanup @@ -110,7 +195,7 @@ func TestDriverPublishesError(t *testing.T) { } } -func getType(driver interface{}) string { +func groveGetType(driver interface{}) string { d := reflect.TypeOf(driver) if d.Kind() == reflect.Ptr { diff --git a/drivers/aio/grove_temperature_sensor_driver.go b/drivers/aio/grove_temperature_sensor_driver.go index f12e5132d..d30675906 100644 --- a/drivers/aio/grove_temperature_sensor_driver.go +++ b/drivers/aio/grove_temperature_sensor_driver.go @@ -1,39 +1,45 @@ package aio import ( + "fmt" "time" "gobot.io/x/gobot/v2" ) -var _ gobot.Driver = (*GroveTemperatureSensorDriver)(nil) - // GroveTemperatureSensorDriver represents a temperature sensor // The temperature is reported in degree Celsius type GroveTemperatureSensorDriver struct { *TemperatureSensorDriver } -// NewGroveTemperatureSensorDriver returns a new GroveTemperatureSensorDriver with a polling interval of -// 10 Milliseconds given an AnalogReader and pin. -// -// Optionally accepts: -// -// time.Duration: Interval at which the sensor is polled for new information (given 0 switch the polling off) +// NewGroveTemperatureSensorDriver returns a new driver for grove temperature sensor, given an AnalogReader and pin. // -// Adds the following API Commands: -// -// "Read" - See AnalogDriverSensor.Read -// "ReadValue" - See AnalogDriverSensor.ReadValue -func NewGroveTemperatureSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GroveTemperatureSensorDriver { - t := NewTemperatureSensorDriver(a, pin, v...) +// Supported options: see [aio.NewAnalogSensorDriver] +// Adds the following API Commands: see [aio.NewAnalogSensorDriver] +func NewGroveTemperatureSensorDriver(a AnalogReader, pin string, opts ...interface{}) *GroveTemperatureSensorDriver { + t := NewTemperatureSensorDriver(a, pin, opts...) ntc := TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3975} // Ohm, R25=10k t.SetNtcScaler(1023, 10000, false, ntc) // Ohm, reference value: 1023, series R: 10k d := &GroveTemperatureSensorDriver{ TemperatureSensorDriver: t, } - d.SetName(gobot.DefaultName("GroveTemperatureSensor")) + d.driverCfg.name = gobot.DefaultName("GroveTemperatureSensor") + + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case sensorOptionApplier: + o.apply(d.sensorCfg) + case time.Duration: + // TODO this is only for backward compatibility and will be removed after version 2.x + d.sensorCfg.readInterval = o + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } + } return d } diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index ebe27a278..1559d4f54 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -15,15 +15,54 @@ import ( var _ gobot.Driver = (*GroveTemperatureSensorDriver)(nil) -func TestGroveTemperatureSensorDriver(t *testing.T) { - testAdaptor := newAioTestAdaptor() - d := NewGroveTemperatureSensorDriver(testAdaptor, "123") - assert.Equal(t, testAdaptor, d.Connection()) - assert.Equal(t, "123", d.Pin()) - assert.Equal(t, 10*time.Millisecond, d.interval) +func TestNewGroveTemperatureSensorDriver(t *testing.T) { + // arrange + const pin = "123" + a := newAioTestAdaptor() + // act + d := NewGroveTemperatureSensorDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &GroveTemperatureSensorDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "GroveTemperatureSensor")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: sensor attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + assert.NotNil(t, d.halt) + assert.NotNil(t, d.Eventer) + require.NotNil(t, d.sensorCfg) + assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) + assert.NotNil(t, d.sensorCfg.scale) +} + +func TestNewGroveTemperatureSensorDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "inlet temperature" + cycReadDur = 10 * time.Millisecond + ) + panicFunc := func() { + NewGroveTemperatureSensorDriver(newAioTestAdaptor(), "1", WithName("crazy"), + WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewGroveTemperatureSensorDriver(newAioTestAdaptor(), "1", WithName(myName), WithSensorCyclicRead(cycReadDur)) + // assert + assert.Equal(t, cycReadDur, d.sensorCfg.readInterval) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } -func TestGroveTemperatureSensorDriverScaling(t *testing.T) { +func TestGroveTemperatureSensorRead_scaler(t *testing.T) { tests := map[string]struct { input int want float64 @@ -40,25 +79,26 @@ func TestGroveTemperatureSensorDriverScaling(t *testing.T) { } a := newAioTestAdaptor() d := NewGroveTemperatureSensorDriver(a, "54") - for name, tt := range tests { + for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange a.analogReadFunc = func() (int, error) { - return tt.input, nil + return tc.input, nil } // act got, err := d.Read() // assert require.NoError(t, err) - assert.InDelta(t, tt.want, got, 0.0) + assert.InDelta(t, tc.want, got, 0.0) }) } } -func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { - sem := make(chan bool, 1) +func TestGroveTemperatureSensor_publishesTemperatureInCelsius(t *testing.T) { + // arrange + sem := make(chan bool) a := newAioTestAdaptor() - d := NewGroveTemperatureSensorDriver(a, "1") + d := NewGroveTemperatureSensorDriver(a, "1", WithSensorCyclicRead(10*time.Millisecond)) a.analogReadFunc = func() (int, error) { return 585, nil @@ -67,18 +107,16 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) + + // act: start cyclic reading require.NoError(t, d.Start()) + // assert: value was published select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Grove Temperature Sensor Event \"Data\" was not published") + t.Errorf("Grove Temperature Sensor Event \"Value\" was not published") } assert.InDelta(t, 31.61532462352477, d.Temperature(), 0.0) } - -func TestGroveTempDriverDefaultName(t *testing.T) { - d := NewGroveTemperatureSensorDriver(newAioTestAdaptor(), "1") - assert.True(t, strings.HasPrefix(d.Name(), "GroveTemperatureSensor")) -} diff --git a/drivers/aio/helpers_test.go b/drivers/aio/helpers_test.go index af7013332..a91029dd5 100644 --- a/drivers/aio/helpers_test.go +++ b/drivers/aio/helpers_test.go @@ -1,14 +1,33 @@ package aio -import "sync" +import ( + "fmt" + "sync" +) + +const analogReadReturnValue = 99 + +type aioTestBareAdaptor struct{} + +func (t *aioTestBareAdaptor) Connect() error { return nil } +func (t *aioTestBareAdaptor) Finalize() error { return nil } +func (t *aioTestBareAdaptor) Name() string { return "bare" } +func (t *aioTestBareAdaptor) SetName(n string) {} + +type aioTestWritten struct { + pin string + val int +} type aioTestAdaptor struct { - name string - port string - mtx sync.Mutex - analogReadFunc func() (val int, err error) - analogWriteFunc func(val int) error - written []int + name string + written []aioTestWritten + simulateWriteError bool + simulateReadError bool + port string + mtx sync.Mutex + analogReadFunc func() (val int, err error) + analogWriteFunc func(val int) error } func newAioTestAdaptor() *aioTestAdaptor { @@ -16,7 +35,7 @@ func newAioTestAdaptor() *aioTestAdaptor { name: "aio_test_adaptor", port: "/dev/null", analogReadFunc: func() (int, error) { - return 99, nil + return analogReadReturnValue, nil }, analogWriteFunc: func(val int) error { return nil @@ -30,6 +49,11 @@ func newAioTestAdaptor() *aioTestAdaptor { func (t *aioTestAdaptor) AnalogRead(pin string) (int, error) { t.mtx.Lock() defer t.mtx.Unlock() + + if t.simulateReadError { + return 0, fmt.Errorf("read error") + } + return t.analogReadFunc() } @@ -37,7 +61,13 @@ func (t *aioTestAdaptor) AnalogRead(pin string) (int, error) { func (t *aioTestAdaptor) AnalogWrite(pin string, val int) error { t.mtx.Lock() defer t.mtx.Unlock() - t.written = append(t.written, val) + + if t.simulateWriteError { + return fmt.Errorf("write error") + } + + w := aioTestWritten{pin: pin, val: val} + t.written = append(t.written, w) return t.analogWriteFunc(val) } diff --git a/drivers/aio/temperature_sensor_driver.go b/drivers/aio/temperature_sensor_driver.go index 15953a04e..f415caa1d 100644 --- a/drivers/aio/temperature_sensor_driver.go +++ b/drivers/aio/temperature_sensor_driver.go @@ -1,6 +1,7 @@ package aio import ( + "fmt" "math" "time" @@ -25,24 +26,28 @@ type TemperatureSensorDriver struct { *AnalogSensorDriver } -// NewTemperatureSensorDriver is a gobot driver for analog temperature sensors -// with a polling interval 10 Milliseconds given an AnalogReader and pin. -// For further details please refer to AnalogSensorDriver. +// NewTemperatureSensorDriver is a driver for analog temperature sensors, given an AnalogReader and pin. // Linear scaling and NTC scaling is supported. // -// Optionally accepts: -// -// time.Duration: Interval at which the sensor is polled for new information (given 0 switch the polling off) -// -// Adds the following API Commands: -// -// "Read" - See AnalogDriverSensor.Read -// "ReadValue" - See AnalogDriverSensor.ReadValue -func NewTemperatureSensorDriver(a AnalogReader, pin string, v ...time.Duration) *TemperatureSensorDriver { - ad := NewAnalogSensorDriver(a, pin, v...) - - d := &TemperatureSensorDriver{AnalogSensorDriver: ad} - d.SetName(gobot.DefaultName("TemperatureSensor")) +// Supported options: see [aio.NewAnalogSensorDriver] +// Adds the following API Commands: see [aio.NewAnalogSensorDriver] +func NewTemperatureSensorDriver(a AnalogReader, pin string, opts ...interface{}) *TemperatureSensorDriver { + d := &TemperatureSensorDriver{AnalogSensorDriver: NewAnalogSensorDriver(a, pin)} + d.driverCfg.name = gobot.DefaultName("TemperatureSensor") + + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case sensorOptionApplier: + o.apply(d.sensorCfg) + case time.Duration: + // TODO this is only for backward compatibility and will be removed after version 2.x + d.sensorCfg.readInterval = o + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } + } return d } @@ -52,6 +57,7 @@ func NewTemperatureSensorDriver(a AnalogReader, pin string, v ...time.Duration) // If the thermistor is connected to ground, the reverse flag must be set to true. // This means the voltage decreases when temperature gets higher. // Currently no negative values for voltage are supported. +// If the scaler is not changed after initialization, prefer to use [aio.WithSensorScaler] instead. func (t *TemperatureSensorDriver) SetNtcScaler(vRef uint, rOhm uint, reverse bool, ntc TemperatureSensorNtcConf) { t.SetScaler(TemperatureSensorNtcScaler(vRef, rOhm, reverse, ntc)) } @@ -59,6 +65,7 @@ func (t *TemperatureSensorDriver) SetNtcScaler(vRef uint, rOhm uint, reverse boo // SetLinearScaler sets a function for linear scaling the read value. // This can be applied for some silicon based PTC sensors or e.g. PT100, // and in a small temperature range also for NTC. +// If the scaler is not changed after initialization, prefer to use [aio.WithSensorScaler] instead. func (t *TemperatureSensorDriver) SetLinearScaler(fromMin, fromMax int, toMin, toMax float64) { t.SetScaler(AnalogSensorLinearScaler(fromMin, fromMax, toMin, toMax)) } diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index f0977562a..1d2a30069 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -12,15 +12,54 @@ import ( "github.com/stretchr/testify/require" ) -func TestTemperatureSensorDriver(t *testing.T) { - testAdaptor := newAioTestAdaptor() - d := NewTemperatureSensorDriver(testAdaptor, "123") - assert.Equal(t, testAdaptor, d.Connection()) - assert.Equal(t, "123", d.Pin()) - assert.Equal(t, 10*time.Millisecond, d.interval) +func TestNewTemperatureSensorDriver(t *testing.T) { + // arrange + const pin = "123" + a := newAioTestAdaptor() + // act + d := NewTemperatureSensorDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &TemperatureSensorDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "TemperatureSensor")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: sensor attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + assert.NotNil(t, d.halt) + assert.NotNil(t, d.Eventer) + require.NotNil(t, d.sensorCfg) + assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) + assert.NotNil(t, d.sensorCfg.scale) +} + +func TestNewTemperatureSensorDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "outlet temperature" + cycReadDur = 10 * time.Millisecond + ) + panicFunc := func() { + NewTemperatureSensorDriver(newAioTestAdaptor(), "1", WithName("crazy"), + WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1", WithName(myName), WithSensorCyclicRead(cycReadDur)) + // assert + assert.Equal(t, cycReadDur, d.sensorCfg.readInterval) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } -func TestTemperatureSensorDriverNtcScaling(t *testing.T) { +func TestTemperatureSensorRead_NtcScaler(t *testing.T) { tests := map[string]struct { input int want float64 @@ -40,22 +79,22 @@ func TestTemperatureSensorDriverNtcScaling(t *testing.T) { d := NewTemperatureSensorDriver(a, "4") ntc1 := TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3950} // Ohm, R25=10k, B=3950 d.SetNtcScaler(255, 1000, true, ntc1) // Ohm, reference value: 3300, series R: 1k - for name, tt := range tests { + for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange a.analogReadFunc = func() (int, error) { - return tt.input, nil + return tc.input, nil } // act got, err := d.Read() // assert require.NoError(t, err) - assert.InDelta(t, tt.want, got, 0.0) + assert.InDelta(t, tc.want, got, 0.0) }) } } -func TestTemperatureSensorDriverLinearScaling(t *testing.T) { +func TestTemperatureSensorDriver_LinearScaler(t *testing.T) { tests := map[string]struct { input int want float64 @@ -74,25 +113,26 @@ func TestTemperatureSensorDriverLinearScaling(t *testing.T) { a := newAioTestAdaptor() d := NewTemperatureSensorDriver(a, "4") d.SetLinearScaler(-128, 127, -40, 100) - for name, tt := range tests { + for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange a.analogReadFunc = func() (int, error) { - return tt.input, nil + return tc.input, nil } // act got, err := d.Read() // assert require.NoError(t, err) - assert.InDelta(t, tt.want, got, 0.0) + assert.InDelta(t, tc.want, got, 0.0) }) } } -func TestTempSensorPublishesTemperatureInCelsius(t *testing.T) { - sem := make(chan bool, 1) +func TestTemperatureSensorPublishesTemperatureInCelsius(t *testing.T) { + // arrange + sem := make(chan bool) a := newAioTestAdaptor() - d := NewTemperatureSensorDriver(a, "1") + d := NewTemperatureSensorDriver(a, "1", WithSensorCyclicRead(10*time.Millisecond)) 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 @@ -114,10 +154,11 @@ func TestTempSensorPublishesTemperatureInCelsius(t *testing.T) { assert.InDelta(t, 31.61532462352477, d.Value(), 0.0) } -func TestTempSensorPublishesError(t *testing.T) { - sem := make(chan bool, 1) +func TestTemperatureSensorWithSensorCyclicReadPublishesError(t *testing.T) { + // arrange + sem := make(chan bool) a := newAioTestAdaptor() - d := NewTemperatureSensorDriver(a, "1") + d := NewTemperatureSensorDriver(a, "1", WithSensorCyclicRead(10*time.Millisecond)) // send error a.analogReadFunc = func() (int, error) { @@ -139,13 +180,15 @@ func TestTempSensorPublishesError(t *testing.T) { } } -func TestTempSensorHalt(t *testing.T) { - d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1") +func TestTemperatureSensorHalt_WithSensorCyclicRead(t *testing.T) { + // arrange + d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1", WithSensorCyclicRead(10*time.Millisecond)) done := make(chan struct{}) go func() { <-d.halt close(done) }() + // act & assert require.NoError(t, d.Halt()) select { case <-done: @@ -154,17 +197,6 @@ func TestTempSensorHalt(t *testing.T) { } } -func TestTempDriverDefaultName(t *testing.T) { - d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1") - assert.True(t, strings.HasPrefix(d.Name(), "TemperatureSensor")) -} - -func TestTempDriverSetName(t *testing.T) { - d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1") - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) -} - func TestTempDriver_initialize(t *testing.T) { tests := map[string]struct { input TemperatureSensorNtcConf @@ -203,14 +235,14 @@ func TestTempDriver_initialize(t *testing.T) { }, }, } - for name, tt := range tests { + for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - ntc := tt.input + ntc := tc.input // act ntc.initialize() // assert - assert.Equal(t, tt.want, ntc) + assert.Equal(t, tc.want, ntc) }) } } diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index f3626a185..f1486ff1a 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -59,7 +59,7 @@ func TestBuzzerDriverOnError(t *testing.T) { return errors.New("write error") } - require.ErrorContains(t, d.On(), "write error") + require.EqualError(t, d.On(), "write error") } func TestBuzzerDriverOffError(t *testing.T) { @@ -69,7 +69,7 @@ func TestBuzzerDriverOffError(t *testing.T) { return errors.New("write error") } - require.ErrorContains(t, d.Off(), "write error") + require.EqualError(t, d.Off(), "write error") } func TestBuzzerDriverToneError(t *testing.T) { @@ -79,5 +79,5 @@ func TestBuzzerDriverToneError(t *testing.T) { return errors.New("write error") } - require.ErrorContains(t, d.Tone(100, 0.01), "write error") + require.EqualError(t, d.Tone(100, 0.01), "write error") } diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index 1dccd9224..9512467f9 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -45,13 +45,13 @@ func TestDirectPinDriver(t *testing.T) { assert.Nil(t, ret["err"]) err = d.Command("DigitalWrite")(map[string]interface{}{"level": "1"}) - require.ErrorContains(t, err.(error), "write error") + require.EqualError(t, err.(error), "write error") err = d.Command("PwmWrite")(map[string]interface{}{"level": "1"}) - require.ErrorContains(t, err.(error), "write error") + require.EqualError(t, err.(error), "write error") err = d.Command("ServoWrite")(map[string]interface{}{"level": "1"}) - require.ErrorContains(t, err.(error), "write error") + require.EqualError(t, err.(error), "write error") } func TestDirectPinDriverStart(t *testing.T) { @@ -76,7 +76,7 @@ func TestDirectPinDriverOff(t *testing.T) { func TestDirectPinDriverOffNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - require.ErrorContains(t, d.Off(), "DigitalWrite is not supported by this platform") + require.EqualError(t, d.Off(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverOn(t *testing.T) { @@ -93,7 +93,7 @@ func TestDirectPinDriverOnError(t *testing.T) { func TestDirectPinDriverOnNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - require.ErrorContains(t, d.On(), "DigitalWrite is not supported by this platform") + require.EqualError(t, d.On(), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWrite(t *testing.T) { @@ -105,7 +105,7 @@ func TestDirectPinDriverDigitalWrite(t *testing.T) { func TestDirectPinDriverDigitalWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - require.ErrorContains(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") + require.EqualError(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") } func TestDirectPinDriverDigitalWriteError(t *testing.T) { @@ -124,7 +124,7 @@ func TestDirectPinDriverDigitalReadNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") _, e := d.DigitalRead() - require.ErrorContains(t, e, "DigitalRead is not supported by this platform") + require.EqualError(t, e, "DigitalRead is not supported by this platform") } func TestDirectPinDriverPwmWrite(t *testing.T) { @@ -136,7 +136,7 @@ func TestDirectPinDriverPwmWrite(t *testing.T) { func TestDirectPinDriverPwmWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - require.ErrorContains(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") + require.EqualError(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") } func TestDirectPinDriverPwmWriteError(t *testing.T) { @@ -153,7 +153,7 @@ func TestDirectPinDriverServoWrite(t *testing.T) { func TestDirectPinDriverServoWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") - require.ErrorContains(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") + require.EqualError(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") } func TestDirectPinDriverServoWriteError(t *testing.T) { diff --git a/drivers/gpio/gpio_driver_test.go b/drivers/gpio/gpio_driver_test.go index 7511a3caf..753c1fd55 100644 --- a/drivers/gpio/gpio_driver_test.go +++ b/drivers/gpio/gpio_driver_test.go @@ -62,7 +62,7 @@ func TestStart(t *testing.T) { // arrange after start function d.afterStart = func() error { return fmt.Errorf("after start error") } // act, assert - require.ErrorContains(t, d.Start(), "after start error") + require.EqualError(t, d.Start(), "after start error") } func TestHalt(t *testing.T) { @@ -73,5 +73,5 @@ func TestHalt(t *testing.T) { // arrange after start function d.beforeHalt = func() error { return fmt.Errorf("before halt error") } // act, assert - require.ErrorContains(t, d.Halt(), "before halt error") + require.EqualError(t, d.Halt(), "before halt error") } diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index a43778118..3fbd13f77 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -94,7 +94,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_4BITMODE, "13", "15", pins) - require.ErrorContains(t, d.Start(), "Initialization error") + require.EqualError(t, d.Start(), "Initialization error") pins = HD44780DataPin{ D0: "31", @@ -107,7 +107,7 @@ func TestHD44780DriverStartError(t *testing.T) { D7: "", } d = NewHD44780Driver(a, 2, 16, HD44780_8BITMODE, "13", "15", pins) - require.ErrorContains(t, d.Start(), "Initialization error") + require.EqualError(t, d.Start(), "Initialization error") } func TestHD44780DriverWrite(t *testing.T) { @@ -131,14 +131,14 @@ func TestHD44780DriverWriteError(t *testing.T) { return errors.New("write error") } _ = d.Start() - require.ErrorContains(t, d.Write("hello gobot"), "write error") + require.EqualError(t, d.Write("hello gobot"), "write error") d, a = initTestHD44780Driver8BitModeWithStubbedAdaptor() a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } _ = d.Start() - require.ErrorContains(t, d.Write("hello gobot"), "write error") + require.EqualError(t, d.Write("hello gobot"), "write error") } func TestHD44780DriverClear(t *testing.T) { @@ -159,10 +159,10 @@ func TestHD44780DriverSetCursor(t *testing.T) { func TestHD44780DriverSetCursorInvalid(t *testing.T) { d := initTestHD44780Driver() - require.ErrorContains(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") - require.ErrorContains(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") - require.ErrorContains(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") - require.ErrorContains(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") + require.EqualError(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") + require.EqualError(t, d.SetCursor(2, 3), "Invalid position value (2, 3), range (1, 15)") + require.EqualError(t, d.SetCursor(0, -1), "Invalid position value (0, -1), range (1, 15)") + require.EqualError(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") } func TestHD44780DriverDisplayOn(t *testing.T) { @@ -234,5 +234,5 @@ func TestHD44780DriverCreateChar(t *testing.T) { func TestHD44780DriverCreateCharError(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - require.ErrorContains(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") + require.EqualError(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") } diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index 0fef94b11..56bda0efa 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -41,16 +41,16 @@ func TestLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - require.ErrorContains(t, err.(error), "write error") + require.EqualError(t, err.(error), "write error") err = d.Command("On")(nil) - require.ErrorContains(t, err.(error), "write error") + require.EqualError(t, err.(error), "write error") err = d.Command("Off")(nil) - require.ErrorContains(t, err.(error), "write error") + require.EqualError(t, err.(error), "write error") err = d.Command("Brightness")(map[string]interface{}{"level": 100.0}) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") } func TestLedDriverStart(t *testing.T) { @@ -78,7 +78,7 @@ func TestLedDriverBrightness(t *testing.T) { a.pwmWriteFunc = func(string, byte) error { return errors.New("pwm error") } - require.ErrorContains(t, d.Brightness(150), "pwm error") + require.EqualError(t, d.Brightness(150), "pwm error") } func TestLEDDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index b4b057986..27d9870d1 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -45,16 +45,16 @@ func TestRgbLedDriver(t *testing.T) { } err = d.Command("Toggle")(nil) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") err = d.Command("On")(nil) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") err = d.Command("Off")(nil) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") err = d.Command("SetRGB")(map[string]interface{}{"r": 0xff, "g": 0xff, "b": 0xff}) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") } func TestRgbLedDriverStart(t *testing.T) { @@ -85,7 +85,7 @@ func TestRgbLedDriverSetLevel(t *testing.T) { a.pwmWriteFunc = func(string, byte) error { return errors.New("pwm error") } - require.ErrorContains(t, d.SetLevel("1", 150), "pwm error") + require.EqualError(t, d.SetLevel("1", 150), "pwm error") } func TestRgbLedDriverDefaultName(t *testing.T) { diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index ee05e932f..8efb5d751 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -32,16 +32,16 @@ func TestServoDriver(t *testing.T) { } err = d.Command("Min")(nil) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") err = d.Command("Center")(nil) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") err = d.Command("Max")(nil) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") err = d.Command("Move")(map[string]interface{}{"angle": 100.0}) - require.ErrorContains(t, err.(error), "pwm error") + require.EqualError(t, err.(error), "pwm error") } func TestServoDriverStart(t *testing.T) { diff --git a/drivers/i2c/ads1x15_driver_1015_test.go b/drivers/i2c/ads1x15_driver_1015_test.go index 5640a27aa..c06018a96 100644 --- a/drivers/i2c/ads1x15_driver_1015_test.go +++ b/drivers/i2c/ads1x15_driver_1015_test.go @@ -253,13 +253,13 @@ func TestADS1015_rawRead(t *testing.T) { // arrange channel := 0 channelOffset := 1 - for name, tt := range tests { + for name, tc := range tests { t.Run(name, func(t *testing.T) { a.written = []byte{} // reset writes of Start() and former test // arrange reads conversion := []uint8{0x00, 0x00} // a conversion is in progress noConversion := []uint8{0x80, 0x00} // no conversion in progress - returnRead := [3][]uint8{conversion, noConversion, tt.input} + returnRead := [3][]uint8{conversion, noConversion, tc.input} numCallsRead := 0 a.i2cReadImpl = func(b []byte) (int, error) { numCallsRead++ @@ -268,15 +268,15 @@ func TestADS1015_rawRead(t *testing.T) { return len(b), nil } // act - got, err := d.rawRead(channel, channelOffset, tt.gain, tt.dataRate) + got, err := d.rawRead(channel, channelOffset, tc.gain, tc.dataRate) // assert require.NoError(t, err) - assert.Equal(t, tt.want, got) + assert.Equal(t, tc.want, got) assert.Equal(t, 3, numCallsRead) assert.Len(t, a.written, 6) assert.Equal(t, uint8(ads1x15PointerConfig), a.written[0]) - assert.Equal(t, tt.wantConfig[0], a.written[1]) // MSByte: OS, MUX, PGA, MODE - assert.Equal(t, tt.wantConfig[1], a.written[2]) // LSByte: DR, COMP_* + assert.Equal(t, tc.wantConfig[0], a.written[1]) // MSByte: OS, MUX, PGA, MODE + assert.Equal(t, tc.wantConfig[1], a.written[2]) // LSByte: DR, COMP_* assert.Equal(t, uint8(ads1x15PointerConfig), a.written[3]) // first check for no conversion assert.Equal(t, uint8(ads1x15PointerConfig), a.written[4]) // second check for no conversion assert.Equal(t, uint8(ads1x15PointerConversion), a.written[5]) diff --git a/drivers/i2c/ads1x15_driver_1115_test.go b/drivers/i2c/ads1x15_driver_1115_test.go index bae7ced2e..ade8579fe 100644 --- a/drivers/i2c/ads1x15_driver_1115_test.go +++ b/drivers/i2c/ads1x15_driver_1115_test.go @@ -253,13 +253,13 @@ func TestADS1115_rawRead(t *testing.T) { // arrange channel := 0 channelOffset := 1 - for name, tt := range tests { + for name, tc := range tests { t.Run(name, func(t *testing.T) { a.written = []byte{} // reset writes of Start() and former test // arrange reads conversion := []uint8{0x00, 0x00} // a conversion is in progress noConversion := []uint8{0x80, 0x00} // no conversion in progress - returnRead := [3][]uint8{conversion, noConversion, tt.input} + returnRead := [3][]uint8{conversion, noConversion, tc.input} numCallsRead := 0 a.i2cReadImpl = func(b []byte) (int, error) { numCallsRead++ @@ -268,15 +268,15 @@ func TestADS1115_rawRead(t *testing.T) { return len(b), nil } // act - got, err := d.rawRead(channel, channelOffset, tt.gain, tt.dataRate) + got, err := d.rawRead(channel, channelOffset, tc.gain, tc.dataRate) // assert require.NoError(t, err) - assert.Equal(t, tt.want, got) + assert.Equal(t, tc.want, got) assert.Equal(t, 3, numCallsRead) assert.Len(t, a.written, 6) assert.Equal(t, uint8(ads1x15PointerConfig), a.written[0]) - assert.Equal(t, tt.wantConfig[0], a.written[1]) // MSByte: OS, MUX, PGA, MODE - assert.Equal(t, tt.wantConfig[1], a.written[2]) // LSByte: DR, COMP_* + assert.Equal(t, tc.wantConfig[0], a.written[1]) // MSByte: OS, MUX, PGA, MODE + assert.Equal(t, tc.wantConfig[1], a.written[2]) // LSByte: DR, COMP_* assert.Equal(t, uint8(ads1x15PointerConfig), a.written[3]) // first check for no conversion assert.Equal(t, uint8(ads1x15PointerConfig), a.written[4]) // second check for no conversion assert.Equal(t, uint8(ads1x15PointerConversion), a.written[5]) diff --git a/drivers/i2c/yl40_driver.go b/drivers/i2c/yl40_driver.go index b740150fe..f4a9addf3 100644 --- a/drivers/i2c/yl40_driver.go +++ b/drivers/i2c/yl40_driver.go @@ -127,20 +127,20 @@ func NewYL40Driver(a Connector, options ...func(Config)) *YL40Driver { } // initialize analog drivers - y.aBri = aio.NewAnalogSensorDriver(pcf, yl40Pins[YL40Bri], y.conf.sensors[YL40Bri].interval) - y.aTemp = aio.NewTemperatureSensorDriver(pcf, yl40Pins[YL40Temp], y.conf.sensors[YL40Temp].interval) - y.aAIN2 = aio.NewAnalogSensorDriver(pcf, yl40Pins[YL40AIN2], y.conf.sensors[YL40AIN2].interval) - y.aPoti = aio.NewAnalogSensorDriver(pcf, yl40Pins[YL40Poti], y.conf.sensors[YL40Poti].interval) - y.aOut = aio.NewAnalogActuatorDriver(pcf, yl40Pins[YL40AOUT]) - - // set input scalers - y.aBri.SetScaler(y.conf.sensors[YL40Bri].scaler) - y.aTemp.SetScaler(y.conf.sensors[YL40Temp].scaler) - y.aAIN2.SetScaler(y.conf.sensors[YL40AIN2].scaler) - y.aPoti.SetScaler(y.conf.sensors[YL40Poti].scaler) - - // set output scaler - y.aOut.SetScaler(y.conf.aOutScaler) + y.aBri = aio.NewAnalogSensorDriver(pcf, yl40Pins[YL40Bri], + aio.WithSensorCyclicRead(y.conf.sensors[YL40Bri].interval), + aio.WithSensorScaler(y.conf.sensors[YL40Bri].scaler)) + y.aTemp = aio.NewTemperatureSensorDriver(pcf, yl40Pins[YL40Temp], + aio.WithSensorCyclicRead(y.conf.sensors[YL40Temp].interval), + aio.WithSensorScaler(y.conf.sensors[YL40Temp].scaler)) + y.aAIN2 = aio.NewAnalogSensorDriver(pcf, yl40Pins[YL40AIN2], + aio.WithSensorCyclicRead(y.conf.sensors[YL40AIN2].interval), + aio.WithSensorScaler(y.conf.sensors[YL40AIN2].scaler)) + y.aPoti = aio.NewAnalogSensorDriver(pcf, yl40Pins[YL40Poti], + aio.WithSensorCyclicRead(y.conf.sensors[YL40Poti].interval), + aio.WithSensorScaler(y.conf.sensors[YL40Poti].scaler)) + y.aOut = aio.NewAnalogActuatorDriver(pcf, yl40Pins[YL40AOUT], + aio.WithActuatorScaler(y.conf.aOutScaler)) return y } diff --git a/examples/beaglebone_led_brightness_with_analog_input.go b/examples/beaglebone_led_brightness_with_analog_input.go index c284c74b7..ddd8598fb 100644 --- a/examples/beaglebone_led_brightness_with_analog_input.go +++ b/examples/beaglebone_led_brightness_with_analog_input.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -17,7 +18,7 @@ import ( func main() { beagleboneAdaptor := beaglebone.NewAdaptor() - sensor := aio.NewAnalogSensorDriver(beagleboneAdaptor, "P9_33") + sensor := aio.NewAnalogSensorDriver(beagleboneAdaptor, "P9_33", aio.WithSensorCyclicRead(500*time.Millisecond)) led := gpio.NewLedDriver(beagleboneAdaptor, "P9_14") work := func() { diff --git a/examples/edison_grove_light_sensor.go b/examples/edison_grove_light_sensor.go index 4497b0647..68f08784f 100644 --- a/examples/edison_grove_light_sensor.go +++ b/examples/edison_grove_light_sensor.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -16,7 +17,7 @@ import ( func main() { board := edison.NewAdaptor() - sensor := aio.NewGroveLightSensorDriver(board, "0") + sensor := aio.NewGroveLightSensorDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) 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 635d19b83..ea30c7e5b 100644 --- a/examples/edison_grove_piezo_vibration.go +++ b/examples/edison_grove_piezo_vibration.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -16,7 +17,7 @@ import ( func main() { board := edison.NewAdaptor() - sensor := aio.NewGrovePiezoVibrationSensorDriver(board, "0") + sensor := aio.NewGrovePiezoVibrationSensorDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(aio.Vibration, func(data interface{}) { diff --git a/examples/edison_grove_rotary_sensor.go b/examples/edison_grove_rotary_sensor.go index 2b50db7e1..6fbde9e86 100644 --- a/examples/edison_grove_rotary_sensor.go +++ b/examples/edison_grove_rotary_sensor.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -16,7 +17,7 @@ import ( func main() { board := edison.NewAdaptor() - sensor := aio.NewGroveRotaryDriver(board, "0") + sensor := aio.NewGroveRotaryDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(aio.Data, func(data interface{}) { diff --git a/examples/edison_grove_sound_sensor.go b/examples/edison_grove_sound_sensor.go index 002e7f5c6..794355297 100644 --- a/examples/edison_grove_sound_sensor.go +++ b/examples/edison_grove_sound_sensor.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -16,7 +17,7 @@ import ( func main() { board := edison.NewAdaptor() - sensor := aio.NewGroveSoundSensorDriver(board, "0") + sensor := aio.NewGroveSoundSensorDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(aio.Data, func(data interface{}) { diff --git a/examples/edison_grove_temperature_sensor.go b/examples/edison_grove_temperature_sensor.go index 721b93e14..6886f6093 100644 --- a/examples/edison_grove_temperature_sensor.go +++ b/examples/edison_grove_temperature_sensor.go @@ -17,7 +17,7 @@ import ( func main() { board := edison.NewAdaptor() - sensor := aio.NewGroveTemperatureSensorDriver(board, "0") + sensor := aio.NewGroveTemperatureSensorDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) 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 edba45aab..9b82fefae 100644 --- a/examples/edison_led_brightness_with_analog_input.go +++ b/examples/edison_led_brightness_with_analog_input.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -17,7 +18,7 @@ import ( func main() { e := edison.NewAdaptor() - sensor := aio.NewAnalogSensorDriver(e, "0") + sensor := aio.NewAnalogSensorDriver(e, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) led := gpio.NewLedDriver(e, "3") work := func() { diff --git a/examples/firmata_grove_sound_sensor.go b/examples/firmata_grove_sound_sensor.go index d0e12ab60..d118c7a52 100644 --- a/examples/firmata_grove_sound_sensor.go +++ b/examples/firmata_grove_sound_sensor.go @@ -9,6 +9,7 @@ package main import ( "fmt" "os" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -17,7 +18,7 @@ import ( func main() { board := firmata.NewAdaptor(os.Args[1]) - sensor := aio.NewGroveSoundSensorDriver(board, "3") + sensor := aio.NewGroveSoundSensorDriver(board, "3", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(aio.Data, func(data interface{}) { diff --git a/examples/firmata_integration.go b/examples/firmata_integration.go index d4006ff50..eafbddbc9 100644 --- a/examples/firmata_integration.go +++ b/examples/firmata_integration.go @@ -29,7 +29,7 @@ func main() { led1 := gpio.NewLedDriver(firmataAdaptor, "3") led2 := gpio.NewLedDriver(firmataAdaptor, "4") button := gpio.NewButtonDriver(firmataAdaptor, "2") - sensor := aio.NewAnalogSensorDriver(firmataAdaptor, "0") + sensor := aio.NewAnalogSensorDriver(firmataAdaptor, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { gobot.Every(1*time.Second, func() { diff --git a/examples/firmata_led_brightness_with_analog_input.go b/examples/firmata_led_brightness_with_analog_input.go index a9c6b4c34..3c86ae375 100644 --- a/examples/firmata_led_brightness_with_analog_input.go +++ b/examples/firmata_led_brightness_with_analog_input.go @@ -16,6 +16,7 @@ package main import ( "fmt" "os" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -25,7 +26,7 @@ import ( func main() { firmataAdaptor := firmata.NewAdaptor(os.Args[1]) - sensor := aio.NewAnalogSensorDriver(firmataAdaptor, "0") + sensor := aio.NewAnalogSensorDriver(firmataAdaptor, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) led := gpio.NewLedDriver(firmataAdaptor, "3") work := func() { diff --git a/examples/gopigo3_grove_light_sensor.go b/examples/gopigo3_grove_light_sensor.go index e9472e345..8454f96fc 100644 --- a/examples/gopigo3_grove_light_sensor.go +++ b/examples/gopigo3_grove_light_sensor.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -18,7 +19,7 @@ import ( func main() { raspiAdaptor := raspi.NewAdaptor() gpg3 := gopigo3.NewDriver(raspiAdaptor) - sensor := aio.NewGroveLightSensorDriver(gpg3, "AD_1_1") + sensor := aio.NewGroveLightSensorDriver(gpg3, "AD_1_1", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(sensor.Event("data"), func(data interface{}) { diff --git a/examples/joule_grove_rotary_sensor.go b/examples/joule_grove_rotary_sensor.go index 84a16c2f9..bd1e7cbc6 100644 --- a/examples/joule_grove_rotary_sensor.go +++ b/examples/joule_grove_rotary_sensor.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -18,7 +19,7 @@ import ( func main() { board := joule.NewAdaptor() ads1015 := i2c.NewADS1015Driver(board) - sensor := aio.NewGroveRotaryDriver(ads1015, "0") + sensor := aio.NewGroveRotaryDriver(ads1015, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(aio.Data, func(data interface{}) { diff --git a/examples/joule_led_brightness_with_analog_input.go b/examples/joule_led_brightness_with_analog_input.go index 3bef27334..167e3210a 100644 --- a/examples/joule_led_brightness_with_analog_input.go +++ b/examples/joule_led_brightness_with_analog_input.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -19,7 +20,7 @@ import ( func main() { e := joule.NewAdaptor() ads1015 := i2c.NewADS1015Driver(e) - sensor := aio.NewAnalogSensorDriver(ads1015, "0") + sensor := aio.NewAnalogSensorDriver(ads1015, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) led := gpio.NewLedDriver(e, "J12_26") work := func() { diff --git a/examples/raspi_grove_pi_rotary.go b/examples/raspi_grove_pi_rotary.go index c73ba961f..afecd5eff 100644 --- a/examples/raspi_grove_pi_rotary.go +++ b/examples/raspi_grove_pi_rotary.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -18,7 +19,7 @@ import ( func main() { board := raspi.NewAdaptor() gp := i2c.NewGrovePiDriver(board) - sensor := aio.NewGroveRotaryDriver(gp, "A1") + sensor := aio.NewGroveRotaryDriver(gp, "A1", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(aio.Data, func(data interface{}) { diff --git a/examples/raspi_grove_rotary_sensor.go b/examples/raspi_grove_rotary_sensor.go index 438798901..f9960ce7f 100644 --- a/examples/raspi_grove_rotary_sensor.go +++ b/examples/raspi_grove_rotary_sensor.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -18,7 +19,7 @@ import ( func main() { board := raspi.NewAdaptor() ads1015 := i2c.NewADS1015Driver(board) - sensor := aio.NewGroveRotaryDriver(ads1015, "0") + sensor := aio.NewGroveRotaryDriver(ads1015, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(aio.Data, func(data interface{}) { diff --git a/examples/wifi_firmata_analog_input.go b/examples/wifi_firmata_analog_input.go index 912f5d6dc..924d81e35 100644 --- a/examples/wifi_firmata_analog_input.go +++ b/examples/wifi_firmata_analog_input.go @@ -9,6 +9,7 @@ package main import ( "fmt" "os" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" @@ -17,7 +18,7 @@ import ( func main() { firmataAdaptor := firmata.NewTCPAdaptor(os.Args[1]) - sensor := aio.NewAnalogSensorDriver(firmataAdaptor, "A0") + sensor := aio.NewAnalogSensorDriver(firmataAdaptor, "A0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { sensor.On(aio.Data, func(data interface{}) { From 916c2bad18421c58dec22a48ca39b742e2b7bcec Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 26 Nov 2023 19:41:02 +0100 Subject: [PATCH 31/57] aio(analog sensor): fix deadlock in cyclic reading (#1042) --- drivers/aio/analog_sensor_driver.go | 89 ++++++++++--------- drivers/aio/analog_sensor_driver_test.go | 15 ++-- drivers/aio/grove_drivers_test.go | 13 +-- .../grove_temperature_sensor_driver_test.go | 9 +- drivers/aio/temperature_sensor_driver_test.go | 14 +-- 5 files changed, 77 insertions(+), 63 deletions(-) diff --git a/drivers/aio/analog_sensor_driver.go b/drivers/aio/analog_sensor_driver.go index 37a7fefbb..adae38e31 100644 --- a/drivers/aio/analog_sensor_driver.go +++ b/drivers/aio/analog_sensor_driver.go @@ -56,8 +56,7 @@ func NewAnalogSensorDriver(a AnalogReader, pin string, opts ...interface{}) *Ana driver: newDriver(a, "AnalogSensor"), sensorCfg: &sensorConfiguration{scale: func(input int) float64 { return float64(input) }}, pin: pin, - Eventer: gobot.NewEventer(), - halt: make(chan bool), + Eventer: gobot.NewEventer(), // needed early due to grove vibration sensor driver } d.afterStart = d.initialize d.beforeHalt = d.shutdown @@ -76,10 +75,6 @@ func NewAnalogSensorDriver(a AnalogReader, pin string, opts ...interface{}) *Ana } } - d.AddEvent(Data) - d.AddEvent(Value) - d.AddEvent(Error) - d.AddCommand("Read", func(params map[string]interface{}) interface{} { val, err := d.Read() return map[string]interface{}{"val": val, "err": err} @@ -112,6 +107,37 @@ func (a *AnalogSensorDriver) SetScaler(scaler func(int) float64) { WithSensorScaler(scaler).apply(a.sensorCfg) } +// Pin returns the AnalogSensorDrivers pin +func (a *AnalogSensorDriver) Pin() string { return a.pin } + +// Read returns the current reading from the sensor, scaled by the current scaler +func (a *AnalogSensorDriver) Read() (float64, error) { + _, value, err := a.analogRead() + return value, err +} + +// ReadRaw returns the current reading from the sensor without scaling +func (a *AnalogSensorDriver) ReadRaw() (int, error) { + rawValue, _, err := a.analogRead() + return rawValue, err +} + +// Value returns the last read value from the sensor +func (a *AnalogSensorDriver) Value() float64 { + a.mutex.Lock() + defer a.mutex.Unlock() + + return a.lastValue +} + +// RawValue returns the last read raw value from the sensor +func (a *AnalogSensorDriver) RawValue() int { + a.mutex.Lock() + defer a.mutex.Unlock() + + return a.lastRawValue +} + // initialize the AnalogSensorDriver and if the cyclic reading is active, reads the sensor at the given interval. // Emits the Events: // @@ -123,12 +149,27 @@ func (a *AnalogSensorDriver) initialize() error { // cyclic reading deactivated return nil } + + a.AddEvent(Data) + a.AddEvent(Value) + a.AddEvent(Error) + + // A small buffer is needed to prevent mutex-channel-deadlock between Halt() and analogRead(). + // This can happen, if the shutdown is in progress (mutex passed) and the go routine is calling + // the analogRead() in between, before the halt can be evaluated by the select statement. + // In this case the mutex of analogRead() blocks the reading of the halt channel and, without a small buffer, + // the writing to halt is blocked because there is no immediate read from channel. + // Please note, that this is special behavior caused by the first read is done immediately before the select + // statement. + a.halt = make(chan bool, 1) + oldRawValue := 0 oldValue := 0.0 go func() { timer := time.NewTimer(a.sensorCfg.readInterval) timer.Stop() for { + // please note, that this ensures the first read is done immediately, but has drawbacks, see notes above rawValue, value, err := a.analogRead() if err != nil { a.Publish(a.Event(Error), err) @@ -142,8 +183,7 @@ func (a *AnalogSensorDriver) initialize() error { oldValue = value } } - - timer.Reset(a.sensorCfg.readInterval) + timer.Reset(a.sensorCfg.readInterval) // ensure that after each read is a wait, independent of duration of read select { case <-timer.C: case <-a.halt: @@ -157,7 +197,7 @@ func (a *AnalogSensorDriver) initialize() error { // shutdown stops polling the analog sensor for new information func (a *AnalogSensorDriver) shutdown() error { - if a.sensorCfg.readInterval == 0 { + if a.sensorCfg.readInterval == 0 || a.halt == nil { // cyclic reading deactivated return nil } @@ -165,37 +205,6 @@ func (a *AnalogSensorDriver) shutdown() error { return nil } -// Pin returns the AnalogSensorDrivers pin -func (a *AnalogSensorDriver) Pin() string { return a.pin } - -// Read returns the current reading from the sensor, scaled by the current scaler -func (a *AnalogSensorDriver) Read() (float64, error) { - _, value, err := a.analogRead() - return value, err -} - -// ReadRaw returns the current reading from the sensor without scaling -func (a *AnalogSensorDriver) ReadRaw() (int, error) { - rawValue, _, err := a.analogRead() - return rawValue, err -} - -// Value returns the last read value from the sensor -func (a *AnalogSensorDriver) Value() float64 { - a.mutex.Lock() - defer a.mutex.Unlock() - - return a.lastValue -} - -// RawValue returns the last read raw value from the sensor -func (a *AnalogSensorDriver) RawValue() int { - a.mutex.Lock() - defer a.mutex.Unlock() - - return a.lastRawValue -} - // analogRead performs an reading from the sensor and sets the internal attributes and returns the raw and scaled value func (a *AnalogSensorDriver) analogRead() (int, float64, error) { a.mutex.Lock() diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index ddb004984..6fcd95499 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -34,7 +34,7 @@ func TestNewAnalogSensorDriver(t *testing.T) { assert.Equal(t, pin, d.Pin()) assert.InDelta(t, 0.0, d.lastValue, 0, 0) assert.Equal(t, 0, d.lastRawValue) - assert.NotNil(t, d.halt) + assert.Nil(t, d.halt) // will be created on initialize, if cyclic reading is on assert.NotNil(t, d.Eventer) require.NotNil(t, d.sensorCfg) assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) @@ -171,6 +171,9 @@ 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{}) { assert.Equal(t, 100, data.(int)) @@ -185,9 +188,6 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) { nextVal <- -1 // arrange: error in read function }) - // act (start cyclic reading) - require.NoError(t, d.Start()) - // assert: both events within timeout select { case <-semDone: @@ -233,13 +233,14 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) { func TestAnalogSensorHalt_WithSensorCyclicRead(t *testing.T) { // arrange d := NewAnalogSensorDriver(newAioTestAdaptor(), "1", WithSensorCyclicRead(10*time.Millisecond)) + require.NoError(t, d.Start()) done := make(chan struct{}) + // act & assert go func() { - <-d.halt + require.NoError(t, d.Halt()) close(done) }() - // act & assert - require.NoError(t, d.Halt()) + // test that the halt is not blocked by any deadlock with mutex and/or channel select { case <-done: case <-time.After(100 * time.Millisecond): diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go index 69cf35c93..a161b4fe5 100644 --- a/drivers/aio/grove_drivers_test.go +++ b/drivers/aio/grove_drivers_test.go @@ -39,7 +39,7 @@ func TestNewGroveRotaryDriver(t *testing.T) { assert.Equal(t, pin, d.Pin()) assert.InDelta(t, 0.0, d.lastValue, 0, 0) assert.Equal(t, 0, d.lastRawValue) - assert.NotNil(t, d.halt) + assert.Nil(t, d.halt) // will be created on initialize, if cyclic reading is on assert.NotNil(t, d.Eventer) require.NotNil(t, d.sensorCfg) assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) @@ -65,7 +65,7 @@ func TestNewGroveLightSensorDriver(t *testing.T) { assert.Equal(t, pin, d.Pin()) assert.InDelta(t, 0.0, d.lastValue, 0, 0) assert.Equal(t, 0, d.lastRawValue) - assert.NotNil(t, d.halt) + assert.Nil(t, d.halt) // will be created on initialize, if cyclic reading is on assert.NotNil(t, d.Eventer) require.NotNil(t, d.sensorCfg) assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) @@ -91,7 +91,7 @@ func TestNewGrovePiezoVibrationSensorDriver(t *testing.T) { assert.Equal(t, pin, d.Pin()) assert.InDelta(t, 0.0, d.lastValue, 0, 0) assert.Equal(t, 0, d.lastRawValue) - assert.NotNil(t, d.halt) + assert.Nil(t, d.halt) // will be created on initialize, if cyclic reading is on assert.NotNil(t, d.Eventer) require.NotNil(t, d.sensorCfg) assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) @@ -117,7 +117,7 @@ func TestNewGroveSoundSensorDriver(t *testing.T) { assert.Equal(t, pin, d.Pin()) assert.InDelta(t, 0.0, d.lastValue, 0, 0) assert.Equal(t, 0, d.lastRawValue) - assert.NotNil(t, d.halt) + assert.Nil(t, d.halt) // will be created on initialize, if cyclic reading is on assert.NotNil(t, d.Eventer) require.NotNil(t, d.sensorCfg) assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) @@ -151,8 +151,9 @@ func TestGroveDriverHalt_WithSensorCyclicRead(t *testing.T) { 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") + // note: if a reading is already in progress, it will be finished before halt have an impact + if atomic.LoadInt32(&callCount) > lastCallCount+1 { + t.Errorf("AnalogRead was called more than once after driver was halted") } } } diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index 1559d4f54..ce8dc66ff 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -34,7 +34,7 @@ func TestNewGroveTemperatureSensorDriver(t *testing.T) { assert.Equal(t, pin, d.Pin()) assert.InDelta(t, 0.0, d.lastValue, 0, 0) assert.Equal(t, 0, d.lastRawValue) - assert.NotNil(t, d.halt) + assert.Nil(t, d.halt) // will be created on initialize, if cyclic reading is on assert.NotNil(t, d.Eventer) require.NotNil(t, d.sensorCfg) assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) @@ -103,14 +103,15 @@ func TestGroveTemperatureSensor_publishesTemperatureInCelsius(t *testing.T) { a.analogReadFunc = func() (int, error) { return 585, nil } + + // act: start cyclic reading + require.NoError(t, d.Start()) + _ = d.Once(d.Event(Value), func(data interface{}) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) - // act: start cyclic reading - require.NoError(t, d.Start()) - // assert: value was published select { case <-sem: diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index 1d2a30069..cc3786a0e 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -31,7 +31,7 @@ func TestNewTemperatureSensorDriver(t *testing.T) { assert.Equal(t, pin, d.Pin()) assert.InDelta(t, 0.0, d.lastValue, 0, 0) assert.Equal(t, 0, d.lastRawValue) - assert.NotNil(t, d.halt) + assert.Nil(t, d.halt) // will be created on initialize, if cyclic reading is on assert.NotNil(t, d.Eventer) require.NotNil(t, d.sensorCfg) assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) @@ -139,11 +139,12 @@ func TestTemperatureSensorPublishesTemperatureInCelsius(t *testing.T) { a.analogReadFunc = func() (int, error) { return 585, nil } + + require.NoError(t, d.Start()) _ = d.Once(d.Event(Value), func(data interface{}) { assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64))) sem <- true }) - require.NoError(t, d.Start()) select { case <-sem: @@ -184,16 +185,17 @@ func TestTemperatureSensorHalt_WithSensorCyclicRead(t *testing.T) { // arrange d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1", WithSensorCyclicRead(10*time.Millisecond)) done := make(chan struct{}) + require.NoError(t, d.Start()) + // act & assert go func() { - <-d.halt + require.NoError(t, d.Halt()) close(done) }() - // act & assert - require.NoError(t, d.Halt()) + // test that the halt is not blocked by any deadlock with mutex and/or channel select { case <-done: case <-time.After(100 * time.Millisecond): - t.Errorf(" Temperature Sensor was not halted") + t.Errorf("Temperature Sensor was not halted") } } From d39848e368baeecc48fe8fa829321f2f94b95acf Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 26 Nov 2023 19:47:28 +0100 Subject: [PATCH 32/57] platforms(adaptors): add a generic analog pin adaptor (#1041) --- adaptor.go | 8 + platforms/adaptors/analogpinsadaptor.go | 95 +++++++ platforms/adaptors/analogpinsadaptor_test.go | 249 ++++++++++++++++++ platforms/beaglebone/beaglebone_adaptor.go | 61 ++--- platforms/beaglebone/black_pins.go | 18 +- platforms/beaglebone/pocketbeagle_pins.go | 16 +- platforms/intel-iot/edison/edison_adaptor.go | 42 +-- .../intel-iot/edison/edison_adaptor_test.go | 23 +- system/PWM.md | 2 + system/analogpin_sysfs.go | 37 +++ system/analogpin_sysfs_test.go | 121 +++++++++ system/digitalpin_access.go | 6 +- system/digitalpin_sysfs.go | 103 +++----- system/digitalpin_sysfs_test.go | 104 ++++---- system/fs_mock.go | 29 +- system/pwmpin_sysfs.go | 73 ++--- system/pwmpin_sysfs_test.go | 71 +++-- system/sysfsfile_access.go | 146 ++++++++++ system/system.go | 14 +- system/system_test.go | 2 +- 20 files changed, 915 insertions(+), 305 deletions(-) create mode 100644 platforms/adaptors/analogpinsadaptor.go create mode 100644 platforms/adaptors/analogpinsadaptor_test.go create mode 100644 system/analogpin_sysfs.go create mode 100644 system/analogpin_sysfs_test.go create mode 100644 system/sysfsfile_access.go diff --git a/adaptor.go b/adaptor.go index ef4730bda..5456136f7 100644 --- a/adaptor.go +++ b/adaptor.go @@ -99,6 +99,14 @@ type PWMPinnerProvider interface { PWMPin(id string) (PWMPinner, error) } +// AnalogPinner is the interface for system analog io interactions +type AnalogPinner interface { + // Read reads the current value of the pin + Read() (int, error) + // Write writes to the pin + Write(val int) error +} + // I2cSystemDevicer is the interface to a i2c bus at system level, according to I2C/SMBus specification. // Some functions are not in the interface yet: // * Process Call (WriteWordDataReadWordData) diff --git a/platforms/adaptors/analogpinsadaptor.go b/platforms/adaptors/analogpinsadaptor.go new file mode 100644 index 000000000..59a210d14 --- /dev/null +++ b/platforms/adaptors/analogpinsadaptor.go @@ -0,0 +1,95 @@ +package adaptors + +import ( + "fmt" + "sync" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/system" +) + +type analogPinTranslator func(pin string) (path string, r, w bool, bufLen uint16, err error) + +// AnalogPinsAdaptor is a adaptor for analog pins, normally used for composition in platforms. +// It is also usable for general sysfs access. +type AnalogPinsAdaptor struct { + sys *system.Accesser + translate analogPinTranslator + pins map[string]gobot.AnalogPinner + mutex sync.Mutex +} + +// NewAnalogPinsAdaptor provides the access to analog pins of the board. Usually sysfs system drivers are used. +// The translator is used to adapt the pin header naming, which is given by user, to the internal file name +// nomenclature. This varies by each platform. +func NewAnalogPinsAdaptor(sys *system.Accesser, t analogPinTranslator) *AnalogPinsAdaptor { + a := AnalogPinsAdaptor{ + sys: sys, + translate: t, + } + return &a +} + +// Connect prepare new connection to analog pins. +func (a *AnalogPinsAdaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() + + a.pins = make(map[string]gobot.AnalogPinner) + return nil +} + +// Finalize closes connection to analog pins +func (a *AnalogPinsAdaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() + + a.pins = nil + return nil +} + +// AnalogRead returns an analog value from specified pin or identifier, defined by the translation function. +func (a *AnalogPinsAdaptor) AnalogRead(id string) (int, error) { + a.mutex.Lock() + defer a.mutex.Unlock() + + pin, err := a.analogPin(id) + if err != nil { + return 0, err + } + + return pin.Read() +} + +// AnalogWrite writes an analog value to the specified pin or identifier, defined by the translation function. +func (a *AnalogPinsAdaptor) AnalogWrite(id string, val int) error { + a.mutex.Lock() + defer a.mutex.Unlock() + + pin, err := a.analogPin(id) + if err != nil { + return err + } + + return pin.Write(val) +} + +// analogPin initializes the pin for analog access and returns matched pin for specified identifier. +func (a *AnalogPinsAdaptor) analogPin(id string) (gobot.AnalogPinner, error) { + if a.pins == nil { + return nil, fmt.Errorf("not connected for pin %s", id) + } + + pin := a.pins[id] + + if pin == nil { + path, r, w, bufLen, err := a.translate(id) + if err != nil { + return nil, err + } + pin = a.sys.NewAnalogPin(path, r, w, bufLen) + a.pins[id] = pin + } + + return pin, nil +} diff --git a/platforms/adaptors/analogpinsadaptor_test.go b/platforms/adaptors/analogpinsadaptor_test.go new file mode 100644 index 000000000..3a5289ed4 --- /dev/null +++ b/platforms/adaptors/analogpinsadaptor_test.go @@ -0,0 +1,249 @@ +//nolint:nonamedreturns // ok for tests +package adaptors + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/system" +) + +const ( + analogReadPath = "/sys/bus/iio/devices/iio:device0/in_voltage0_raw" + analogWritePath = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/export" + analogReadWritePath = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/period" + analogReadWriteStringPath = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/polarity" +) + +var analogMockPaths = []string{ + analogReadPath, + analogWritePath, + analogReadWritePath, + analogReadWriteStringPath, +} + +func initTestAnalogPinsAdaptorWithMockedFilesystem(mockPaths []string) (*AnalogPinsAdaptor, *system.MockFilesystem) { + sys := system.NewAccesser() + fs := sys.UseMockFilesystem(mockPaths) + a := NewAnalogPinsAdaptor(sys, testAnalogPinTranslator) + fs.Files[analogReadPath].Contents = "54321" + fs.Files[analogWritePath].Contents = "0" + fs.Files[analogReadWritePath].Contents = "30000" + fs.Files[analogReadWriteStringPath].Contents = "inverted" + if err := a.Connect(); err != nil { + panic(err) + } + return a, fs +} + +func testAnalogPinTranslator(id string) (string, bool, bool, uint16, error) { + switch id { + case "read": + return analogReadPath, true, false, 10, nil + case "write": + return analogWritePath, false, true, 11, nil + case "read/write": + return analogReadWritePath, true, true, 12, nil + case "read/write_string": + return analogReadWriteStringPath, true, true, 13, nil + } + + return "", false, false, 0, fmt.Errorf("'%s' is not a valid id of a analog pin", id) +} + +func TestAnalogPinsConnect(t *testing.T) { + translate := func(id string) (path string, r, w bool, bufLen uint16, err error) { return } + a := NewAnalogPinsAdaptor(system.NewAccesser(), translate) + assert.Equal(t, (map[string]gobot.AnalogPinner)(nil), a.pins) + + err := a.AnalogWrite("write", 1) + require.ErrorContains(t, err, "not connected") + + err = a.Connect() + require.NoError(t, err) + assert.NotEqual(t, (map[string]gobot.AnalogPinner)(nil), a.pins) + assert.Empty(t, a.pins) +} + +func TestAnalogPinsFinalize(t *testing.T) { + // arrange + sys := system.NewAccesser() + fs := sys.UseMockFilesystem(analogMockPaths) + a := NewAnalogPinsAdaptor(sys, testAnalogPinTranslator) + fs.Files[analogReadPath].Contents = "0" + // assert that finalize before connect is working + require.NoError(t, a.Finalize()) + // arrange + require.NoError(t, a.Connect()) + require.NoError(t, a.AnalogWrite("write", 1)) + assert.Len(t, a.pins, 1) + // act + err := a.Finalize() + // assert + require.NoError(t, err) + assert.Empty(t, a.pins) + // assert that finalize after finalize is working + require.NoError(t, a.Finalize()) + // arrange missing file + require.NoError(t, a.Connect()) + require.NoError(t, a.AnalogWrite("write", 2)) + delete(fs.Files, analogWritePath) + err = a.Finalize() + require.NoError(t, err) // because there is currently no access on finalize + // arrange write error + require.NoError(t, a.Connect()) + require.NoError(t, a.AnalogWrite("read/write_string", 5)) + fs.WithWriteError = true + err = a.Finalize() + require.NoError(t, err) // because there is currently no access on finalize +} + +func TestAnalogPinsReConnect(t *testing.T) { + // arrange + a, _ := initTestAnalogPinsAdaptorWithMockedFilesystem(analogMockPaths) + require.NoError(t, a.AnalogWrite("read/write_string", 1)) + assert.Len(t, a.pins, 1) + require.NoError(t, a.Finalize()) + // act + err := a.Connect() + // assert + require.NoError(t, err) + assert.NotNil(t, a.pins) + assert.Empty(t, a.pins) +} + +func TestAnalogWrite(t *testing.T) { + tests := map[string]struct { + pin string + simulateWriteErr bool + simulateReadErr bool + wantValW string + wantValRW string + wantValRWS string + wantErr string + }{ + "write_w_pin": { + pin: "write", + wantValW: "100", + wantValRW: "30000", + wantValRWS: "inverted", + }, + "write_rw_pin": { + pin: "read/write_string", + wantValW: "0", + wantValRW: "30000", + wantValRWS: "100", + }, + "ok_on_read_error": { + pin: "read/write_string", + simulateReadErr: true, + wantValW: "0", + wantValRW: "30000", + wantValRWS: "100", + }, + "error_write_error": { + pin: "read/write_string", + simulateWriteErr: true, + wantValW: "0", + wantValRW: "30000", + wantValRWS: "inverted", + wantErr: "write error", + }, + "error_notexist": { + pin: "notexist", + wantValW: "0", + wantValRW: "30000", + wantValRWS: "inverted", + wantErr: "'notexist' is not a valid id of a analog pin", + }, + "error_write_not_allowed": { + pin: "read", + wantValW: "0", + wantValRW: "30000", + wantValRWS: "inverted", + wantErr: "the pin '/sys/bus/iio/devices/iio:device0/in_voltage0_raw' is not allowed to write (val: 100)", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a, fs := initTestAnalogPinsAdaptorWithMockedFilesystem(analogMockPaths) + fs.WithWriteError = tc.simulateWriteErr + fs.WithReadError = tc.simulateReadErr + // act + err := a.AnalogWrite(tc.pin, 100) + // assert + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + } else { + require.NoError(t, err) + } + assert.Equal(t, "54321", fs.Files[analogReadPath].Contents) + assert.Equal(t, tc.wantValW, fs.Files[analogWritePath].Contents) + assert.Equal(t, tc.wantValRW, fs.Files[analogReadWritePath].Contents) + assert.Equal(t, tc.wantValRWS, fs.Files[analogReadWriteStringPath].Contents) + }) + } +} + +func TestAnalogRead(t *testing.T) { + tests := map[string]struct { + pin string + simulateReadErr bool + simulateWriteErr bool + wantVal int + wantErr string + }{ + "read_r_pin": { + pin: "read", + wantVal: 54321, + }, + "read_rw_pin": { + pin: "read/write", + wantVal: 30000, + }, + "ok_on_write_error": { + pin: "read", + simulateWriteErr: true, + wantVal: 54321, + }, + "error_read_error": { + pin: "read", + simulateReadErr: true, + wantErr: "read error", + }, + "error_notexist": { + pin: "notexist", + wantErr: "'notexist' is not a valid id of a analog pin", + }, + "error_invalid_syntax": { + pin: "read/write_string", + wantErr: "strconv.Atoi: parsing \"inverted\": invalid syntax", + }, + "error_read_not_allowed": { + pin: "write", + wantErr: "the pin '/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/export' is not allowed to read", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a, fs := initTestAnalogPinsAdaptorWithMockedFilesystem(analogMockPaths) + fs.WithReadError = tc.simulateReadErr + fs.WithWriteError = tc.simulateWriteErr + // act + got, err := a.AnalogRead(tc.pin) + // assert + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + } else { + require.NoError(t, err) + } + assert.Equal(t, tc.wantVal, got) + }) + } +} diff --git a/platforms/beaglebone/beaglebone_adaptor.go b/platforms/beaglebone/beaglebone_adaptor.go index 7048a3c66..87269eae4 100644 --- a/platforms/beaglebone/beaglebone_adaptor.go +++ b/platforms/beaglebone/beaglebone_adaptor.go @@ -14,12 +14,19 @@ import ( "gobot.io/x/gobot/v2/system" ) -type pwmPinData struct { +type pwmPinDefinition struct { channel int dir string dirRegexp string } +type analogPinDefinition struct { + path string + r bool // readable + w bool // writable + bufLen uint16 +} + const ( pwmPeriodDefault = 500000 // 0.5 ms = 2 kHz @@ -37,15 +44,15 @@ type Adaptor struct { name string sys *system.Accesser mutex sync.Mutex + *adaptors.AnalogPinsAdaptor *adaptors.DigitalPinsAdaptor *adaptors.PWMPinsAdaptor *adaptors.I2cBusAdaptor *adaptors.SpiBusAdaptor usrLed string - analogPath string pinMap map[string]int - pwmPinMap map[string]pwmPinData - analogPinMap map[string]string + pwmPinMap map[string]pwmPinDefinition + analogPinMap map[string]analogPinDefinition } // NewAdaptor returns a new Beaglebone Black/Green Adaptor @@ -63,9 +70,8 @@ func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { pwmPinMap: bbbPwmPinMap, analogPinMap: bbbAnalogPinMap, usrLed: "/sys/class/leds/beaglebone:green:", - analogPath: "/sys/bus/iio/devices/iio:device0", } - + c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateAndMuxDigitalPin, opts...) c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translateAndMuxPWMPin, adaptors.WithPWMPinDefaultPeriod(pwmPeriodDefault)) @@ -94,6 +100,10 @@ func (c *Adaptor) Connect() error { return err } + if err := c.AnalogPinsAdaptor.Connect(); err != nil { + return err + } + if err := c.PWMPinsAdaptor.Connect(); err != nil { return err } @@ -111,6 +121,10 @@ func (c *Adaptor) Finalize() error { err = multierror.Append(err, e) } + if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + err = multierror.Append(err, e) + } + if e := c.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } @@ -140,29 +154,6 @@ func (c *Adaptor) DigitalWrite(id string, val byte) error { return c.DigitalPinsAdaptor.DigitalWrite(id, val) } -// AnalogRead returns an analog value from specified pin -func (c *Adaptor) AnalogRead(pin string) (int, error) { - analogPin, err := c.translateAnalogPin(pin) - if err != nil { - return 0, err - } - fi, err := c.sys.OpenFile(fmt.Sprintf("%v/%v", c.analogPath, analogPin), os.O_RDONLY, 0o644) - defer fi.Close() //nolint:staticcheck // for historical reasons - - if err != nil { - return 0, err - } - - buf := make([]byte, 1024) - _, err = fi.Read(buf) - if err != nil { - return 0, err - } - - val, _ := strconv.Atoi(strings.Split(string(buf), "\n")[0]) - return val, nil -} - func (c *Adaptor) validateSpiBusNumber(busNr int) error { // Valid bus numbers are [0,1] which corresponds to /dev/spidev0.x through /dev/spidev1.x. // x is the chip number <255 @@ -181,11 +172,13 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { } // translateAnalogPin converts analog pin name to pin position -func (c *Adaptor) translateAnalogPin(pin string) (string, error) { - if val, ok := c.analogPinMap[pin]; ok { - return val, nil +func (c *Adaptor) translateAnalogPin(pin string) (string, bool, bool, uint16, error) { + pinInfo, ok := c.analogPinMap[pin] + if !ok { + return "", false, false, 0, fmt.Errorf("Not a valid analog pin") } - return "", fmt.Errorf("Not a valid analog pin") + + return pinInfo.path, pinInfo.r, pinInfo.w, pinInfo.bufLen, nil } // translatePin converts digital pin name to pin position @@ -219,7 +212,7 @@ func (c *Adaptor) translateAndMuxPWMPin(id string) (string, int, error) { return path, pinInfo.channel, nil } -func (p pwmPinData) findPWMDir(sys *system.Accesser) (string, error) { +func (p pwmPinDefinition) findPWMDir(sys *system.Accesser) (string, error) { items, _ := sys.Find(p.dir, p.dirRegexp) if len(items) == 0 { return "", fmt.Errorf("No path found for PWM directory pattern, '%s' in path '%s'", p.dirRegexp, p.dir) diff --git a/platforms/beaglebone/black_pins.go b/platforms/beaglebone/black_pins.go index 9d8357f46..c8f03ae98 100644 --- a/platforms/beaglebone/black_pins.go +++ b/platforms/beaglebone/black_pins.go @@ -49,7 +49,7 @@ var bbbPinMap = map[string]int{ "P9_31": 110, } -var bbbPwmPinMap = map[string]pwmPinData{ +var bbbPwmPinMap = map[string]pwmPinDefinition{ "P8_13": { dir: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1, }, @@ -73,12 +73,12 @@ var bbbPwmPinMap = map[string]pwmPinData{ }, } -var bbbAnalogPinMap = map[string]string{ - "P9_39": "in_voltage0_raw", - "P9_40": "in_voltage1_raw", - "P9_37": "in_voltage2_raw", - "P9_38": "in_voltage3_raw", - "P9_33": "in_voltage4_raw", - "P9_36": "in_voltage5_raw", - "P9_35": "in_voltage6_raw", +var bbbAnalogPinMap = map[string]analogPinDefinition{ + "P9_39": {path: "/sys/bus/iio/devices/iio:device0/in_voltage0_raw", r: true, w: false, bufLen: 1024}, + "P9_40": {path: "/sys/bus/iio/devices/iio:device0/in_voltage1_raw", r: true, w: false, bufLen: 1024}, + "P9_37": {path: "/sys/bus/iio/devices/iio:device0/in_voltage2_raw", r: true, w: false, bufLen: 1024}, + "P9_38": {path: "/sys/bus/iio/devices/iio:device0/in_voltage3_raw", r: true, w: false, bufLen: 1024}, + "P9_33": {path: "/sys/bus/iio/devices/iio:device0/in_voltage4_raw", r: true, w: false, bufLen: 1024}, + "P9_36": {path: "/sys/bus/iio/devices/iio:device0/in_voltage5_raw", r: true, w: false, bufLen: 1024}, + "P9_35": {path: "/sys/bus/iio/devices/iio:device0/in_voltage6_raw", r: true, w: false, bufLen: 1024}, } diff --git a/platforms/beaglebone/pocketbeagle_pins.go b/platforms/beaglebone/pocketbeagle_pins.go index b138c3e60..c94dd42ad 100644 --- a/platforms/beaglebone/pocketbeagle_pins.go +++ b/platforms/beaglebone/pocketbeagle_pins.go @@ -76,7 +76,7 @@ var pocketBeaglePinMap = map[string]int{ // P2_36 - AIO7 } -var pocketBeaglePwmPinMap = map[string]pwmPinData{ +var pocketBeaglePwmPinMap = map[string]pwmPinDefinition{ "P1_33": {dir: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1}, "P1_36": {dir: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 0}, @@ -84,11 +84,11 @@ var pocketBeaglePwmPinMap = map[string]pwmPinData{ "P2_3": {dir: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/", dirRegexp: "pwmchip[0-9]+$", channel: 1}, } -var pocketBeagleAnalogPinMap = map[string]string{ - "P1_19": "in_voltage0_raw", - "P1_21": "in_voltage1_raw", - "P1_23": "in_voltage2_raw", - "P1_25": "in_voltage3_raw", - "P1_27": "in_voltage4_raw", - "P2_36": "in_voltage7_raw", +var pocketBeagleAnalogPinMap = map[string]analogPinDefinition{ + "P1_19": {path: "/sys/bus/iio/devices/iio:device0/in_voltage0_raw", r: true, w: false, bufLen: 1024}, + "P1_21": {path: "/sys/bus/iio/devices/iio:device0/in_voltage1_raw", r: true, w: false, bufLen: 1024}, + "P1_23": {path: "/sys/bus/iio/devices/iio:device0/in_voltage2_raw", r: true, w: false, bufLen: 1024}, + "P1_25": {path: "/sys/bus/iio/devices/iio:device0/in_voltage3_raw", r: true, w: false, bufLen: 1024}, + "P1_27": {path: "/sys/bus/iio/devices/iio:device0/in_voltage4_raw", r: true, w: false, bufLen: 1024}, + "P2_36": {path: "/sys/bus/iio/devices/iio:device0/in_voltage7_raw", r: true, w: false, bufLen: 1024}, } diff --git a/platforms/intel-iot/edison/edison_adaptor.go b/platforms/intel-iot/edison/edison_adaptor.go index 17a7b24ff..07a1ca76c 100644 --- a/platforms/intel-iot/edison/edison_adaptor.go +++ b/platforms/intel-iot/edison/edison_adaptor.go @@ -40,6 +40,7 @@ type Adaptor struct { pinmap map[string]sysfsPin tristate gobot.DigitalPinner digitalPins map[int]gobot.DigitalPinner + *adaptors.AnalogPinsAdaptor *adaptors.PWMPinsAdaptor *adaptors.I2cBusAdaptor arduinoI2cInitialized bool @@ -58,6 +59,7 @@ func NewAdaptor(boardType ...string) *Adaptor { if len(boardType) > 0 && boardType[0] != "" { c.board = boardType[0] } + c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translateAndMuxPWMPin, adaptors.WithPWMPinInitializer(pwmPinInitializer)) defI2cBusNr := defaultI2cBusNumber @@ -82,6 +84,10 @@ func (c *Adaptor) Connect() error { return err } + if err := c.AnalogPinsAdaptor.Connect(); err != nil { + return err + } + if err := c.PWMPinsAdaptor.Connect(); err != nil { return err } @@ -127,6 +133,10 @@ func (c *Adaptor) Finalize() error { err = multierror.Append(err, e) } + if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + err = multierror.Append(err, e) + } + if e := c.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } @@ -165,14 +175,12 @@ func (c *Adaptor) DigitalPin(id string) (gobot.DigitalPinner, error) { // AnalogRead returns value from analog reading of specified pin func (c *Adaptor) AnalogRead(pin string) (int, error) { - buf, err := c.readFile("/sys/bus/iio/devices/iio:device1/in_voltage" + pin + "_raw") + rawRead, err := c.AnalogPinsAdaptor.AnalogRead(pin) if err != nil { return 0, err } - val, err := strconv.Atoi(string(buf[0 : len(buf)-1])) - - return val / 4, err + return rawRead / 4, err } func (c *Adaptor) validateAndSetupI2cBusNumber(busNr int) error { @@ -263,22 +271,6 @@ func (c *Adaptor) arduinoI2CSetup() error { return c.tristate.Write(system.HIGH) } -func (c *Adaptor) readFile(path string) ([]byte, error) { - file, err := c.sys.OpenFile(path, os.O_RDONLY, 0o644) - defer file.Close() //nolint:staticcheck // for historical reasons - if err != nil { - return make([]byte, 0), err - } - - buf := make([]byte, 200) - var i int - i, err = file.Read(buf) - if i == 0 { - return buf, err - } - return buf[:i], err -} - func (c *Adaptor) digitalPin(id string, o ...func(gobot.DigitalPinOptioner) bool) (gobot.DigitalPinner, error) { i := c.pinmap[id] @@ -347,6 +339,16 @@ func pwmPinInitializer(pin gobot.PWMPinner) error { return pin.SetEnabled(true) } +func (c *Adaptor) translateAnalogPin(pin string) (string, bool, bool, uint16, error) { + path := fmt.Sprintf("/sys/bus/iio/devices/iio:device1/in_voltage%s_raw", pin) + const ( + read = true + write = false + readBufLen = 200 + ) + return path, read, write, readBufLen, nil +} + func (c *Adaptor) translateAndMuxPWMPin(id string) (string, int, error) { sysPin, ok := c.pinmap[id] if !ok { diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index 6709d9991..8451d949e 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -364,7 +364,7 @@ func TestFinalize(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") _ = a.DigitalWrite("3", 1) - _ = a.PwmWrite("5", 100) + require.NoError(t, a.PwmWrite("5", 100)) _, _ = a.GetI2cConnection(0xff, 6) require.NoError(t, a.Finalize()) @@ -373,7 +373,7 @@ func TestFinalize(t *testing.T) { require.NoError(t, a.Finalize()) // assert that re-connect is working - _ = a.Connect() + require.NoError(t, a.Connect()) // remove one file to force Finalize error delete(fs.Files, "/sys/class/gpio/unexport") err := a.Finalize() @@ -384,7 +384,7 @@ func TestFinalize(t *testing.T) { func TestFinalizeError(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - _ = a.PwmWrite("5", 100) + require.NoError(t, a.PwmWrite("5", 100)) fs.WithWriteError = true err := a.Finalize() @@ -397,10 +397,10 @@ func TestFinalizeError(t *testing.T) { func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") - _ = a.DigitalWrite("13", 1) + require.NoError(t, a.DigitalWrite("13", 1)) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio40/value"].Contents) - _ = a.DigitalWrite("2", 0) + require.NoError(t, a.DigitalWrite("2", 0)) i, err := a.DigitalRead("2") require.NoError(t, err) assert.Equal(t, 0, i) @@ -411,7 +411,7 @@ func TestDigitalPinInFileError(t *testing.T) { fs := a.sys.UseMockFilesystem(pwmMockPathsMux40) delete(fs.Files, "/sys/class/gpio/gpio40/value") delete(fs.Files, "/sys/class/gpio/gpio40/direction") - _ = a.Connect() + _ = a.Connect() // we drop this error _, err := a.DigitalPin("13") require.ErrorContains(t, err, "no such file") @@ -422,7 +422,7 @@ func TestDigitalPinInResistorFileError(t *testing.T) { fs := a.sys.UseMockFilesystem(pwmMockPathsMux40) delete(fs.Files, "/sys/class/gpio/gpio229/value") delete(fs.Files, "/sys/class/gpio/gpio229/direction") - _ = a.Connect() + _ = a.Connect() // we drop this error _, err := a.DigitalPin("13") require.ErrorContains(t, err, "no such file") @@ -433,7 +433,7 @@ func TestDigitalPinInLevelShifterFileError(t *testing.T) { fs := a.sys.UseMockFilesystem(pwmMockPathsMux40) delete(fs.Files, "/sys/class/gpio/gpio261/value") delete(fs.Files, "/sys/class/gpio/gpio261/direction") - _ = a.Connect() + _ = a.Connect() // we drop this error _, err := a.DigitalPin("13") require.ErrorContains(t, err, "no such file") @@ -444,7 +444,7 @@ func TestDigitalPinInMuxFileError(t *testing.T) { fs := a.sys.UseMockFilesystem(pwmMockPathsMux40) delete(fs.Files, "/sys/class/gpio/gpio243/value") delete(fs.Files, "/sys/class/gpio/gpio243/direction") - _ = a.Connect() + _ = a.Connect() // we drop this error _, err := a.DigitalPin("13") require.ErrorContains(t, err, "no such file") @@ -492,7 +492,7 @@ func TestPwmEnableError(t *testing.T) { a := NewAdaptor() fs := a.sys.UseMockFilesystem(pwmMockPathsMux13) delete(fs.Files, "/sys/class/pwm/pwmchip0/pwm1/enable") - _ = a.Connect() + _ = a.Connect() // we drop this error err := a.PwmWrite("5", 100) require.ErrorContains(t, err, "/sys/class/pwm/pwmchip0/pwm1/enable: no such file") @@ -526,7 +526,8 @@ func TestAnalog(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem("arduino") fs.Files["/sys/bus/iio/devices/iio:device1/in_voltage0_raw"].Contents = "1000\n" - i, _ := a.AnalogRead("0") + i, err := a.AnalogRead("0") + require.NoError(t, err) assert.Equal(t, 250, i) } diff --git a/system/PWM.md b/system/PWM.md index 949fce02b..971673829 100644 --- a/system/PWM.md +++ b/system/PWM.md @@ -93,3 +93,5 @@ Now we should measure a value of around 2.3V with the meter, which is the differ If we have attached an oscilloscope we can play around with the values for period and duty_cycle and see what happen. ## Links + +* diff --git a/system/analogpin_sysfs.go b/system/analogpin_sysfs.go new file mode 100644 index 000000000..016f8be3c --- /dev/null +++ b/system/analogpin_sysfs.go @@ -0,0 +1,37 @@ +package system + +import "fmt" + +type analogPinSysFs struct { + sysfsPath string + r, w bool + sfa *sysfsFileAccess +} + +func newAnalogPinSysfs(sfa *sysfsFileAccess, path string, r, w bool) *analogPinSysFs { + p := &analogPinSysFs{ + sysfsPath: path, + sfa: sfa, + r: r, + w: w, + } + return p +} + +// Read reads a value from sysf path +func (p *analogPinSysFs) Read() (int, error) { + if !p.r { + return 0, fmt.Errorf("the pin '%s' is not allowed to read", p.sysfsPath) + } + + return p.sfa.readInteger(p.sysfsPath) +} + +// Write writes a value to sysf path +func (p *analogPinSysFs) Write(val int) error { + if !p.w { + return fmt.Errorf("the pin '%s' is not allowed to write (val: %v)", p.sysfsPath, val) + } + + return p.sfa.writeInteger(p.sysfsPath, val) +} diff --git a/system/analogpin_sysfs_test.go b/system/analogpin_sysfs_test.go new file mode 100644 index 000000000..4551ea7ff --- /dev/null +++ b/system/analogpin_sysfs_test.go @@ -0,0 +1,121 @@ +package system + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_newAnalogPinSysfs(t *testing.T) { + // arrange + m := &MockFilesystem{} + sfa := sysfsFileAccess{fs: m, readBufLen: 2} + const path = "/sys/whatever" + // act + pin := newAnalogPinSysfs(&sfa, path, true, false) + // assert + assert.Equal(t, path, pin.sysfsPath) + assert.Equal(t, &sfa, pin.sfa) + assert.True(t, pin.r) + assert.False(t, pin.w) +} + +func TestRead(t *testing.T) { + const ( + sysfsPath = "/sys/testread" + value = "32" + ) + tests := map[string]struct { + readable bool + simErr bool + wantVal int + wantErr string + }{ + "read_ok": { + readable: true, + wantVal: 32, + }, + "error_not_readable": { + readable: false, + wantErr: "the pin '/sys/testread' is not allowed to read", + }, + "error_on_read": { + readable: true, + simErr: true, + wantErr: "read error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + fs := newMockFilesystem([]string{sysfsPath}) + sfa := sysfsFileAccess{fs: fs, readBufLen: 2} + pin := newAnalogPinSysfs(&sfa, sysfsPath, tc.readable, false) + fs.Files[sysfsPath].Contents = value + if tc.simErr { + fs.Files[sysfsPath].simulateReadError = fmt.Errorf("read error") + } + // act + got, err := pin.Read() + // assert + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + } else { + require.NoError(t, err) + } + assert.Equal(t, tc.wantVal, got) + }) + } +} + +func TestWrite(t *testing.T) { + const ( + sysfsPath = "/sys/testwrite" + oldVal = "old_value" + ) + tests := map[string]struct { + writeable bool + simErr bool + wantVal string + wantErr string + }{ + "write_ok": { + writeable: true, + wantVal: "23", + }, + "error_not_writeable": { + writeable: false, + wantErr: "the pin '/sys/testwrite' is not allowed to write (val: 23)", + wantVal: oldVal, + }, + "error_on_write": { + writeable: true, + simErr: true, + wantErr: "write error", + wantVal: "23", // the mock is implemented in this way + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + fs := newMockFilesystem([]string{sysfsPath}) + sfa := sysfsFileAccess{fs: fs, readBufLen: 10} + pin := newAnalogPinSysfs(&sfa, sysfsPath, false, tc.writeable) + fs.Files[sysfsPath].Contents = oldVal + if tc.simErr { + fs.Files[sysfsPath].simulateWriteError = fmt.Errorf("write error") + } + // act + err := pin.Write(23) + // assert + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + } else { + require.NoError(t, err) + } + assert.Equal(t, tc.wantVal, fs.Files[sysfsPath].Contents) + }) + } +} diff --git a/system/digitalpin_access.go b/system/digitalpin_access.go index 9ba351338..fa2a3c536 100644 --- a/system/digitalpin_access.go +++ b/system/digitalpin_access.go @@ -8,7 +8,7 @@ import ( // sysfsDitalPinHandler represents the sysfs implementation type sysfsDigitalPinAccess struct { - fs filesystem + sfa *sysfsFileAccess } // gpiodDigitalPinAccess represents the character device implementation @@ -25,11 +25,11 @@ func (h *sysfsDigitalPinAccess) isSupported() bool { func (h *sysfsDigitalPinAccess) createPin(chip string, pin int, o ...func(gobot.DigitalPinOptioner) bool, ) gobot.DigitalPinner { - return newDigitalPinSysfs(h.fs, strconv.Itoa(pin), o...) + return newDigitalPinSysfs(h.sfa, strconv.Itoa(pin), o...) } func (h *sysfsDigitalPinAccess) setFs(fs filesystem) { - h.fs = fs + h.sfa = &sysfsFileAccess{fs: fs, readBufLen: 2} } func (h *gpiodDigitalPinAccess) isSupported() bool { diff --git a/system/digitalpin_sysfs.go b/system/digitalpin_sysfs.go index 9c0e89c8c..e7c0230d2 100644 --- a/system/digitalpin_sysfs.go +++ b/system/digitalpin_sysfs.go @@ -3,7 +3,6 @@ package system import ( "errors" "fmt" - "io" "log" "os" "strconv" @@ -24,21 +23,25 @@ var errNotExported = errors.New("pin has not been exported") type digitalPinSysfs struct { pin string *digitalPinConfig - fs filesystem + sfa *sysfsFileAccess - dirFile File - valFile File - activeLowFile File + dirFile *sysfsFile + valFile *sysfsFile + activeLowFile *sysfsFile } // newDigitalPinSysfs returns a digital pin using for the given number. The name of the sysfs file will prepend "gpio" // to the pin number, eg. a pin number of 10 will have a name of "gpio10". The pin is handled by the sysfs Kernel ABI. -func newDigitalPinSysfs(fs filesystem, pin string, options ...func(gobot.DigitalPinOptioner) bool) *digitalPinSysfs { +func newDigitalPinSysfs( + sfa *sysfsFileAccess, + pin string, + options ...func(gobot.DigitalPinOptioner) bool, +) *digitalPinSysfs { cfg := newDigitalPinConfig("gpio"+pin, options...) d := &digitalPinSysfs{ pin: pin, digitalPinConfig: cfg, - fs: fs, + sfa: sfa, } return d } @@ -68,26 +71,26 @@ func (d *digitalPinSysfs) Export() error { // Unexport release the pin func (d *digitalPinSysfs) Unexport() error { - unexport, err := d.fs.openFile(gpioPath+"/unexport", os.O_WRONLY, 0o644) + unexport, err := d.sfa.openWrite(gpioPath + "/unexport") if err != nil { return err } - defer unexport.Close() + defer unexport.close() if d.dirFile != nil { - d.dirFile.Close() + d.dirFile.close() d.dirFile = nil } if d.valFile != nil { - d.valFile.Close() + d.valFile.close() d.valFile = nil } if d.activeLowFile != nil { - d.activeLowFile.Close() + d.activeLowFile.close() d.activeLowFile = nil } - err = writeFile(unexport, []byte(d.pin)) + err = unexport.write([]byte(d.pin)) if err != nil { // If EINVAL then the pin is reserved in the system and can't be unexported, we suppress the error var pathError *os.PathError @@ -101,13 +104,19 @@ func (d *digitalPinSysfs) Unexport() error { // Write writes the given value to the character device func (d *digitalPinSysfs) Write(b int) error { - err := writeFile(d.valFile, []byte(strconv.Itoa(b))) + if d.valFile == nil { + return errNotExported + } + err := d.valFile.write([]byte(strconv.Itoa(b))) return err } -// Read reads the given value from character device +// Read reads a value from character device func (d *digitalPinSysfs) Read() (int, error) { - buf, err := readFile(d.valFile) + if d.valFile == nil { + return 0, errNotExported + } + buf, err := d.valFile.read() if err != nil { return 0, err } @@ -115,13 +124,13 @@ func (d *digitalPinSysfs) Read() (int, error) { } func (d *digitalPinSysfs) reconfigure() error { - exportFile, err := d.fs.openFile(gpioPath+"/export", os.O_WRONLY, 0o644) + exportFile, err := d.sfa.openWrite(gpioPath + "/export") if err != nil { return err } - defer exportFile.Close() + defer exportFile.close() - err = writeFile(exportFile, []byte(d.pin)) + err = exportFile.write([]byte(d.pin)) if err != nil { // If EBUSY then the pin has already been exported, we suppress the error var pathError *os.PathError @@ -131,13 +140,13 @@ func (d *digitalPinSysfs) reconfigure() error { } if d.dirFile != nil { - d.dirFile.Close() + d.dirFile.close() } attempt := 0 for { attempt++ - d.dirFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/direction", gpioPath, d.label), os.O_RDWR, 0o644) + d.dirFile, err = d.sfa.openReadWrite(fmt.Sprintf("%s/%s/direction", gpioPath, d.label)) if err == nil { break } @@ -148,10 +157,10 @@ func (d *digitalPinSysfs) reconfigure() error { } if d.valFile != nil { - d.valFile.Close() + d.valFile.close() } if err == nil { - d.valFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/value", gpioPath, d.label), os.O_RDWR, 0o644) + d.valFile, err = d.sfa.openReadWrite(fmt.Sprintf("%s/%s/value", gpioPath, d.label)) } // configure direction @@ -162,9 +171,9 @@ func (d *digitalPinSysfs) reconfigure() error { // configure inverse logic if err == nil { if d.activeLow { - d.activeLowFile, err = d.fs.openFile(fmt.Sprintf("%s/%s/active_low", gpioPath, d.label), os.O_RDWR, 0o644) + d.activeLowFile, err = d.sfa.openReadWrite(fmt.Sprintf("%s/%s/active_low", gpioPath, d.label)) if err == nil { - err = writeFile(d.activeLowFile, []byte("1")) + err = d.activeLowFile.write([]byte("1")) } } } @@ -211,48 +220,16 @@ func (d *digitalPinSysfs) reconfigure() error { } func (d *digitalPinSysfs) writeDirectionWithInitialOutput() error { - if err := writeFile(d.dirFile, []byte(d.direction)); err != nil || d.direction == IN { + if d.dirFile == nil { + return errNotExported + } + if err := d.dirFile.write([]byte(d.direction)); err != nil || d.direction == IN { return err } - err := writeFile(d.valFile, []byte(strconv.Itoa(d.outInitialState))) - return err -} -// Linux sysfs / GPIO specific sysfs docs. -// https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt -// https://www.kernel.org/doc/Documentation/gpio/sysfs.txt - -var writeFile = func(f File, data []byte) error { - if f == nil { + if d.valFile == nil { return errNotExported } - // sysfs docs say: - // > When writing sysfs files, userspace processes should first read the - // > entire file, modify the values it wishes to change, then write the - // > entire buffer back. - // however, this seems outdated/inaccurate (docs are from back in the Kernel BitKeeper days). - - // Write() returns already a non-nil error when n != len(b). - _, err := f.Write(data) - return err -} - -var readFile = func(f File) ([]byte, error) { - if f == nil { - return nil, errNotExported - } - - // sysfs docs say: - // > If userspace seeks back to zero or does a pread(2) with an offset of '0' the [..] method will - // > be called again, rearmed, to fill the buffer. - - // TODO: Examine if seek is needed if full buffer is read from sysfs file. - - buf := make([]byte, 2) - _, err := f.Seek(0, io.SeekStart) - if err == nil { - _, err = f.Read(buf) - } - return buf, err + return d.valFile.write([]byte(strconv.Itoa(d.outInitialState))) } diff --git a/system/digitalpin_sysfs_test.go b/system/digitalpin_sysfs_test.go index 6f6473ac9..ca617f7be 100644 --- a/system/digitalpin_sysfs_test.go +++ b/system/digitalpin_sysfs_test.go @@ -21,19 +21,21 @@ var ( func initTestDigitalPinSysfsWithMockedFilesystem(mockPaths []string) (*digitalPinSysfs, *MockFilesystem) { fs := newMockFilesystem(mockPaths) - pin := newDigitalPinSysfs(fs, "10") + sfa := sysfsFileAccess{fs: fs, readBufLen: 2} + pin := newDigitalPinSysfs(&sfa, "10") return pin, fs } func Test_newDigitalPinSysfs(t *testing.T) { // arrange m := &MockFilesystem{} + sfa := sysfsFileAccess{fs: m, readBufLen: 2} const pinID = "1" // act - pin := newDigitalPinSysfs(m, pinID, WithPinOpenDrain()) + pin := newDigitalPinSysfs(&sfa, pinID, WithPinOpenDrain()) // assert assert.Equal(t, pinID, pin.pin) - assert.Equal(t, m, pin.fs) + assert.Equal(t, &sfa, pin.sfa) assert.Equal(t, "gpio"+pinID, pin.label) assert.Equal(t, "in", pin.direction) assert.Equal(t, 1, pin.drive) @@ -134,7 +136,7 @@ func TestDigitalPinExportSysfs(t *testing.T) { changeDebouncePeriod time.Duration changeEdge int changePollInterval time.Duration - simEbusyOnWrite int + simEbusyOnPath string wantWrites int wantExport string wantUnexport string @@ -225,11 +227,11 @@ func TestDigitalPinExportSysfs(t *testing.T) { wantValue: "0", }, "ok_already_exported": { - mockPaths: allMockPaths, - wantWrites: 2, - wantExport: "10", - wantDirection: "in", - simEbusyOnWrite: 1, // just means "already exported" + mockPaths: allMockPaths, + wantWrites: 2, + wantExport: "10", + wantDirection: "in", + simEbusyOnPath: exportPath, // just means "already exported" }, "error_no_eventhandler_for_polling": { // this only tests the call of function, all other is tested separately mockPaths: allMockPaths, @@ -250,11 +252,11 @@ func TestDigitalPinExportSysfs(t *testing.T) { wantErr: "gpio10/direction: no such file", }, "error_write_direction_file": { - mockPaths: allMockPaths, - wantWrites: 3, - wantUnexport: "10", - simEbusyOnWrite: 2, - wantErr: "device or resource busy", + mockPaths: allMockPaths, + wantWrites: 3, + wantUnexport: "10", + simEbusyOnPath: dirPath, + wantErr: "device or resource busy", }, "error_no_value_file": { mockPaths: []string{exportPath, dirPath, unexportPath}, @@ -281,7 +283,8 @@ func TestDigitalPinExportSysfs(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange fs := newMockFilesystem(tc.mockPaths) - pin := newDigitalPinSysfs(fs, "10") + sfa := sysfsFileAccess{fs: fs, readBufLen: 2} + pin := newDigitalPinSysfs(&sfa, "10") if tc.changeDirection != "" { pin.direction = tc.changeDirection } @@ -307,17 +310,9 @@ func TestDigitalPinExportSysfs(t *testing.T) { pin.pollInterval = tc.changePollInterval } // arrange write function - oldWriteFunc := writeFile - numCallsWrite := 0 - writeFile = func(f File, data []byte) error { - numCallsWrite++ - require.NoError(t, oldWriteFunc(f, data)) - if numCallsWrite == tc.simEbusyOnWrite { - return &os.PathError{Err: Syscall_EBUSY} - } - return nil + if tc.simEbusyOnPath != "" { + fs.Files[tc.simEbusyOnPath].simulateWriteError = &os.PathError{Err: Syscall_EBUSY} } - defer func() { writeFile = oldWriteFunc }() // act err := pin.Export() // assert @@ -333,7 +328,7 @@ func TestDigitalPinExportSysfs(t *testing.T) { assert.Equal(t, tc.wantInverse, fs.Files[inversePath].Contents) } assert.Equal(t, tc.wantUnexport, fs.Files[unexportPath].Contents) - assert.Equal(t, tc.wantWrites, numCallsWrite) + assert.Equal(t, tc.wantWrites, fs.numCallsWrite) }) } } @@ -368,7 +363,8 @@ func TestDigitalPinSysfs(t *testing.T) { data, _ := pin.Read() assert.Equal(t, 1, data) - pin2 := newDigitalPinSysfs(fs, "30") + sfa := sysfsFileAccess{fs: fs, readBufLen: 2} + pin2 := newDigitalPinSysfs(&sfa, "30") err = pin2.Write(1) require.ErrorContains(t, err, "pin has not been exported") @@ -376,33 +372,47 @@ func TestDigitalPinSysfs(t *testing.T) { require.ErrorContains(t, err, "pin has not been exported") assert.Equal(t, 0, data) - writeFile = func(File, []byte) error { - return &os.PathError{Err: Syscall_EINVAL} - } - - err = pin.Unexport() - require.NoError(t, err) - - writeFile = func(File, []byte) error { - return &os.PathError{Err: errors.New("write error")} - } - + // arrange: unexport general write error, the error is not suppressed + fs.Files["/sys/class/gpio/unexport"].simulateWriteError = &os.PathError{Err: errors.New("write error")} + // act: unexport err = pin.Unexport() + // assert: the error is not suppressed var pathError *os.PathError require.ErrorAs(t, err, &pathError) require.ErrorContains(t, err, "write error") } func TestDigitalPinUnexportErrorSysfs(t *testing.T) { - mockPaths := []string{ - "/sys/class/gpio/unexport", + tests := map[string]struct { + simulateError error + wantErr string + }{ + "reserved_pin": { + // simulation of reserved pin, the internal error is suppressed + simulateError: &os.PathError{Err: Syscall_EINVAL}, + wantErr: "", + }, + "error_busy": { + simulateError: &os.PathError{Err: Syscall_EBUSY}, + wantErr: " : device or resource busy", + }, } - pin, _ := initTestDigitalPinSysfsWithMockedFilesystem(mockPaths) - - writeFile = func(File, []byte) error { - return &os.PathError{Err: Syscall_EBUSY} + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + mockPaths := []string{ + "/sys/class/gpio/unexport", + } + pin, fs := initTestDigitalPinSysfsWithMockedFilesystem(mockPaths) + fs.Files["/sys/class/gpio/unexport"].simulateWriteError = tc.simulateError + // act + err := pin.Unexport() + // assert + if tc.wantErr != "" { + require.ErrorContains(t, err, tc.wantErr) + } else { + require.NoError(t, err) + } + }) } - - err := pin.Unexport() - require.ErrorContains(t, err, " : device or resource busy") } diff --git a/system/fs_mock.go b/system/fs_mock.go index d91c4383e..afcb11a3f 100644 --- a/system/fs_mock.go +++ b/system/fs_mock.go @@ -2,6 +2,7 @@ package system import ( "fmt" + "log" "os" "path" "regexp" @@ -21,16 +22,20 @@ type MockFilesystem struct { WithReadError bool WithWriteError bool WithCloseError bool + numCallsWrite int + numCallsRead int } // A MockFile represents a mock file that contains a single string. Any write // overwrites, and any read returns from the start. type MockFile struct { - Contents string - Seq int // When this file was last written or read. - Opened bool - Closed bool - fd uintptr + Contents string + Seq int // When this file was last written or read. + Opened bool + Closed bool + fd uintptr + simulateWriteError error + simulateReadError error fs *MockFilesystem } @@ -46,6 +51,7 @@ func (f *MockFile) Write(b []byte) (int, error) { if f.fs.WithWriteError { return 0, errWrite } + return f.WriteString(string(b)) } @@ -58,7 +64,8 @@ func (f *MockFile) Seek(offset int64, whence int) (int64, error) { func (f *MockFile) WriteString(s string) (int, error) { f.Contents = s f.Seq = f.fs.next() - return len(s), nil + f.fs.numCallsWrite++ + return len(s), f.simulateWriteError } // Sync implements the File interface Sync function @@ -79,7 +86,8 @@ func (f *MockFile) Read(b []byte) (int, error) { copy(b, []byte(f.Contents)[:count]) f.Seq = f.fs.next() - return count, nil + f.fs.numCallsRead++ + return count, f.simulateReadError } // ReadAt calls MockFile.Read @@ -135,9 +143,10 @@ func (fs *MockFilesystem) openFile(name string, _ int, _ os.FileMode) (File, err func (fs *MockFilesystem) stat(name string) (os.FileInfo, error) { _, ok := fs.Files[name] if ok { - // return file based mock FileInfo - tmpFile, err := os.CreateTemp("", name) + // return file based mock FileInfo, CreateTemp don't like "/" in between + tmpFile, err := os.CreateTemp("", strings.ReplaceAll(name, "/", "_")) if err != nil { + log.Println("A") return nil, err } defer os.Remove(tmpFile.Name()) @@ -194,6 +203,8 @@ func (fs *MockFilesystem) readFile(name string) ([]byte, error) { if !ok { return nil, &os.PathError{Err: fmt.Errorf("%s: no such file", name)} } + + f.fs.numCallsRead++ return []byte(f.Contents), nil } diff --git a/system/pwmpin_sysfs.go b/system/pwmpin_sysfs.go index a038e469f..b31a9484a 100644 --- a/system/pwmpin_sysfs.go +++ b/system/pwmpin_sysfs.go @@ -24,30 +24,25 @@ type pwmPinSysFs struct { polarityNormalIdentifier string polarityInvertedIdentifier string - write func(fs filesystem, path string, data []byte) (i int, err error) - read func(fs filesystem, path string) ([]byte, error) - fs filesystem + sfa *sysfsFileAccess } // newPWMPinSysfs returns a new pwmPin, working with sysfs file access. -func newPWMPinSysfs(fs filesystem, path string, pin int, polNormIdent string, polInvIdent string) *pwmPinSysFs { +func newPWMPinSysfs(sfa *sysfsFileAccess, path string, pin int, polNormIdent string, polInvIdent string) *pwmPinSysFs { p := &pwmPinSysFs{ path: path, pin: strconv.Itoa(pin), polarityNormalIdentifier: polNormIdent, polarityInvertedIdentifier: polInvIdent, - read: readPwmFile, - write: writePwmFile, - fs: fs, + sfa: sfa, } return p } // Export exports the pin for use by the operating system by writing the pin to the "Export" path func (p *pwmPinSysFs) Export() error { - _, err := p.write(p.fs, p.pwmExportPath(), []byte(p.pin)) - if err != nil { + if err := p.sfa.write(p.pwmExportPath(), []byte(p.pin)); err != nil { // If EBUSY then the pin has already been exported, we suppress the error var pathError *os.PathError if !(errors.As(err, &pathError) && errors.Is(err, Syscall_EBUSY)) { @@ -65,7 +60,7 @@ func (p *pwmPinSysFs) Export() error { // Unexport releases the pin from the operating system by writing the pin to the "Unexport" path func (p *pwmPinSysFs) Unexport() error { - if _, err := p.write(p.fs, p.pwmUnexportPath(), []byte(p.pin)); err != nil { + if err := p.sfa.write(p.pwmUnexportPath(), []byte(p.pin)); err != nil { return fmt.Errorf(pwmPinErrorPattern, "Unexport", p.pin, err) } return nil @@ -73,16 +68,12 @@ func (p *pwmPinSysFs) Unexport() error { // Enabled reads and returns the enabled state of the pin func (p *pwmPinSysFs) Enabled() (bool, error) { - buf, err := p.read(p.fs, p.pwmEnablePath()) + val, err := p.sfa.readInteger(p.pwmEnablePath()) if err != nil { return false, fmt.Errorf(pwmPinErrorPattern, "Enabled", p.pin, err) } - if len(buf) == 0 { - return false, nil - } - val, e := strconv.Atoi(string(bytes.TrimRight(buf, "\n"))) - return val > 0, e + return val > 0, nil } // SetEnabled writes enable(1) or disable(0) status. For most platforms this is only possible if period was @@ -92,7 +83,7 @@ func (p *pwmPinSysFs) SetEnabled(enable bool) error { if enable { enableVal = 1 } - if _, err := p.write(p.fs, p.pwmEnablePath(), []byte(strconv.Itoa(enableVal))); err != nil { + if err := p.sfa.writeInteger(p.pwmEnablePath(), enableVal); err != nil { if pwmDebug { p.printState() } @@ -104,7 +95,7 @@ func (p *pwmPinSysFs) SetEnabled(enable bool) error { // Polarity reads and returns false if the polarity is inverted, otherwise true func (p *pwmPinSysFs) Polarity() (bool, error) { - buf, err := p.read(p.fs, p.pwmPolarityPath()) + buf, err := p.sfa.read(p.pwmPolarityPath()) if err != nil { return true, fmt.Errorf(pwmPinErrorPattern, "Polarity", p.pin, err) } @@ -133,7 +124,7 @@ func (p *pwmPinSysFs) SetPolarity(normal bool) error { if !normal { value = p.polarityInvertedIdentifier } - if _, err := p.write(p.fs, p.pwmPolarityPath(), []byte(value)); err != nil { + if err := p.sfa.write(p.pwmPolarityPath(), []byte(value)); err != nil { if pwmDebug { p.printState() } @@ -144,23 +135,17 @@ func (p *pwmPinSysFs) SetPolarity(normal bool) error { // Period returns the current period func (p *pwmPinSysFs) Period() (uint32, error) { - buf, err := p.read(p.fs, p.pwmPeriodPath()) + val, err := p.sfa.readInteger(p.pwmPeriodPath()) if err != nil { return 0, fmt.Errorf(pwmPinErrorPattern, "Period", p.pin, err) } - if len(buf) == 0 { - return 0, nil - } - v := bytes.TrimRight(buf, "\n") - val, e := strconv.Atoi(string(v)) - return uint32(val), e + return uint32(val), nil } // SetPeriod writes the current period in nanoseconds func (p *pwmPinSysFs) SetPeriod(period uint32) error { - //nolint:perfsprint // ok here - if _, err := p.write(p.fs, p.pwmPeriodPath(), []byte(fmt.Sprintf("%v", period))); err != nil { + if err := p.sfa.writeInteger(p.pwmPeriodPath(), int(period)); err != nil { if pwmDebug { p.printState() @@ -172,19 +157,17 @@ func (p *pwmPinSysFs) SetPeriod(period uint32) error { // DutyCycle reads and returns the duty cycle in nanoseconds func (p *pwmPinSysFs) DutyCycle() (uint32, error) { - buf, err := p.read(p.fs, p.pwmDutyCyclePath()) + val, err := p.sfa.readInteger(p.pwmDutyCyclePath()) if err != nil { return 0, fmt.Errorf(pwmPinErrorPattern, "DutyCycle", p.pin, err) } - val, err := strconv.Atoi(string(bytes.TrimRight(buf, "\n"))) return uint32(val), err } // SetDutyCycle writes the duty cycle in nanoseconds func (p *pwmPinSysFs) SetDutyCycle(duty uint32) error { - //nolint:perfsprint // ok here - if _, err := p.write(p.fs, p.pwmDutyCyclePath(), []byte(fmt.Sprintf("%v", duty))); err != nil { + if err := p.sfa.writeInteger(p.pwmDutyCyclePath(), int(duty)); err != nil { if pwmDebug { p.printState() } @@ -223,32 +206,6 @@ func (p *pwmPinSysFs) pwmPolarityPath() string { return path.Join(p.path, "pwm"+p.pin, "polarity") } -func writePwmFile(fs filesystem, path string, data []byte) (int, error) { - file, err := fs.openFile(path, os.O_WRONLY, 0o644) - defer file.Close() //nolint:staticcheck // for historical reasons - if err != nil { - return 0, err - } - - return file.Write(data) -} - -func readPwmFile(fs filesystem, path string) ([]byte, error) { - file, err := fs.openFile(path, os.O_RDONLY, 0o644) - defer file.Close() //nolint:staticcheck // for historical reasons - if err != nil { - return make([]byte, 0), err - } - - buf := make([]byte, 200) - var i int - i, err = file.Read(buf) - if i == 0 { - return []byte{}, err - } - return buf[:i], err -} - func (p *pwmPinSysFs) printState() { enabled, _ := p.Enabled() polarity, _ := p.Polarity() diff --git a/system/pwmpin_sysfs_test.go b/system/pwmpin_sysfs_test.go index b4c1f82c9..a9460667f 100644 --- a/system/pwmpin_sysfs_test.go +++ b/system/pwmpin_sysfs_test.go @@ -19,7 +19,8 @@ const ( func initTestPWMPinSysFsWithMockedFilesystem(mockPaths []string) (*pwmPinSysFs, *MockFilesystem) { fs := newMockFilesystem(mockPaths) - pin := newPWMPinSysfs(fs, "/sys/class/pwm/pwmchip0", 10, normal, inverted) + sfa := &sysfsFileAccess{fs: fs, readBufLen: 200} + pin := newPWMPinSysfs(sfa, "/sys/class/pwm/pwmchip0", 10, normal, inverted) return pin, fs } @@ -76,6 +77,7 @@ func TestPwmPin(t *testing.T) { } func TestPwmPinAlreadyExported(t *testing.T) { + // arrange mockedPaths := []string{ "/sys/class/pwm/pwmchip0/export", "/sys/class/pwm/pwmchip0/unexport", @@ -83,17 +85,14 @@ func TestPwmPinAlreadyExported(t *testing.T) { "/sys/class/pwm/pwmchip0/pwm10/period", "/sys/class/pwm/pwmchip0/pwm10/duty_cycle", } - pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) - - pin.write = func(filesystem, string, []byte) (int, error) { - return 0, &os.PathError{Err: Syscall_EBUSY} - } - - // no error indicates that the pin was already exported + pin, fs := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) + fs.Files["/sys/class/pwm/pwmchip0/export"].simulateWriteError = &os.PathError{Err: Syscall_EBUSY} + // act & assert: no error indicates that the pin was already exported require.NoError(t, pin.Export()) } func TestPwmPinExportError(t *testing.T) { + // arrange mockedPaths := []string{ "/sys/class/pwm/pwmchip0/export", "/sys/class/pwm/pwmchip0/unexport", @@ -101,18 +100,16 @@ func TestPwmPinExportError(t *testing.T) { "/sys/class/pwm/pwmchip0/pwm10/period", "/sys/class/pwm/pwmchip0/pwm10/duty_cycle", } - pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) - - pin.write = func(filesystem, string, []byte) (int, error) { - return 0, &os.PathError{Err: Syscall_EFAULT} - } - - // no error indicates that the pin was already exported + pin, fs := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) + fs.Files["/sys/class/pwm/pwmchip0/export"].simulateWriteError = &os.PathError{Err: Syscall_EFAULT} + // act err := pin.Export() + // assert require.ErrorContains(t, err, "Export() failed for id 10 with : bad address") } func TestPwmPinUnxportError(t *testing.T) { + // arrange mockedPaths := []string{ "/sys/class/pwm/pwmchip0/export", "/sys/class/pwm/pwmchip0/unexport", @@ -120,17 +117,16 @@ func TestPwmPinUnxportError(t *testing.T) { "/sys/class/pwm/pwmchip0/pwm10/period", "/sys/class/pwm/pwmchip0/pwm10/duty_cycle", } - pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) - - pin.write = func(filesystem, string, []byte) (int, error) { - return 0, &os.PathError{Err: Syscall_EBUSY} - } - + pin, fs := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) + fs.Files["/sys/class/pwm/pwmchip0/unexport"].simulateWriteError = &os.PathError{Err: Syscall_EBUSY} + // act err := pin.Unexport() + // assert require.ErrorContains(t, err, "Unexport() failed for id 10 with : device or resource busy") } func TestPwmPinPeriodError(t *testing.T) { + // arrange mockedPaths := []string{ "/sys/class/pwm/pwmchip0/export", "/sys/class/pwm/pwmchip0/unexport", @@ -138,35 +134,34 @@ func TestPwmPinPeriodError(t *testing.T) { "/sys/class/pwm/pwmchip0/pwm10/period", "/sys/class/pwm/pwmchip0/pwm10/duty_cycle", } - pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) - - pin.read = func(filesystem, string) ([]byte, error) { - return nil, &os.PathError{Err: Syscall_EBUSY} - } - + pin, fs := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) + fs.Files["/sys/class/pwm/pwmchip0/pwm10/period"].simulateReadError = &os.PathError{Err: Syscall_EBUSY} + // act _, err := pin.Period() + // assert require.ErrorContains(t, err, "Period() failed for id 10 with : device or resource busy") } func TestPwmPinPolarityError(t *testing.T) { + // arrange mockedPaths := []string{ "/sys/class/pwm/pwmchip0/export", "/sys/class/pwm/pwmchip0/unexport", "/sys/class/pwm/pwmchip0/pwm10/enable", "/sys/class/pwm/pwmchip0/pwm10/period", "/sys/class/pwm/pwmchip0/pwm10/duty_cycle", + "/sys/class/pwm/pwmchip0/pwm10/polarity", } - pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) - - pin.read = func(filesystem, string) ([]byte, error) { - return nil, &os.PathError{Err: Syscall_EBUSY} - } - + pin, fs := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) + fs.Files["/sys/class/pwm/pwmchip0/pwm10/polarity"].simulateReadError = &os.PathError{Err: Syscall_EBUSY} + // act _, err := pin.Polarity() + // assert require.ErrorContains(t, err, "Polarity() failed for id 10 with : device or resource busy") } func TestPwmPinDutyCycleError(t *testing.T) { + // arrange mockedPaths := []string{ "/sys/class/pwm/pwmchip0/export", "/sys/class/pwm/pwmchip0/unexport", @@ -174,12 +169,10 @@ func TestPwmPinDutyCycleError(t *testing.T) { "/sys/class/pwm/pwmchip0/pwm10/period", "/sys/class/pwm/pwmchip0/pwm10/duty_cycle", } - pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) - - pin.read = func(filesystem, string) ([]byte, error) { - return nil, &os.PathError{Err: Syscall_EBUSY} - } - + pin, fs := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths) + fs.Files["/sys/class/pwm/pwmchip0/pwm10/duty_cycle"].simulateReadError = &os.PathError{Err: Syscall_EBUSY} + // act _, err := pin.DutyCycle() + // assert require.ErrorContains(t, err, "DutyCycle() failed for id 10 with : device or resource busy") } diff --git a/system/sysfsfile_access.go b/system/sysfsfile_access.go new file mode 100644 index 000000000..f65542eb1 --- /dev/null +++ b/system/sysfsfile_access.go @@ -0,0 +1,146 @@ +package system + +import ( + "io" + "os" + "strconv" + "strings" +) + +type sysfsFileAccess struct { + fs filesystem + readBufLen uint16 +} + +// Linux sysfs / GPIO specific sysfs docs. +// +// https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt +// https://www.kernel.org/doc/Documentation/gpio/sysfs.txt +// https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt +// see also PWM.md +type sysfsFile struct { + sfa sysfsFileAccess + file File + sysfsPath string +} + +func (sfa sysfsFileAccess) readInteger(path string) (int, error) { + sf, err := sfa.openRead(path) + defer func() { _ = sf.close() }() + if err != nil { + return 0, err + } + + return sf.readInteger() +} + +func (sfa sysfsFileAccess) read(path string) ([]byte, error) { + sf, err := sfa.openRead(path) + defer func() { _ = sf.close() }() + if err != nil { + return nil, err + } + + return sf.read() +} + +func (sfa sysfsFileAccess) writeInteger(path string, val int) error { + sf, err := sfa.openWrite(path) + defer func() { _ = sf.close() }() + if err != nil { + return err + } + + return sf.writeInteger(val) +} + +func (sfa sysfsFileAccess) write(path string, data []byte) error { + sf, err := sfa.openWrite(path) + defer func() { _ = sf.close() }() + if err != nil { + return err + } + + return sf.write(data) +} + +func (sfa sysfsFileAccess) openRead(path string) (*sysfsFile, error) { + f, err := sfa.fs.openFile(path, os.O_RDONLY, 0o644) + if err != nil { + return nil, err + } + return &sysfsFile{sfa: sfa, file: f, sysfsPath: path}, nil +} + +func (sfa sysfsFileAccess) openWrite(path string) (*sysfsFile, error) { + f, err := sfa.fs.openFile(path, os.O_WRONLY, 0o644) + if err != nil { + return nil, err + } + return &sysfsFile{sfa: sfa, file: f, sysfsPath: path}, nil +} + +func (sfa sysfsFileAccess) openReadWrite(path string) (*sysfsFile, error) { + f, err := sfa.fs.openFile(path, os.O_RDWR, 0o644) + if err != nil { + return nil, err + } + return &sysfsFile{sfa: sfa, file: f, sysfsPath: path}, nil +} + +func (sf *sysfsFile) close() error { + if sf == nil || sf.file == nil { + return nil + } + return sf.file.Close() +} + +func (sf *sysfsFile) readInteger() (int, error) { + buf, err := sf.read() + if err != nil { + return 0, err + } + + if len(buf) == 0 { + return 0, nil + } + + return strconv.Atoi(strings.Split(string(buf), "\n")[0]) +} + +func (sf *sysfsFile) read() ([]byte, error) { + // sysfs docs say: + // > If userspace seeks back to zero or does a pread(2) with an offset of '0' the [..] method will + // > be called again, rearmed, to fill the buffer. + // > The buffer will always be PAGE_SIZE bytes in length. On i386, this is 4096. + + // TODO: Examine if seek is needed if full buffer is read from sysfs file. + + buf := make([]byte, sf.sfa.readBufLen) + if _, err := sf.file.Seek(0, io.SeekStart); err != nil { + return nil, err + } + + i, err := sf.file.Read(buf) + if i == 0 { + return []byte{}, err + } + + return buf[:i], err +} + +func (sf *sysfsFile) writeInteger(val int) error { + return sf.write([]byte(strconv.Itoa(val))) +} + +func (sf *sysfsFile) write(data []byte) error { + // sysfs docs say: + // > When writing sysfs files, userspace processes should first read the + // > entire file, modify the values it wishes to change, then write the + // > entire buffer back. + // however, this seems outdated/inaccurate (docs are from back in the Kernel BitKeeper days). + + // Write() returns already a non-nil error when n != len(b). + _, err := sf.file.Write(data) + return err +} diff --git a/system/system.go b/system/system.go index 6e53fe144..210b6b001 100644 --- a/system/system.go +++ b/system/system.go @@ -72,7 +72,7 @@ func NewAccesser(options ...func(Optioner)) *Accesser { fs: &nativeFilesystem{}, } s.spiAccess = &periphioSpiAccess{fs: s.fs} - s.digitalPinAccess = &sysfsDigitalPinAccess{fs: s.fs} + s.digitalPinAccess = &sysfsDigitalPinAccess{sfa: &sysfsFileAccess{fs: s.fs, readBufLen: 2}} for _, option := range options { option(s) } @@ -85,7 +85,7 @@ func (a *Accesser) UseDigitalPinAccessWithMockFs(digitalPinAccess string, files var dph digitalPinAccesser switch digitalPinAccess { case "sysfs": - dph = &sysfsDigitalPinAccess{fs: fs} + dph = &sysfsDigitalPinAccess{sfa: &sysfsFileAccess{fs: fs, readBufLen: 2}} case "cdev": dph = &gpiodDigitalPinAccess{fs: fs} default: @@ -135,7 +135,15 @@ func (a *Accesser) IsSysfsDigitalPinAccess() bool { // NewPWMPin returns a new system PWM pin, according to the given pin number. func (a *Accesser) NewPWMPin(path string, pin int, polNormIdent string, polInvIdent string) gobot.PWMPinner { - return newPWMPinSysfs(a.fs, path, pin, polNormIdent, polInvIdent) + sfa := &sysfsFileAccess{fs: a.fs, readBufLen: 200} + return newPWMPinSysfs(sfa, path, pin, polNormIdent, polInvIdent) +} + +func (a *Accesser) NewAnalogPin(path string, r, w bool, readBufLen uint16) gobot.AnalogPinner { + if readBufLen == 0 { + readBufLen = 32 // max. count of characters for int value is 20 + } + return newAnalogPinSysfs(&sysfsFileAccess{fs: a.fs, readBufLen: readBufLen}, path, r, w) } // NewSpiDevice returns a new connection to SPI with the given parameters. diff --git a/system/system_test.go b/system/system_test.go index 0edeab0da..78dadebd9 100644 --- a/system/system_test.go +++ b/system/system_test.go @@ -82,7 +82,7 @@ func TestNewAccesser_IsSysfsDigitalPinAccess(t *testing.T) { assert.True(t, got) dpaSys := a.digitalPinAccess.(*sysfsDigitalPinAccess) assert.NotNil(t, dpaSys) - assert.Equal(t, a.fs.(*nativeFilesystem), dpaSys.fs) + assert.Equal(t, a.fs.(*nativeFilesystem), dpaSys.sfa.fs) } else { assert.False(t, got) dpaGpiod := a.digitalPinAccess.(*gpiodDigitalPinAccess) From d139c0ac7e6c5de56ad838913a4c68bbf411646e Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Mon, 27 Nov 2023 16:42:42 +0100 Subject: [PATCH 33/57] aio(thermalzone): add driver for read a thermalzone from system (#1040) --- README.md | 3 + drivers/aio/README.md | 6 +- drivers/aio/analog_sensor_driver.go | 11 ++- drivers/aio/temperature_sensor_driver_test.go | 4 +- drivers/aio/thermalzone_driver.go | 83 +++++++++++++++++ drivers/aio/thermalzone_driver_test.go | 91 +++++++++++++++++++ examples/raspi_thermalzone.go | 50 ++++++++++ examples/tinkerboard_thermalzone.go | 50 ++++++++++ platforms/nanopi/nanopi_adaptor.go | 49 ++++++++-- platforms/nanopi/nanopi_adaptor_test.go | 68 ++++++++++++++ platforms/nanopi/nanopineo_pin_map.go | 5 + platforms/raspi/raspi_adaptor.go | 49 ++++++++-- platforms/raspi/raspi_adaptor_test.go | 68 ++++++++++++++ platforms/raspi/raspi_pin_map.go | 5 + platforms/tinkerboard/adaptor.go | 55 ++++++++++- platforms/tinkerboard/adaptor_test.go | 74 +++++++++++++++ platforms/tinkerboard/pin_map.go | 16 ++-- 17 files changed, 650 insertions(+), 37 deletions(-) create mode 100644 drivers/aio/thermalzone_driver.go create mode 100644 drivers/aio/thermalzone_driver_test.go create mode 100644 examples/raspi_thermalzone.go create mode 100644 examples/tinkerboard_thermalzone.go diff --git a/README.md b/README.md index 2becbb603..c38830e07 100644 --- a/README.md +++ b/README.md @@ -298,12 +298,15 @@ Support for many devices that use Analog Input/Output (AIO) have a shared set of drivers provided using the `gobot/drivers/aio` package: - [AIO](https://en.wikipedia.org/wiki/Analog-to-digital_converter) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/aio) + - Analog Actuator - Analog Sensor - Grove Light Sensor - Grove Piezo Vibration Sensor - Grove Rotary Dial - Grove Sound Sensor - Grove Temperature Sensor + - Temperature Sensor (supports linear and NTC thermistor in normal and inverse mode) + - Thermal Zone Temperature Sensor Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of drivers provided using the `gobot/drivers/i2c` package: diff --git a/drivers/aio/README.md b/drivers/aio/README.md index 131fb93b7..aee953467 100644 --- a/drivers/aio/README.md +++ b/drivers/aio/README.md @@ -12,12 +12,12 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r Gobot has a extensible system for connecting to hardware devices. The following AIO devices are currently supported: -- Analog Sensor - Analog Actuator +- Analog Sensor - Grove Light Sensor +- Grove Piezo Vibration Sensor - Grove Rotary Dial - Grove Sound Sensor - Grove Temperature Sensor - Temperature Sensor (supports linear and NTC thermistor in normal and inverse mode) - -More drivers are coming soon... +- Thermal Zone Temperature Sensor diff --git a/drivers/aio/analog_sensor_driver.go b/drivers/aio/analog_sensor_driver.go index adae38e31..4742118c1 100644 --- a/drivers/aio/analog_sensor_driver.go +++ b/drivers/aio/analog_sensor_driver.go @@ -26,7 +26,7 @@ type sensorScaleOption struct { scaler func(input int) (value float64) } -// AnalogSensorDriver represents an Analog Sensor +// AnalogSensorDriver represents an analog sensor type AnalogSensorDriver struct { *driver sensorCfg *sensorConfiguration @@ -35,6 +35,7 @@ type AnalogSensorDriver struct { gobot.Eventer lastRawValue int lastValue float64 + analogRead func() (int, float64, error) } // NewAnalogSensorDriver returns a new driver for analog sensors, given an AnalogReader and pin. @@ -60,6 +61,7 @@ func NewAnalogSensorDriver(a AnalogReader, pin string, opts ...interface{}) *Ana } d.afterStart = d.initialize d.beforeHalt = d.shutdown + d.analogRead = d.analogSensorRead for _, opt := range opts { switch o := opt.(type) { @@ -168,6 +170,7 @@ func (a *AnalogSensorDriver) initialize() error { go func() { timer := time.NewTimer(a.sensorCfg.readInterval) timer.Stop() + for { // please note, that this ensures the first read is done immediately, but has drawbacks, see notes above rawValue, value, err := a.analogRead() @@ -183,6 +186,7 @@ func (a *AnalogSensorDriver) initialize() error { oldValue = value } } + timer.Reset(a.sensorCfg.readInterval) // ensure that after each read is a wait, independent of duration of read select { case <-timer.C: @@ -205,8 +209,9 @@ func (a *AnalogSensorDriver) shutdown() error { return nil } -// analogRead performs an reading from the sensor and sets the internal attributes and returns the raw and scaled value -func (a *AnalogSensorDriver) analogRead() (int, float64, error) { +// analogSensorRead performs an reading from the sensor, sets the internal attributes and returns +// the raw and scaled value +func (a *AnalogSensorDriver) analogSensorRead() (int, float64, error) { a.mutex.Lock() defer a.mutex.Unlock() diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index cc3786a0e..0b9d2b3d5 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -128,7 +128,7 @@ func TestTemperatureSensorDriver_LinearScaler(t *testing.T) { } } -func TestTemperatureSensorPublishesTemperatureInCelsius(t *testing.T) { +func TestTemperatureSensorWithSensorCyclicRead_PublishesTemperatureInCelsius(t *testing.T) { // arrange sem := make(chan bool) a := newAioTestAdaptor() @@ -155,7 +155,7 @@ func TestTemperatureSensorPublishesTemperatureInCelsius(t *testing.T) { assert.InDelta(t, 31.61532462352477, d.Value(), 0.0) } -func TestTemperatureSensorWithSensorCyclicReadPublishesError(t *testing.T) { +func TestTemperatureSensorWithSensorCyclicRead_PublishesError(t *testing.T) { // arrange sem := make(chan bool) a := newAioTestAdaptor() diff --git a/drivers/aio/thermalzone_driver.go b/drivers/aio/thermalzone_driver.go new file mode 100644 index 000000000..55dfbe168 --- /dev/null +++ b/drivers/aio/thermalzone_driver.go @@ -0,0 +1,83 @@ +package aio + +import ( + "fmt" + + "gobot.io/x/gobot/v2" +) + +// thermalZoneOptionApplier needs to be implemented by each configurable option type +type thermalZoneOptionApplier interface { + apply(cfg *thermalZoneConfiguration) +} + +// thermalZoneConfiguration contains all changeable attributes of the driver. +type thermalZoneConfiguration struct { + scaleUnit func(float64) float64 +} + +// thermalZoneUnitscalerOption is the type for applying another unit scaler to the configuration +type thermalZoneUnitscalerOption struct { + unitscaler func(float64) float64 +} + +// ThermalZoneDriver represents an driver for reading the system thermal zone temperature +type ThermalZoneDriver struct { + *AnalogSensorDriver + thermalZoneCfg *thermalZoneConfiguration +} + +// NewThermalZoneDriver is a driver for reading the system thermal zone temperature, given an AnalogReader and zone id. +// +// Supported options: see also [aio.NewAnalogSensorDriver] +// +// "WithFahrenheit()" +// +// Adds the following API Commands: see [aio.NewAnalogSensorDriver] +func NewThermalZoneDriver(a AnalogReader, zoneID string, opts ...interface{}) *ThermalZoneDriver { + degreeScaler := func(input int) float64 { return float64(input) / 1000 } + d := ThermalZoneDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, zoneID, WithSensorScaler(degreeScaler)), + thermalZoneCfg: &thermalZoneConfiguration{ + scaleUnit: func(input float64) float64 { return input }, // 1:1 in °C + }, + } + d.driverCfg.name = gobot.DefaultName("ThermalZone") + d.analogRead = d.thermalZoneRead + + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case sensorOptionApplier: + o.apply(d.sensorCfg) + case thermalZoneOptionApplier: + o.apply(d.thermalZoneCfg) + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } + } + + return &d +} + +// WithFahrenheit substitute the default 1:1 °C scaler by a scaler for °F +func WithFahrenheit() thermalZoneOptionApplier { + // (1°C × 9/5) + 32 = 33,8°F + unitscaler := func(input float64) float64 { return input*9.0/5.0 + 32.0 } + return thermalZoneUnitscalerOption{unitscaler: unitscaler} +} + +// thermalZoneRead overrides and extends the analogSensorRead() function to add the unit scaler +func (d *ThermalZoneDriver) thermalZoneRead() (int, float64, error) { + if _, _, err := d.analogSensorRead(); err != nil { + return 0, 0, err + } + // apply unit scaler on value + d.lastValue = d.thermalZoneCfg.scaleUnit(d.lastValue) + return d.lastRawValue, d.lastValue, nil +} + +func (o thermalZoneUnitscalerOption) apply(cfg *thermalZoneConfiguration) { + cfg.scaleUnit = o.unitscaler +} diff --git a/drivers/aio/thermalzone_driver_test.go b/drivers/aio/thermalzone_driver_test.go new file mode 100644 index 000000000..1a3f92d1d --- /dev/null +++ b/drivers/aio/thermalzone_driver_test.go @@ -0,0 +1,91 @@ +package aio + +import ( + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewThermalZoneDriver(t *testing.T) { + // arrange + const pin = "thermal_zone0" + a := newAioTestAdaptor() + // act + d := NewThermalZoneDriver(a, pin) + // assert: driver attributes + assert.IsType(t, &ThermalZoneDriver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), "ThermalZone")) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: sensor attributes + assert.Equal(t, pin, d.Pin()) + assert.InDelta(t, 0.0, d.lastValue, 0, 0) + assert.Equal(t, 0, d.lastRawValue) + assert.Nil(t, d.halt) // will be created on initialize, if cyclic reading is on + assert.NotNil(t, d.Eventer) + require.NotNil(t, d.sensorCfg) + assert.Equal(t, time.Duration(0), d.sensorCfg.readInterval) + assert.NotNil(t, d.sensorCfg.scale) + // assert: thermal zone attributes + require.NotNil(t, d.thermalZoneCfg) + require.NotNil(t, d.thermalZoneCfg.scaleUnit) + assert.InDelta(t, 1.0, d.thermalZoneCfg.scaleUnit(1), 0.0) +} + +func TestNewThermalZoneDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "outlet temperature" + cycReadDur = 10 * time.Millisecond + ) + panicFunc := func() { + NewThermalZoneDriver(newAioTestAdaptor(), "1", WithName("crazy"), + WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewThermalZoneDriver(newAioTestAdaptor(), "1", + WithName(myName), + WithSensorCyclicRead(cycReadDur), + WithFahrenheit()) + // assert + assert.Equal(t, cycReadDur, d.sensorCfg.readInterval) + assert.InDelta(t, 33.8, d.thermalZoneCfg.scaleUnit(1), 0.0) // (1°C × 9/5) + 32 = 33,8°F + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + +func TestThermalZoneWithSensorCyclicRead_PublishesTemperatureInFahrenheit(t *testing.T) { + // arrange + sem := make(chan bool) + a := newAioTestAdaptor() + d := NewThermalZoneDriver(a, "1", WithSensorCyclicRead(10*time.Millisecond), WithFahrenheit()) + a.analogReadFunc = func() (int, error) { + return -100000, nil // -100.000 °C + } + // act: start cyclic reading + require.NoError(t, d.Start()) + // assert + _ = d.Once(d.Event(Value), func(data interface{}) { + //nolint:forcetypeassert // ok here + assert.InDelta(t, -148.0, data.(float64), 0.0) + sem <- true + }) + + select { + case <-sem: + case <-time.After(1 * time.Second): + t.Errorf(" Temperature Sensor Event \"Data\" was not published") + } + + assert.InDelta(t, -148.0, d.Value(), 0.0) +} diff --git a/examples/raspi_thermalzone.go b/examples/raspi_thermalzone.go new file mode 100644 index 000000000..f2608197d --- /dev/null +++ b/examples/raspi_thermalzone.go @@ -0,0 +1,50 @@ +//go:build example +// +build example + +// +// Do not build by default. + +package main + +import ( + "fmt" + "log" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" + "gobot.io/x/gobot/v2/platforms/raspi" +) + +// Wiring: no wiring needed +func main() { + adaptor := raspi.NewAdaptor() + therm0C := aio.NewThermalZoneDriver(adaptor, "thermal_zone0") + therm0F := aio.NewThermalZoneDriver(adaptor, "thermal_zone0", aio.WithFahrenheit()) + + work := func() { + gobot.Every(500*time.Millisecond, func() { + t0C, err := therm0C.Read() + if err != nil { + log.Println(err) + } + + t0F, err := therm0F.Read() + if err != nil { + log.Println(err) + } + + fmt.Printf("Zone 0: %2.3f °C, %2.3f °F\n", t0C, t0F) + }) + } + + robot := gobot.NewRobot("thermalBot", + []gobot.Connection{adaptor}, + []gobot.Device{therm0C, therm0F}, + work, + ) + + if err := robot.Start(); err != nil { + panic(err) + } +} diff --git a/examples/tinkerboard_thermalzone.go b/examples/tinkerboard_thermalzone.go new file mode 100644 index 000000000..758ea3f65 --- /dev/null +++ b/examples/tinkerboard_thermalzone.go @@ -0,0 +1,50 @@ +//go:build example +// +build example + +// +// Do not build by default. + +package main + +import ( + "fmt" + "log" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" + "gobot.io/x/gobot/v2/platforms/tinkerboard" +) + +// Wiring: no wiring needed +func main() { + adaptor := tinkerboard.NewAdaptor() + therm0 := aio.NewThermalZoneDriver(adaptor, "thermal_zone0") + therm1 := aio.NewThermalZoneDriver(adaptor, "thermal_zone1", aio.WithFahrenheit()) + + work := func() { + gobot.Every(500*time.Millisecond, func() { + t0, err := therm0.Read() + if err != nil { + log.Println(err) + } + + t1, err := therm1.Read() + if err != nil { + log.Println(err) + } + + fmt.Printf("Zone 0: %2.3f °C, Zone 1: %2.3f °F\n", t0, t1) + }) + } + + robot := gobot.NewRobot("thermalBot", + []gobot.Connection{adaptor}, + []gobot.Device{therm0, therm1}, + work, + ) + + if err := robot.Start(); err != nil { + panic(err) + } +} diff --git a/platforms/nanopi/nanopi_adaptor.go b/platforms/nanopi/nanopi_adaptor.go index ff298762f..0ef45cffb 100644 --- a/platforms/nanopi/nanopi_adaptor.go +++ b/platforms/nanopi/nanopi_adaptor.go @@ -33,6 +33,13 @@ type gpioPinDefinition struct { cdev cdevPin } +type analogPinDefinition struct { + path string + r bool // readable + w bool // writable + bufLen uint16 +} + type pwmPinDefinition struct { channel int dir string @@ -46,6 +53,7 @@ type Adaptor struct { gpioPinMap map[string]gpioPinDefinition pwmPinMap map[string]pwmPinDefinition mutex sync.Mutex + *adaptors.AnalogPinsAdaptor *adaptors.DigitalPinsAdaptor *adaptors.PWMPinsAdaptor *adaptors.I2cBusAdaptor @@ -56,13 +64,13 @@ type Adaptor struct { // // Optional parameters: // -// adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -// adaptors.WithGpiosActiveLow(pin's): invert the pin behavior -// adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor -// adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior -// adaptors.WithGpioDebounce(pin, period): sets the input debouncer -// adaptors.WithGpioEventOnFallingEdge/RaisingEdge/BothEdges(pin, handler): activate edge detection +// adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) +// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithGpiosActiveLow(pin's): invert the pin behavior +// adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor +// adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior +// adaptors.WithGpioDebounce(pin, period): sets the input debouncer +// adaptors.WithGpioEventOnFallingEdge/RaisingEdge/BothEdges(pin, handler): activate edge detection func NewNeoAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { sys := system.NewAccesser(system.WithDigitalPinGpiodAccess()) c := &Adaptor{ @@ -71,6 +79,7 @@ func NewNeoAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { gpioPinMap: neoGpioPins, pwmPinMap: neoPwmPins, } + c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin, adaptors.WithPolarityInvertedIdentifier(pwmInvertedIdentifier)) @@ -99,6 +108,10 @@ func (c *Adaptor) Connect() error { return err } + if err := c.AnalogPinsAdaptor.Connect(); err != nil { + return err + } + if err := c.PWMPinsAdaptor.Connect(); err != nil { return err } @@ -116,6 +129,10 @@ func (c *Adaptor) Finalize() error { err = multierror.Append(err, e) } + if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + err = multierror.Append(err, e) + } + if e := c.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } @@ -143,6 +160,24 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } +func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { + pinInfo, ok := analogPinDefinitions[id] + if !ok { + return "", false, false, 0, fmt.Errorf("'%s' is not a valid id for a analog pin", id) + } + + path := pinInfo.path + info, err := c.sys.Stat(path) + if err != nil { + return "", false, 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 path, pinInfo.r, pinInfo.w, pinInfo.bufLen, nil +} + func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { pindef, ok := c.gpioPinMap[id] if !ok { diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index bfae8fdd0..b145d6e3b 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/system" @@ -58,6 +59,7 @@ var ( _ gpio.DigitalWriter = (*Adaptor)(nil) _ gpio.PwmWriter = (*Adaptor)(nil) _ gpio.ServoWriter = (*Adaptor)(nil) + _ aio.AnalogReader = (*Adaptor)(nil) _ i2c.Connector = (*Adaptor)(nil) ) @@ -99,6 +101,29 @@ func TestDigitalIO(t *testing.T) { require.NoError(t, a.Finalize()) } +func TestAnalog(t *testing.T) { + mockPaths := []string{ + "/sys/class/thermal/thermal_zone0/temp", + } + + a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) + + fs.Files["/sys/class/thermal/thermal_zone0/temp"].Contents = "567\n" + got, err := a.AnalogRead("thermal_zone0") + require.NoError(t, err) + assert.Equal(t, 567, got) + + _, err = a.AnalogRead("thermal_zone10") + require.ErrorContains(t, err, "'thermal_zone10' is not a valid id for a analog pin") + + fs.WithReadError = true + _, err = a.AnalogRead("thermal_zone0") + require.ErrorContains(t, err, "read error") + fs.WithReadError = false + + require.NoError(t, a.Finalize()) +} + func TestInvalidPWMPin(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) @@ -342,6 +367,49 @@ func Test_translateDigitalPin(t *testing.T) { } } +func Test_translateAnalogPin(t *testing.T) { + 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 + }{ + "translate_thermal_zone0": { + id: "thermal_zone0", + wantPath: "/sys/class/thermal/thermal_zone0/temp", + wantReadable: true, + wantBufLen: 7, + }, + "unknown_id": { + id: "thermal_zone1", + wantErr: "'thermal_zone1' is not a valid id for a analog pin", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a, _ := initTestAdaptorWithMockedFilesystem(mockedPaths) + // act + path, r, w, buf, err := a.translateAnalogPin(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) + }) + } +} + func Test_translatePWMPin(t *testing.T) { basePaths := []string{"/sys/devices/platform/soc/1c21400.pwm/pwm/"} tests := map[string]struct { diff --git a/platforms/nanopi/nanopineo_pin_map.go b/platforms/nanopi/nanopineo_pin_map.go index 366473d16..e055c1c29 100644 --- a/platforms/nanopi/nanopineo_pin_map.go +++ b/platforms/nanopi/nanopineo_pin_map.go @@ -23,3 +23,8 @@ var neoPwmPins = map[string]pwmPinDefinition{ // UART_RXD0, GPIOA5, PWM "PWM": {dir: "/sys/devices/platform/soc/1c21400.pwm/pwm/", dirRegexp: "pwmchip[0]$", channel: 0}, } + +var analogPinDefinitions = map[string]analogPinDefinition{ + // +/-273.200 °C need >=7 characters to read: +/-273200 millidegree Celsius + "thermal_zone0": {path: "/sys/class/thermal/thermal_zone0/temp", r: true, w: false, bufLen: 7}, +} diff --git a/platforms/raspi/raspi_adaptor.go b/platforms/raspi/raspi_adaptor.go index f87608c36..75e3fe5e0 100644 --- a/platforms/raspi/raspi_adaptor.go +++ b/platforms/raspi/raspi_adaptor.go @@ -24,6 +24,13 @@ const ( defaultSpiMaxSpeed = 500000 ) +type analogPinDefinition struct { + path string + r bool // readable + w bool // writable + bufLen uint16 +} + // Adaptor is the Gobot Adaptor for the Raspberry Pi type Adaptor struct { name string @@ -31,6 +38,7 @@ type Adaptor struct { sys *system.Accesser revision string pwmPins map[string]gobot.PWMPinner + *adaptors.AnalogPinsAdaptor *adaptors.DigitalPinsAdaptor *adaptors.I2cBusAdaptor *adaptors.SpiBusAdaptor @@ -41,13 +49,13 @@ type Adaptor struct { // // Optional parameters: // -// adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -// adaptors.WithGpiosActiveLow(pin's): invert the pin behavior -// adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor -// adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior -// adaptors.WithGpioDebounce(pin, period): sets the input debouncer -// adaptors.WithGpioEventOnFallingEdge/RaisingEdge/BothEdges(pin, handler): activate edge detection +// adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) +// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithGpiosActiveLow(pin's): invert the pin behavior +// adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor +// adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior +// adaptors.WithGpioDebounce(pin, period): sets the input debouncer +// adaptors.WithGpioEventOnFallingEdge/RaisingEdge/BothEdges(pin, handler): activate edge detection func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { sys := system.NewAccesser(system.WithDigitalPinGpiodAccess()) c := &Adaptor{ @@ -55,6 +63,7 @@ func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { sys: sys, PiBlasterPeriod: 10000000, } + c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.getPinTranslatorFunction(), opts...) c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, 1) c.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, c.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, @@ -91,6 +100,10 @@ func (c *Adaptor) Connect() error { return err } + if err := c.AnalogPinsAdaptor.Connect(); err != nil { + return err + } + c.pwmPins = make(map[string]gobot.PWMPinner) return c.DigitalPinsAdaptor.Connect() } @@ -111,6 +124,10 @@ func (c *Adaptor) Finalize() error { } c.pwmPins = nil + if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + err = multierror.Append(err, e) + } + if e := c.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } @@ -184,6 +201,24 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } +func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { + pinInfo, ok := analogPinDefinitions[id] + if !ok { + return "", false, false, 0, fmt.Errorf("'%s' is not a valid id for a analog pin", id) + } + + path := pinInfo.path + info, err := c.sys.Stat(path) + if err != nil { + return "", false, 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 path, pinInfo.r, pinInfo.w, pinInfo.bufLen, nil +} + func (c *Adaptor) getPinTranslatorFunction() func(string) (string, int, error) { return func(pin string) (string, int, error) { var line int diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index 4fd330ecb..c48f7ae46 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/drivers/spi" @@ -27,6 +28,7 @@ var ( _ gpio.DigitalWriter = (*Adaptor)(nil) _ gpio.PwmWriter = (*Adaptor)(nil) _ gpio.ServoWriter = (*Adaptor)(nil) + _ aio.AnalogReader = (*Adaptor)(nil) _ i2c.Connector = (*Adaptor)(nil) _ spi.Connector = (*Adaptor)(nil) ) @@ -108,6 +110,29 @@ func TestFinalize(t *testing.T) { require.NoError(t, a.Finalize()) } +func TestAnalog(t *testing.T) { + mockPaths := []string{ + "/sys/class/thermal/thermal_zone0/temp", + } + + a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) + + fs.Files["/sys/class/thermal/thermal_zone0/temp"].Contents = "567\n" + got, err := a.AnalogRead("thermal_zone0") + require.NoError(t, err) + assert.Equal(t, 567, got) + + _, err = a.AnalogRead("thermal_zone10") + require.ErrorContains(t, err, "'thermal_zone10' is not a valid id for a analog pin") + + fs.WithReadError = true + _, err = a.AnalogRead("thermal_zone0") + require.ErrorContains(t, err, "read error") + fs.WithReadError = false + + require.NoError(t, a.Finalize()) +} + func TestDigitalPWM(t *testing.T) { mockedPaths := []string{"/dev/pi-blaster"} a, fs := initTestAdaptorWithMockedFilesystem(mockedPaths) @@ -339,3 +364,46 @@ func Test_validateI2cBusNumber(t *testing.T) { }) } } + +func Test_translateAnalogPin(t *testing.T) { + 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 + }{ + "translate_thermal_zone0": { + id: "thermal_zone0", + wantPath: "/sys/class/thermal/thermal_zone0/temp", + wantReadable: true, + wantBufLen: 7, + }, + "unknown_id": { + id: "thermal_zone1", + wantErr: "'thermal_zone1' is not a valid id for a analog pin", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a, _ := initTestAdaptorWithMockedFilesystem(mockedPaths) + // act + path, r, w, buf, err := a.translateAnalogPin(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) + }) + } +} diff --git a/platforms/raspi/raspi_pin_map.go b/platforms/raspi/raspi_pin_map.go index 775b62427..6fdda4835 100644 --- a/platforms/raspi/raspi_pin_map.go +++ b/platforms/raspi/raspi_pin_map.go @@ -86,3 +86,8 @@ var pins = map[string]map[string]int{ "3": 21, }, } + +var analogPinDefinitions = map[string]analogPinDefinition{ + // +/-273.200 °C need >=7 characters to read: +/-273200 millidegree Celsius + "thermal_zone0": {path: "/sys/class/thermal/thermal_zone0/temp", r: true, w: false, bufLen: 7}, +} diff --git a/platforms/tinkerboard/adaptor.go b/platforms/tinkerboard/adaptor.go index 63f8a451d..f63ce80c7 100644 --- a/platforms/tinkerboard/adaptor.go +++ b/platforms/tinkerboard/adaptor.go @@ -23,10 +23,27 @@ const ( defaultSpiMaxSpeed = 500000 ) +type cdevPin struct { + chip uint8 + line uint8 +} + +type gpioPinDefinition struct { + sysfs int + cdev cdevPin +} + +type analogPinDefinition struct { + path string + r bool // readable + w bool // writable + bufLen uint16 +} + type pwmPinDefinition struct { - channel int dir string dirRegexp string + channel int } // Adaptor represents a Gobot Adaptor for the ASUS Tinker Board @@ -34,6 +51,7 @@ type Adaptor struct { name string sys *system.Accesser mutex sync.Mutex + *adaptors.AnalogPinsAdaptor *adaptors.DigitalPinsAdaptor *adaptors.PWMPinsAdaptor *adaptors.I2cBusAdaptor @@ -44,10 +62,10 @@ type Adaptor struct { // // Optional parameters: // -// adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -// adaptors.WithGpiosActiveLow(pin's): invert the pin behavior -// adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor +// adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) +// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithGpiosActiveLow(pin's): invert the pin behavior +// adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor // // note from RK3288 datasheet: "The pull direction (pullup or pulldown) for all of GPIOs are software-programmable", but // the latter is not working for any pin (armbian 22.08.7) @@ -57,6 +75,7 @@ func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { name: gobot.DefaultName("Tinker Board"), sys: sys, } + c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin, adaptors.WithPolarityInvertedIdentifier(pwmInvertedIdentifier)) @@ -85,6 +104,10 @@ func (c *Adaptor) Connect() error { return err } + if err := c.AnalogPinsAdaptor.Connect(); err != nil { + return err + } + if err := c.PWMPinsAdaptor.Connect(); err != nil { return err } @@ -102,6 +125,10 @@ func (c *Adaptor) Finalize() error { err = multierror.Append(err, e) } + if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + err = multierror.Append(err, e) + } + if e := c.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } @@ -130,6 +157,24 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } +func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { + pinInfo, ok := analogPinDefinitions[id] + if !ok { + return "", false, false, 0, fmt.Errorf("'%s' is not a valid id for a analog pin", id) + } + + path := pinInfo.path + info, err := c.sys.Stat(path) + if err != nil { + return "", false, 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 path, pinInfo.r, pinInfo.w, pinInfo.bufLen, nil +} + func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { pindef, ok := gpioPinDefinitions[id] if !ok { diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index f00374fde..25d1ab778 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/system" @@ -58,6 +59,7 @@ var ( _ gpio.DigitalWriter = (*Adaptor)(nil) _ gpio.PwmWriter = (*Adaptor)(nil) _ gpio.ServoWriter = (*Adaptor)(nil) + _ aio.AnalogReader = (*Adaptor)(nil) _ i2c.Connector = (*Adaptor)(nil) ) @@ -99,6 +101,29 @@ func TestDigitalIO(t *testing.T) { require.NoError(t, a.Finalize()) } +func TestAnalog(t *testing.T) { + mockPaths := []string{ + "/sys/class/thermal/thermal_zone0/temp", + } + + a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) + + fs.Files["/sys/class/thermal/thermal_zone0/temp"].Contents = "567\n" + got, err := a.AnalogRead("thermal_zone0") + require.NoError(t, err) + assert.Equal(t, 567, got) + + _, err = a.AnalogRead("thermal_zone10") + require.ErrorContains(t, err, "'thermal_zone10' is not a valid id for a analog pin") + + fs.WithReadError = true + _, err = a.AnalogRead("thermal_zone0") + require.ErrorContains(t, err, "read error") + fs.WithReadError = false + + require.NoError(t, a.Finalize()) +} + func TestInvalidPWMPin(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) @@ -355,6 +380,55 @@ func Test_translateDigitalPin(t *testing.T) { } } +func Test_translateAnalogPin(t *testing.T) { + 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 + }{ + "translate_thermal_zone0": { + id: "thermal_zone0", + wantPath: "/sys/class/thermal/thermal_zone0/temp", + wantReadable: true, + wantBufLen: 7, + }, + "translate_thermal_zone1": { + id: "thermal_zone1", + wantPath: "/sys/class/thermal/thermal_zone1/temp", + wantReadable: true, + wantBufLen: 7, + }, + "unknown_id": { + id: "99", + wantErr: "'99' is not a valid id for a analog pin", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a, _ := initTestAdaptorWithMockedFilesystem(mockedPaths) + // act + path, r, w, buf, err := a.translateAnalogPin(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) + }) + } +} + func Test_translatePWMPin(t *testing.T) { basePaths := []string{ "/sys/devices/platform/ff680020.pwm/pwm/", diff --git a/platforms/tinkerboard/pin_map.go b/platforms/tinkerboard/pin_map.go index aa396d9cb..40feeaca1 100644 --- a/platforms/tinkerboard/pin_map.go +++ b/platforms/tinkerboard/pin_map.go @@ -1,15 +1,5 @@ package tinkerboard -type cdevPin struct { - chip uint8 - line uint8 -} - -type gpioPinDefinition struct { - sysfs int - cdev cdevPin -} - // notes for character device // pins: A=0+Nr, B=8+Nr, C=16+Nr // tested: armbian Linux, OK: work as input and output, IN: work only as input @@ -50,3 +40,9 @@ var pwmPinDefinitions = map[string]pwmPinDefinition{ // GPIO7_C7_UART2TX_PWM3 "32": {dir: "/sys/devices/platform/ff680030.pwm/pwm/", dirRegexp: "pwmchip[0|1|2|3]$", channel: 0}, } + +var analogPinDefinitions = map[string]analogPinDefinition{ + // +/-273.200 °C need >=7 characters to read: +/-273200 millidegree Celsius + "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}, +} From be1ccf07e45f8a3a25961b3fafe0d0df8140e969 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 3 Dec 2023 18:03:02 +0100 Subject: [PATCH 34/57] gpio(all): introduce functional options (#1045) --- README.md | 12 +- driver.go | 3 +- drivers/aio/analog_sensor_driver.go | 6 +- drivers/aio/analog_sensor_driver_test.go | 27 +- drivers/gpio/MIGRATION.md | 195 +++++++++ drivers/gpio/README.md | 12 +- drivers/gpio/aip1640_driver.go | 132 +++---- drivers/gpio/aip1640_driver_test.go | 81 ++-- drivers/gpio/button_driver.go | 135 +++++-- drivers/gpio/button_driver_test.go | 111 +++--- drivers/gpio/buzzer_driver.go | 76 ++-- drivers/gpio/buzzer_driver_test.go | 70 ++-- drivers/gpio/direct_pin_driver.go | 70 +--- drivers/gpio/direct_pin_driver_test.go | 96 +++-- drivers/gpio/easy_driver.go | 158 +++++--- drivers/gpio/easy_driver_test.go | 92 +++-- drivers/gpio/gpio_driver.go | 141 +++++-- drivers/gpio/gpio_driver_test.go | 33 +- drivers/gpio/grove_drivers.go | 84 ++-- drivers/gpio/grove_drivers_test.go | 41 +- drivers/gpio/hcsr04_driver.go | 164 +++++--- drivers/gpio/hcsr04_driver_test.go | 35 +- drivers/gpio/hd44780_driver.go | 372 +++++++++--------- drivers/gpio/hd44780_driver_test.go | 140 ++++--- drivers/gpio/led_driver.go | 56 +-- drivers/gpio/led_driver_test.go | 77 ++-- drivers/gpio/max7219_driver.go | 208 +++++----- drivers/gpio/max7219_driver_test.go | 70 ++-- drivers/gpio/motor_driver.go | 285 +++++++++----- drivers/gpio/motor_driver_test.go | 215 ++++++---- drivers/gpio/pir_motion_driver.go | 110 ++++-- drivers/gpio/pir_motion_driver_test.go | 72 ++-- drivers/gpio/relay_driver.go | 104 ++--- drivers/gpio/relay_driver_test.go | 67 ++-- drivers/gpio/rgb_led_driver.go | 54 +-- drivers/gpio/rgb_led_driver_test.go | 79 ++-- drivers/gpio/servo_driver.go | 82 ++-- drivers/gpio/servo_driver_test.go | 97 +++-- drivers/gpio/stepper_driver.go | 39 +- drivers/gpio/stepper_driver_test.go | 28 +- drivers/gpio/tm1638_driver.go | 253 ++++++------ drivers/gpio/tm1638_driver_test.go | 76 ++-- drivers/i2c/adafruit1109_driver.go | 5 +- examples/edison_grove_button.go | 2 +- examples/edison_grove_led.go | 2 +- examples/edison_grove_touch.go | 2 +- examples/firmata_cat_toy.go | 2 +- examples/firmata_motor.go | 2 +- examples/firmata_travis.go | 9 +- examples/gopigo3_grove_button.go | 4 +- examples/gopigo3_led_brightness.go | 2 +- examples/nanopi_button.go | 71 ++++ examples/raspi_grove_pi_button.go | 3 +- examples/raspi_hcsr04.go | 6 +- examples/tinkerboard_button.go | 71 ++++ examples/tinkerboard_hcsr04.go | 6 +- examples/tinkerboard_motor.go | 66 ++++ examples/tinkerboard_servo.go | 90 +++++ platforms/adaptors/pwmpinsadaptor.go | 42 +- platforms/adaptors/pwmpinsadaptor_test.go | 4 +- .../beaglebone/beaglebone_adaptor_test.go | 66 ++-- platforms/chip/chip_adaptor_test.go | 9 +- platforms/nanopi/nanopi_adaptor_test.go | 8 +- platforms/tinkerboard/adaptor_test.go | 4 +- platforms/upboard/up2/adaptor_test.go | 52 ++- system/pwmpin_sysfs.go | 2 +- 66 files changed, 3004 insertions(+), 1784 deletions(-) create mode 100644 drivers/gpio/MIGRATION.md create mode 100644 examples/nanopi_button.go create mode 100644 examples/tinkerboard_button.go create mode 100644 examples/tinkerboard_motor.go create mode 100644 examples/tinkerboard_servo.go diff --git a/README.md b/README.md index c38830e07..a9e48b4c4 100644 --- a/README.md +++ b/README.md @@ -275,12 +275,12 @@ a shared set of drivers provided using the `gobot/drivers/gpio` package: - Buzzer - Direct Pin - EasyDriver - - Grove Button - - Grove Buzzer - - Grove LED - - Grove Magnetic Switch - - Grove Relay - - Grove Touch Sensor + - Grove Button (by using driver for Button) + - Grove Buzzer (by using driver for Buzzer) + - Grove LED (by using driver for LED) + - Grove Magnetic Switch (by using driver for Button) + - Grove Relay (by using driver for Relay) + - Grove Touch Sensor (by using driver for Button) - HC-SR04 Ultrasonic Ranging Module - HD44780 LCD controller - LED diff --git a/driver.go b/driver.go index 0c64fdf97..7581f2826 100644 --- a/driver.go +++ b/driver.go @@ -4,7 +4,8 @@ package gobot type Driver interface { // Name returns the label for the Driver Name() string - // SetName sets the label for the Driver + // SetName sets the label for the Driver. + // Please prefer to use options [gpio.WithName or aio.WithName] instead, if possible. SetName(s string) // Start initiates the Driver Start() error diff --git a/drivers/aio/analog_sensor_driver.go b/drivers/aio/analog_sensor_driver.go index 4742118c1..c02d91ad5 100644 --- a/drivers/aio/analog_sensor_driver.go +++ b/drivers/aio/analog_sensor_driver.go @@ -31,7 +31,7 @@ type AnalogSensorDriver struct { *driver sensorCfg *sensorConfiguration pin string - halt chan bool + halt chan struct{} gobot.Eventer lastRawValue int lastValue float64 @@ -163,7 +163,7 @@ func (a *AnalogSensorDriver) initialize() error { // the writing to halt is blocked because there is no immediate read from channel. // Please note, that this is special behavior caused by the first read is done immediately before the select // statement. - a.halt = make(chan bool, 1) + a.halt = make(chan struct{}, 1) oldRawValue := 0 oldValue := 0.0 @@ -205,7 +205,7 @@ func (a *AnalogSensorDriver) shutdown() error { // cyclic reading deactivated return nil } - a.halt <- true + close(a.halt) // broadcast halt, also to the test return nil } diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index 6fcd95499..f4918e55a 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -4,6 +4,7 @@ package aio import ( "fmt" "strings" + "sync" "testing" "time" @@ -217,8 +218,8 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) { semDone <- true }) - // act: send a halt message - d.halt <- true + // act: send the halt message + require.NoError(t, d.Halt()) // assert: no event select { @@ -234,18 +235,20 @@ func TestAnalogSensorHalt_WithSensorCyclicRead(t *testing.T) { // arrange d := NewAnalogSensorDriver(newAioTestAdaptor(), "1", WithSensorCyclicRead(10*time.Millisecond)) require.NoError(t, d.Start()) - done := make(chan struct{}) - // act & assert + timeout := 2 * d.sensorCfg.readInterval + wg := sync.WaitGroup{} + wg.Add(1) go func() { - require.NoError(t, d.Halt()) - close(done) + defer wg.Done() + select { + case <-d.halt: // wait until halt is broadcasted by close the channel + case <-time.After(timeout): // otherwise run into the timeout + assert.Fail(t, "halt was not received within %s", timeout) + } }() - // test that the halt is not blocked by any deadlock with mutex and/or channel - select { - case <-done: - case <-time.After(100 * time.Millisecond): - t.Errorf("AnalogSensor was not halted") - } + // act & assert + require.NoError(t, d.Halt()) + wg.Wait() // wait until the go function was really finished } func TestAnalogSensorCommands_WithSensorScaler(t *testing.T) { diff --git a/drivers/gpio/MIGRATION.md b/drivers/gpio/MIGRATION.md new file mode 100644 index 000000000..c493e1b4a --- /dev/null +++ b/drivers/gpio/MIGRATION.md @@ -0,0 +1,195 @@ +# Migration of GPIO drivers + +From time to time a breaking change of API can happen. Following to [SemVer](https://semver.org/), the gobot main version +should be increased. In such case all users needs to adjust there projects for the next update, although they not using +a driver with changed API. + +To prevent this scenario for most users, the main version will not always increased, but affected GPIO drivers are listed +here and a migration strategy is provided. + +## Switch from version 2.2.0 + +### ButtonDriver, PIRMotionDriver: substitute parameter "v time.duration" + +A backward compatible case is still included, but it is recommended to use "WithButtonPollInterval" instead, see example +below. + +```go +// old +d := gpio.NewButtonDriver(adaptor, "1", 50*time.Millisecond) + +// new +d := gpio.NewButtonDriver(adaptor, "1", gpio.WithButtonPollInterval(50*time.Millisecond)) +``` + +### EasyDriver: optional pins + +There is no need to use the direction, enable or sleep feature of the driver. Therefore the parameters are removed from +constructor. Please migrate according to the examples below. The order of the optional functions does not matter. + +```go +// old +d0 := gpio.NewEasyDriver(adaptor, 0.80, "1", "", "", "") +d1 := gpio.NewEasyDriver(adaptor, 0.81, "11", "12", "", "") +d2 := gpio.NewEasyDriver(adaptor, 0.82, "21", "22", "23", "") +d3 := gpio.NewEasyDriver(adaptor, 0.83, "31", "32", "33", "34") + +// new +d0 := gpio.NewEasyDriver(adaptor, 0.80, "1") +d1 := gpio.NewEasyDriver(adaptor, 0.81, "11", gpio.WithEasyDirectionPin("12")) +d2 := gpio.NewEasyDriver(adaptor, 0.82, "21", gpio.WithEasyDirectionPin("22"), gpio.WithEasyEnablePin("23")) +d3 := gpio.NewEasyDriver(adaptor, 0.83, "31", gpio.WithEasyDirectionPin("32"), gpio.WithEasyEnablePin("33"), + gpio.WithEasySleepPin("34")) +``` + +### BuzzerDriver: unexport 'BPM' attribute + +```go +d := gpio.NewBuzzerDriver(adaptor, "1") +// old +d.BPM = 120.0 +fmt.Println("BPM:", d.BPM) + +// new +d.SetBPM(120.0) +fmt.Println("BPM:", d.BPM()) +``` + +### RelayDriver: unexport 'Inverted' attribute + +Usually the relay is inverted or not, except be rewired. From now on the inverted behavior can only be changed on +initialization. If there is really a different use case, please file a new issue. + +```go +// old +d := gpio.NewRelayDriver(adaptor, "1") +d.Inverted = true +fmt.Println("is inverted:", d.Inverted) + +// new +d := gpio.NewRelayDriver(adaptor, "1", gpio.WithRelayInverted()) +fmt.Println("is inverted:", d.IsInverted()) +``` + +### HD44780Driver: make 'SetRWPin()' an option + +```go +// old +d := gpio.NewHD44780Driver(adaptor, ...) +d.SetRWPin("10") + +// new +d := gpio.NewHD44780Driver(adaptor, ..., gpio.WithHD44780RWPin("10")) +``` + +### ServoDriver: unexport 'CurrentAngle' and rename functions 'Min()', 'Max()', 'Center()' + +```go +d := gpio.NewServoDriver(adaptor, "1") +// old +d.Min() +fmt.Println("current position:", d.CurrentAngle) +d.Center() +d.Max() + +// new +d.ToMin() +fmt.Println("current position:", d.Angle()) +d.ToCenter() +d.ToMax() +``` + +### MotorDriver: unexport pin and state attributes, rename functions + +The motor driver was heavily revised - sorry for the inconveniences. + +affected pins: + +* SpeedPin +* SwitchPin (removed, was unused) +* DirectionPin +* ForwardPin +* BackwardPin + +Usually the pins will not change without a hardware rewiring. All pins, except the speed pin are optionally, so options +are designed for that. + +```go +// old +d := gpio.NewMotorDriver(adaptor, "1") +d.DirectionPin = "10" + +// new +d := gpio.NewMotorDriver(adaptor, "1", gpio.WithMotorDirectionPin("10")) +``` + +```go +// old +d := gpio.NewMotorDriver(adaptor, "1") +d.ForwardPin = "10" +d.BackWardPin = "11" + +// new +d := gpio.NewMotorDriver(adaptor, "1", gpio.WithMotorForwardPin("10"), gpio.WithMotorBackwardPin("11")) +``` + +affected functions: + +* Speed() --> SetSpeed() +* Direction() --> SetDirection() +* Max() --> RunMax() +* Min() --> RunMin() + +affected states: + +* CurrentState +* CurrentSpeed +* CurrentMode +* CurrentDirection + +Most of the attributes were used only for reading. If there is something missing, please file a new issue. + +```go +d := gpio.NewMotorDriver(adaptor, "1") +// old +d.On() +fmt.Println("is on:", d.CurrentState==1) +fmt.Println("speed:", d.CurrentSpeed) +d.Off() +fmt.Println("is off:", d.CurrentState==0) +fmt.Println("mode is digital:", d.CurrentMode=="digital") +fmt.Println("direction:", d.CurrentDirection) + +// new +d.On() +fmt.Println("is on:", d.IsOn()) +d.Off() +fmt.Println("is on:", d.IsOff()) +fmt.Println("speed:", d.Speed()) +fmt.Println("mode is digital:", d.IsDigital()) +fmt.Println("direction:", d.Direction()) +``` + +```go +d := gpio.NewMotorDriver(adaptor, "1") +// old +d.Speed(123) +fmt.Println("is mode now analog?", d.CurrentMode!="digital") + +// new +d.SetSpeed(123) +fmt.Println("is mode now analog?", d.IsAnalog()) +``` + +Although, it is working like above, it will be more clear, if the mode is defined at the beginning, like so. + +```go +// old +d := gpio.NewMotorDriver(adaptor, "1") +d.CurrentMode=="analog" +d.Max() + +// new +d := gpio.NewMotorDriver(adaptor, "1", gpio.WithMotorAnalog()) +d.RunMax() +``` diff --git a/drivers/gpio/README.md b/drivers/gpio/README.md index 8426a02c0..f01681556 100644 --- a/drivers/gpio/README.md +++ b/drivers/gpio/README.md @@ -17,12 +17,12 @@ Gobot has a extensible system for connecting to hardware devices. The following - Buzzer - Direct Pin - EasyDriver -- Grove Button -- Grove Buzzer -- Grove LED -- Grove Magnetic Switch -- Grove Relay -- Grove Touch Sensor +- Grove Button (by using driver for Button) +- Grove Buzzer (by using driver for Buzzer) +- Grove LED (by using driver for LED) +- Grove Magnetic Switch (by using driver for Button) +- Grove Relay (by using driver for Relay) +- Grove Touch Sensor (by using driver for Button) - HC-SR04 Ultrasonic Ranging Module - HD44780 LCD controller - LED diff --git a/drivers/gpio/aip1640_driver.go b/drivers/gpio/aip1640_driver.go index 32b6c54e9..a3257bc43 100644 --- a/drivers/gpio/aip1640_driver.go +++ b/drivers/gpio/aip1640_driver.go @@ -22,168 +22,156 @@ const ( // // Library ported from: https://github.com/wemos/WEMOS_Matrix_LED_Shield_Arduino_Library type AIP1640Driver struct { - pinClock *DirectPinDriver - pinData *DirectPinDriver - name string - intensity byte - buffer [8]byte - connection gobot.Connection - gobot.Commander + *driver + pinClock *DirectPinDriver + pinData *DirectPinDriver + intensity byte + buffer [8]byte } -// NewAIP1640Driver return a new AIP1640Driver given a gobot.Connection and the clock, data and strobe pins -func NewAIP1640Driver(a gobot.Connection, clockPin string, dataPin string) *AIP1640Driver { - t := &AIP1640Driver{ - name: gobot.DefaultName("AIP1640Driver"), - pinClock: NewDirectPinDriver(a, clockPin), - pinData: NewDirectPinDriver(a, dataPin), - intensity: 7, - connection: a, - Commander: gobot.NewCommander(), +// NewAIP1640Driver return a new driver for AIP1640 LED driver given a gobot.Connection and the clock, +// data and strobe pins. +// +// Supported options: +// +// "WithName" +func NewAIP1640Driver(a gobot.Connection, clockPin string, dataPin string, opts ...interface{}) *AIP1640Driver { + d := &AIP1640Driver{ + driver: newDriver(a, "AIP1640", opts...), + pinClock: NewDirectPinDriver(a, clockPin), + pinData: NewDirectPinDriver(a, dataPin), + intensity: 7, } + d.afterStart = d.initialize /* TODO : Add commands */ - return t -} - -// Start initializes the tm1638, it uses a SPI-like communication protocol -func (a *AIP1640Driver) Start() error { - if err := a.pinData.On(); err != nil { - return err - } - return a.pinClock.On() -} - -// Halt implements the Driver interface -func (a *AIP1640Driver) Halt() error { return nil } - -// Name returns the AIP1640Drivers name -func (a *AIP1640Driver) Name() string { return a.name } - -// SetName sets the AIP1640Drivers name -func (a *AIP1640Driver) SetName(n string) { a.name = n } - -// Connection returns the AIP1640Driver Connection -func (a *AIP1640Driver) Connection() gobot.Connection { - return a.connection + return d } // SetIntensity changes the intensity (from 1 to 7) of the display -func (a *AIP1640Driver) SetIntensity(level byte) { +func (d *AIP1640Driver) SetIntensity(level byte) { if level >= 7 { level = 7 } - a.intensity = level + d.intensity = level } // Display sends the buffer to the display (ie. turns on/off the corresponding LEDs) -func (a *AIP1640Driver) Display() error { +func (d *AIP1640Driver) Display() error { for i := 0; i < 8; i++ { - if err := a.sendData(byte(i), a.buffer[i]); err != nil { + if err := d.sendData(byte(i), d.buffer[i]); err != nil { return err } - if err := a.pinData.Off(); err != nil { + if err := d.pinData.Off(); err != nil { return err } - if err := a.pinClock.Off(); err != nil { + if err := d.pinClock.Off(); err != nil { return err } time.Sleep(1 * time.Millisecond) - if err := a.pinClock.On(); err != nil { + if err := d.pinClock.On(); err != nil { return err } - if err := a.pinData.On(); err != nil { + if err := d.pinData.On(); err != nil { return err } } - return a.sendCommand(AIP1640DispCtrl | a.intensity) + return d.sendCommand(AIP1640DispCtrl | d.intensity) } // Clear empties the buffer (turns off all the LEDs) -func (a *AIP1640Driver) Clear() { +func (d *AIP1640Driver) Clear() { for i := 0; i < 8; i++ { - a.buffer[i] = 0x00 + d.buffer[i] = 0x00 } } // DrawPixel turns on or off a specific in the buffer -func (a *AIP1640Driver) DrawPixel(x, y byte, enabled bool) { +func (d *AIP1640Driver) DrawPixel(x, y byte, enabled bool) { if x >= 8 || y >= 8 { return } y = 7 - y if enabled { - a.buffer[y] |= 1 << x + d.buffer[y] |= 1 << x } else { - a.buffer[y] &^= 1 << x + d.buffer[y] &^= 1 << x } } // DrawRow sets any given row of LEDs in the buffer -func (a *AIP1640Driver) DrawRow(row, data byte) { +func (d *AIP1640Driver) DrawRow(row, data byte) { if row >= 8 { return } - a.buffer[7-row] = data + d.buffer[7-row] = data } // DrawMatrix sets the whole buffer -func (a *AIP1640Driver) DrawMatrix(data [8]byte) { +func (d *AIP1640Driver) DrawMatrix(data [8]byte) { for i := 0; i < 8; i++ { - a.buffer[7-i] = data[i] + d.buffer[7-i] = data[i] + } +} + +// initialize initializes the tm1638, it uses a SPI-like communication protocol +func (d *AIP1640Driver) initialize() error { + if err := d.pinData.On(); err != nil { + return err } + return d.pinClock.On() } // sendCommand is an auxiliary function to send commands to the AIP1640Driver module -func (a *AIP1640Driver) sendCommand(cmd byte) error { - if err := a.pinData.Off(); err != nil { +func (d *AIP1640Driver) sendCommand(cmd byte) error { + if err := d.pinData.Off(); err != nil { return err } - if err := a.send(cmd); err != nil { + if err := d.send(cmd); err != nil { return err } - return a.pinData.On() + return d.pinData.On() } // sendData is an auxiliary function to send data to the AIP1640Driver module -func (a *AIP1640Driver) sendData(address byte, data byte) error { - if err := a.sendCommand(AIP1640DataCmd | AIP1640FixedAddr); err != nil { +func (d *AIP1640Driver) sendData(address byte, data byte) error { + if err := d.sendCommand(AIP1640DataCmd | AIP1640FixedAddr); err != nil { return err } - if err := a.pinData.Off(); err != nil { + if err := d.pinData.Off(); err != nil { return err } - if err := a.send(AIP1640AddrCmd | address); err != nil { + if err := d.send(AIP1640AddrCmd | address); err != nil { return err } - if err := a.send(data); err != nil { + if err := d.send(data); err != nil { return err } - return a.pinData.On() + return d.pinData.On() } // send writes data on the module -func (a *AIP1640Driver) send(data byte) error { +func (d *AIP1640Driver) send(data byte) error { for i := 0; i < 8; i++ { - if err := a.pinClock.Off(); err != nil { + if err := d.pinClock.Off(); err != nil { return err } if (data & 1) > 0 { - if err := a.pinData.On(); err != nil { + if err := d.pinData.On(); err != nil { return err } } else { - if err := a.pinData.Off(); err != nil { + if err := d.pinData.Off(); err != nil { return err } } data >>= 1 - if err := a.pinClock.On(); err != nil { + if err := d.pinClock.On(); err != nil { return err } } diff --git a/drivers/gpio/aip1640_driver_test.go b/drivers/gpio/aip1640_driver_test.go index a820dd00e..2c21fff00 100644 --- a/drivers/gpio/aip1640_driver_test.go +++ b/drivers/gpio/aip1640_driver_test.go @@ -3,77 +3,94 @@ package gpio import ( "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*AIP1640Driver)(nil) -// --------- HELPERS func initTestAIP1640Driver() *AIP1640Driver { d, _ := initTestAIP1640DriverWithStubbedAdaptor() return d } func initTestAIP1640DriverWithStubbedAdaptor() (*AIP1640Driver, *gpioTestAdaptor) { - adaptor := newGpioTestAdaptor() - return NewAIP1640Driver(adaptor, "1", "2"), adaptor + a := newGpioTestAdaptor() + return NewAIP1640Driver(a, "1", "2"), a } -// --------- TESTS -func TestAIP1640Driver(t *testing.T) { - var a interface{} = initTestAIP1640Driver() - _, ok := a.(*AIP1640Driver) - if !ok { - t.Errorf("NewAIP1640Driver() should have returned a *AIP1640Driver") - } -} - -func TestAIP1640DriverStart(t *testing.T) { - d := initTestAIP1640Driver() - require.NoError(t, d.Start()) -} - -func TestAIP1640DriverHalt(t *testing.T) { - d := initTestAIP1640Driver() - require.NoError(t, d.Halt()) +func TestNewAIP1640Driver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewAIP1640Driver(a, "1", "2") + // assert + assert.IsType(t, &AIP1640Driver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "AIP1640")) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.NotNil(t, d.pinClock) + assert.NotNil(t, d.pinData) + assert.Equal(t, uint8(7), d.intensity) } -func TestAIP1640DriverDefaultName(t *testing.T) { - d := initTestAIP1640Driver() - assert.True(t, strings.HasPrefix(d.Name(), "AIP1640Driver")) +func TestNewAIP1640Driver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "count up" + cycReadDur = 30 * time.Millisecond + ) + panicFunc := func() { + NewAIP1640Driver(newGpioTestAdaptor(), "1", "2", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewAIP1640Driver(newGpioTestAdaptor(), "1", "2", WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } -func TestAIP1640DriverSetName(t *testing.T) { +func TestAIP1640Start(t *testing.T) { d := initTestAIP1640Driver() - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) + require.NoError(t, d.Start()) } -func TestAIP1640DriveDrawPixel(t *testing.T) { +func TestAIP1640DrawPixel(t *testing.T) { d := initTestAIP1640Driver() d.DrawPixel(2, 3, true) d.DrawPixel(0, 3, true) assert.Equal(t, uint8(5), d.buffer[7-3]) } -func TestAIP1640DriverDrawRow(t *testing.T) { +func TestAIP1640DrawRow(t *testing.T) { d := initTestAIP1640Driver() d.DrawRow(4, 0x3C) assert.Equal(t, uint8(0x3C), d.buffer[7-4]) } -func TestAIP1640DriverDrawMatrix(t *testing.T) { +func TestAIP1640DrawMatrix(t *testing.T) { d := initTestAIP1640Driver() drawing := [8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} d.DrawMatrix(drawing) assert.Equal(t, [8]byte{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01}, d.buffer) } -func TestAIP1640DriverClear(t *testing.T) { +func TestAIP1640Clear(t *testing.T) { d := initTestAIP1640Driver() drawing := [8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} d.DrawMatrix(drawing) @@ -82,13 +99,13 @@ func TestAIP1640DriverClear(t *testing.T) { assert.Equal(t, [8]byte{}, d.buffer) } -func TestAIP1640DriverSetIntensity(t *testing.T) { +func TestAIP1640SetIntensity(t *testing.T) { d := initTestAIP1640Driver() d.SetIntensity(3) assert.Equal(t, uint8(3), d.intensity) } -func TestAIP1640DriverSetIntensityHigherThan7(t *testing.T) { +func TestAIP1640SetIntensityHigherThan7(t *testing.T) { d := initTestAIP1640Driver() d.SetIntensity(19) assert.Equal(t, uint8(7), d.intensity) diff --git a/drivers/gpio/button_driver.go b/drivers/gpio/button_driver.go index 509156983..18aa5d1a3 100644 --- a/drivers/gpio/button_driver.go +++ b/drivers/gpio/button_driver.go @@ -1,55 +1,80 @@ package gpio import ( + "fmt" "time" "gobot.io/x/gobot/v2" ) +// buttonOptionApplier needs to be implemented by each configurable option type +type buttonOptionApplier interface { + apply(cfg *buttonConfiguration) +} + +// buttonConfiguration contains all changeable attributes of the driver. +type buttonConfiguration struct { + readInterval time.Duration + defaultState int +} + +// buttonReadIntervalOption is the type for applying another read interval to the configuration +type buttonReadIntervalOption time.Duration + +// buttonDefaultStateOption is the type for applying another default state to the configuration +type buttonDefaultStateOption int + // ButtonDriver Represents a digital Button type ButtonDriver struct { - *Driver + *driver + buttonCfg *buttonConfiguration gobot.Eventer - pin string - active bool - defaultState int - halt chan bool - interval time.Duration + active bool + halt chan struct{} } -// NewButtonDriver returns a new ButtonDriver with a polling interval of -// 10 Milliseconds given a DigitalReader and pin. +// NewButtonDriver returns a driver for a button with a polling interval for changed state of 10 milliseconds, +// given a DigitalReader and pin. // -// Optionally accepts: +// Supported options: // -// time.Duration: Interval at which the ButtonDriver is polled for new information -func NewButtonDriver(a DigitalReader, pin string, v ...time.Duration) *ButtonDriver { +// "WithName" +// "WithButtonPollInterval" +func NewButtonDriver(a DigitalReader, pin string, opts ...interface{}) *ButtonDriver { //nolint:forcetypeassert // no error return value, so there is no better way d := &ButtonDriver{ - Driver: NewDriver(a.(gobot.Connection), "Button"), - Eventer: gobot.NewEventer(), - pin: pin, - active: false, - defaultState: 0, - interval: 10 * time.Millisecond, - halt: make(chan bool), + driver: newDriver(a.(gobot.Connection), "Button", withPin(pin)), + buttonCfg: &buttonConfiguration{readInterval: 10 * time.Millisecond, defaultState: 0}, } d.afterStart = d.initialize d.beforeHalt = d.shutdown - if len(v) > 0 { - d.interval = v[0] + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case buttonOptionApplier: + o.apply(d.buttonCfg) + case time.Duration: + // TODO this is only for backward compatibility and will be removed after version 2.x + d.buttonCfg.readInterval = o + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } } - d.AddEvent(ButtonPush) - d.AddEvent(ButtonRelease) - d.AddEvent(Error) - return d } -// Pin returns the ButtonDrivers pin -func (d *ButtonDriver) Pin() string { return d.pin } +// WithButtonPollInterval change the asynchronous cyclic reading interval from default 10ms to the given value. +func WithButtonPollInterval(interval time.Duration) buttonOptionApplier { + return buttonReadIntervalOption(interval) +} + +// WithButtonDefaultState change the default state from default 0 to the given value. +func WithButtonDefaultState(s int) buttonOptionApplier { + return buttonDefaultStateOption(s) +} // Active gets the current state func (d *ButtonDriver) Active() bool { @@ -61,12 +86,13 @@ func (d *ButtonDriver) Active() bool { } // SetDefaultState for the next start. +// Deprecated: Please use option [gpio.WithButtonDefaultState] instead. func (d *ButtonDriver) SetDefaultState(s int) { // ensure that read and write can not interfere d.mutex.Lock() defer d.mutex.Unlock() - d.defaultState = s + WithButtonDefaultState(s).apply(d.buttonCfg) } // initialize the ButtonDriver and polls the state of the button at the given interval. @@ -77,18 +103,30 @@ func (d *ButtonDriver) SetDefaultState(s int) { // Release int - On button release // Error error - On button error func (d *ButtonDriver) initialize() error { - state := d.defaultState + if d.buttonCfg.readInterval == 0 { + return fmt.Errorf("the read interval for button needs to be greater than zero") + } + + d.Eventer = gobot.NewEventer() + d.AddEvent(ButtonPush) + d.AddEvent(ButtonRelease) + d.AddEvent(Error) + + d.halt = make(chan struct{}) + + state := d.buttonCfg.defaultState + go func() { for { - newValue, err := d.connection.(DigitalReader).DigitalRead(d.Pin()) - if err != nil { - d.Publish(Error, err) - } else if newValue != state && newValue != -1 { - state = newValue - d.update(newValue) - } select { - case <-time.After(d.interval): + case <-time.After(d.buttonCfg.readInterval): + newValue, err := d.digitalRead(d.driverCfg.pin) + if err != nil { + d.Publish(Error, err) + } else if newValue != state && newValue != -1 { + state = newValue + d.update(newValue) + } case <-d.halt: return } @@ -98,7 +136,12 @@ func (d *ButtonDriver) initialize() error { } func (d *ButtonDriver) shutdown() error { - d.halt <- true + if d.buttonCfg.readInterval == 0 || d.halt == nil { + // cyclic reading deactivated + return nil + } + + close(d.halt) // broadcast halt, also to the test return nil } @@ -107,7 +150,7 @@ func (d *ButtonDriver) update(newValue int) { d.mutex.Lock() defer d.mutex.Unlock() - if newValue != d.defaultState { + if newValue != d.buttonCfg.defaultState { d.active = true d.Publish(ButtonPush, newValue) } else { @@ -115,3 +158,19 @@ func (d *ButtonDriver) update(newValue int) { d.Publish(ButtonRelease, newValue) } } + +func (o buttonReadIntervalOption) String() string { + return "read interval option for buttons" +} + +func (o buttonDefaultStateOption) String() string { + return "default state option for buttons" +} + +func (o buttonReadIntervalOption) apply(cfg *buttonConfiguration) { + cfg.readInterval = time.Duration(o) +} + +func (o buttonDefaultStateOption) apply(cfg *buttonConfiguration) { + cfg.defaultState = int(o) +} diff --git a/drivers/gpio/button_driver_test.go b/drivers/gpio/button_driver_test.go index 9503b48e2..b8824e38c 100644 --- a/drivers/gpio/button_driver_test.go +++ b/drivers/gpio/button_driver_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*ButtonDriver)(nil) @@ -30,21 +31,52 @@ func TestNewButtonDriver(t *testing.T) { d := NewButtonDriver(a, "1") // assert assert.IsType(t, &ButtonDriver{}, d) - assert.True(t, strings.HasPrefix(d.name, "Button")) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "Button")) + assert.Equal(t, "1", d.driverCfg.pin) assert.Equal(t, a, d.connection) assert.NotNil(t, d.afterStart) assert.NotNil(t, d.beforeHalt) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) - assert.NotNil(t, d.Eventer) - assert.Equal(t, "1", d.pin) + // assert: driver specific attributes assert.False(t, d.active) - assert.Equal(t, 0, d.defaultState) - assert.Equal(t, 10*time.Millisecond, d.interval) - assert.NotNil(t, d.halt) - // act & assert other interval - d = NewButtonDriver(newGpioTestAdaptor(), "1", 30*time.Second) - assert.Equal(t, 30*time.Second, d.interval) + assert.Nil(t, d.Eventer) // will be created on initialize + assert.Nil(t, d.halt) // will be created on initialize + require.NotNil(t, d.buttonCfg) + assert.Equal(t, 0, d.buttonCfg.defaultState) + assert.Equal(t, 10*time.Millisecond, d.buttonCfg.readInterval) +} + +func TestNewButtonDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "count up" + cycReadDur = 30 * time.Millisecond + ) + panicFunc := func() { + NewButtonDriver(newGpioTestAdaptor(), "1", WithName("crazy"), aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewButtonDriver(newGpioTestAdaptor(), "1", WithName(myName), WithButtonPollInterval(cycReadDur)) + // assert + assert.Equal(t, cycReadDur, d.buttonCfg.readInterval) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + +func TestButton_WithButtonDefaultState(t *testing.T) { + // arrange + const myDefaultState = 5 // only for test, usually it would be 0 or 1 + cfg := buttonConfiguration{} + // act + WithButtonDefaultState(myDefaultState).apply(&cfg) + // assert + assert.Equal(t, myDefaultState, cfg.defaultState) } func TestButtonStart(t *testing.T) { @@ -67,22 +99,22 @@ func TestButtonStart(t *testing.T) { } } + // act: start cyclic reading + err := d.Start() + _ = d.Once(ButtonPush, func(data interface{}) { assert.True(t, d.Active()) nextVal <- 0 sem <- true }) - // act - err := d.Start() - // assert & rearrange require.NoError(t, err) select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): - t.Errorf("Button Event \"Push\" was not published") + assert.Fail(t, "Button Event \"Push\" was not published") } _ = d.Once(ButtonRelease, func(data interface{}) { @@ -94,7 +126,7 @@ func TestButtonStart(t *testing.T) { select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): - t.Errorf("Button Event \"Release\" was not published") + assert.Fail(t, "Button Event \"Release\" was not published") } _ = d.Once(Error, func(data interface{}) { @@ -104,28 +136,29 @@ func TestButtonStart(t *testing.T) { select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): - t.Errorf("Button Event \"Error\" was not published") + assert.Fail(t, "Button Event \"Error\" was not published") } _ = d.Once(ButtonPush, func(data interface{}) { sem <- true }) - d.halt <- true + require.NoError(t, d.Halt()) nextVal <- 1 select { case <-sem: - t.Errorf("Button Event \"Press\" should not published") + assert.Fail(t, "Button Event \"Press\" should not published") case <-time.After(buttonTestDelay * time.Millisecond): } } -func TestButtonSetDefaultState(t *testing.T) { +func TestButtonStart_WithDefaultState(t *testing.T) { // arrange sem := make(chan bool) nextVal := make(chan int, 1) - d, a := initTestButtonDriverWithStubbedAdaptor() + a := newGpioTestAdaptor() + d := NewButtonDriver(a, "1", WithButtonDefaultState(1)) a.digitalReadFunc = func(string) (int, error) { val := 0 @@ -136,23 +169,19 @@ func TestButtonSetDefaultState(t *testing.T) { return val, nil } } + + // act: start cyclic reading + require.NoError(t, d.Start()) _ = d.Once(ButtonPush, func(data interface{}) { assert.True(t, d.Active()) nextVal <- 1 sem <- true }) - // act - d.SetDefaultState(1) - - // assert & rearrange - require.Equal(t, 1, d.defaultState) - require.NoError(t, d.Start()) - select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): - t.Errorf("Button Event \"Push\" was not published") + assert.Fail(t, "Button Event \"Push\" was not published") } _ = d.Once(ButtonRelease, func(data interface{}) { @@ -164,22 +193,23 @@ func TestButtonSetDefaultState(t *testing.T) { select { case <-sem: case <-time.After(buttonTestDelay * time.Millisecond): - t.Errorf("Button Event \"Release\" was not published") + assert.Fail(t, "Button Event \"Release\" was not published") } } func TestButtonHalt(t *testing.T) { // arrange d, _ := initTestButtonDriverWithStubbedAdaptor() - const timeout = 10 * time.Microsecond + require.NoError(t, d.Start()) + timeout := 2 * d.buttonCfg.readInterval wg := sync.WaitGroup{} wg.Add(1) go func() { defer wg.Done() select { - case <-d.halt: // wait until halt was set to the channel + case <-d.halt: // wait until halt is broadcasted by close the channel case <-time.After(timeout): // otherwise run into the timeout - t.Errorf("halt was not received within %s", timeout) + assert.Fail(t, "halt was not received within %s", timeout) } }() // act & assert @@ -187,23 +217,6 @@ func TestButtonHalt(t *testing.T) { wg.Wait() // wait until the go function was really finished } -func TestButtonPin(t *testing.T) { - tests := map[string]struct { - want string - }{ - "10": {want: "10"}, - "36": {want: "36"}, - } - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - // arrange - d := ButtonDriver{pin: name} - // act & assert - assert.Equal(t, tc.want, d.Pin()) - }) - } -} - func TestButtonActive(t *testing.T) { tests := map[string]struct { want bool @@ -214,7 +227,7 @@ func TestButtonActive(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - d := ButtonDriver{Driver: NewDriver(nil, "Button")} // just for mutex + d := ButtonDriver{driver: newDriver(nil, "Button")} // just for mutex d.active = tc.want // act & assert assert.Equal(t, tc.want, d.Active()) diff --git a/drivers/gpio/buzzer_driver.go b/drivers/gpio/buzzer_driver.go index 333985678..368032fd2 100644 --- a/drivers/gpio/buzzer_driver.go +++ b/drivers/gpio/buzzer_driver.go @@ -1,7 +1,7 @@ package gpio import ( - "log" + "fmt" "time" "gobot.io/x/gobot/v2" @@ -128,63 +128,55 @@ const ( B8 = 7902.13 ) -var _ gobot.Driver = (*BuzzerDriver)(nil) - // BuzzerDriver represents a digital buzzer type BuzzerDriver struct { - pin string - name string - connection DigitalWriter - high bool - BPM float64 + *driver + high bool + bpm float64 } // NewBuzzerDriver return a new BuzzerDriver given a DigitalWriter and pin. -func NewBuzzerDriver(a DigitalWriter, pin string) *BuzzerDriver { - l := &BuzzerDriver{ - name: gobot.DefaultName("Buzzer"), - pin: pin, - connection: a, - high: false, - BPM: 96.0, +// +// Supported options: +// +// "WithName" +func NewBuzzerDriver(a DigitalWriter, pin string, opts ...interface{}) *BuzzerDriver { + //nolint:forcetypeassert // no error return value, so there is no better way + d := &BuzzerDriver{ + driver: newDriver(a.(gobot.Connection), "Buzzer", withPin(pin)), + bpm: 96.0, } - return l -} - -// Start implements the Driver interface -func (d *BuzzerDriver) Start() error { return nil } - -// Halt implements the Driver interface -func (d *BuzzerDriver) Halt() error { return nil } - -// Name returns the BuzzerDrivers name -func (d *BuzzerDriver) Name() string { return d.name } - -// SetName sets the BuzzerDrivers name -func (d *BuzzerDriver) SetName(n string) { d.name = n } + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } + } -// Pin returns the BuzzerDrivers name -func (d *BuzzerDriver) Pin() string { return d.pin } + return d +} -// Connection returns the BuzzerDrivers Connection -func (d *BuzzerDriver) Connection() gobot.Connection { - if conn, ok := d.connection.(gobot.Connection); ok { - return conn - } +// SetBPM change the bpm value. +func (d *BuzzerDriver) SetBPM(val float64) { + d.bpm = val +} - log.Printf("%s has no gobot connection\n", d.name) - return nil +// BPM gets the current bpm value. +func (d *BuzzerDriver) BPM() float64 { + return d.bpm } -// State return true if the buzzer is On and false if the led is Off +// State return true if the buzzer is on and false if the buzzer is off func (d *BuzzerDriver) State() bool { return d.high } // On sets the buzzer to a high state. func (d *BuzzerDriver) On() error { - if err := d.connection.DigitalWrite(d.Pin(), 1); err != nil { + if err := d.digitalWrite(d.driverCfg.pin, 1); err != nil { return err } d.high = true @@ -193,7 +185,7 @@ func (d *BuzzerDriver) On() error { // Off sets the buzzer to a low state. func (d *BuzzerDriver) Off() error { - if err := d.connection.DigitalWrite(d.Pin(), 0); err != nil { + if err := d.digitalWrite(d.driverCfg.pin, 0); err != nil { return err } d.high = false @@ -213,7 +205,7 @@ func (d *BuzzerDriver) Tone(hz, duration float64) error { // calculation based off https://www.arduino.cc/en/Tutorial/Melody tone := (1.0 / (2.0 * hz)) * 1000000.0 - tempo := ((60 / d.BPM) * (duration * 1000)) + tempo := ((60 / d.bpm) * (duration * 1000)) for i := 0.0; i < tempo*1000; i += tone * 2.0 { if err := d.On(); err != nil { diff --git a/drivers/gpio/buzzer_driver_test.go b/drivers/gpio/buzzer_driver_test.go index f1486ff1a..d88bdcdc8 100644 --- a/drivers/gpio/buzzer_driver_test.go +++ b/drivers/gpio/buzzer_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*BuzzerDriver)(nil) @@ -17,42 +18,61 @@ func initTestBuzzerDriver(conn DigitalWriter) *BuzzerDriver { return NewBuzzerDriver(conn, "1") } -func TestBuzzerDriverDefaultName(t *testing.T) { - g := initTestBuzzerDriver(newGpioTestAdaptor()) - assert.True(t, strings.HasPrefix(g.Name(), "Buzzer")) -} - -func TestBuzzerDriverSetName(t *testing.T) { - g := initTestBuzzerDriver(newGpioTestAdaptor()) - g.SetName("mybot") - assert.Equal(t, "mybot", g.Name()) -} - -func TestBuzzerDriverStart(t *testing.T) { - d := initTestBuzzerDriver(newGpioTestAdaptor()) - require.NoError(t, d.Start()) +func TestNewBuzzerDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewBuzzerDriver(a, "10") + // assert + assert.IsType(t, &BuzzerDriver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "Buzzer")) + assert.Equal(t, "10", d.driverCfg.pin) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.False(t, d.high) + assert.InDelta(t, 96, d.bpm, 0.0) } -func TestBuzzerDriverHalt(t *testing.T) { - d := initTestBuzzerDriver(newGpioTestAdaptor()) - require.NoError(t, d.Halt()) +func TestNewBuzzerDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "song player" + ) + panicFunc := func() { + NewBuzzerDriver(newGpioTestAdaptor(), "1", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewBuzzerDriver(newGpioTestAdaptor(), "1", WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } -func TestBuzzerDriverToggle(t *testing.T) { +func TestBuzzerToggle(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) - _ = d.Off() - _ = d.Toggle() + require.NoError(t, d.Off()) + require.NoError(t, d.Toggle()) assert.True(t, d.State()) - _ = d.Toggle() + require.NoError(t, d.Toggle()) assert.False(t, d.State()) } -func TestBuzzerDriverTone(t *testing.T) { +func TestBuzzerTone(t *testing.T) { d := initTestBuzzerDriver(newGpioTestAdaptor()) require.NoError(t, d.Tone(100, 0.01)) } -func TestBuzzerDriverOnError(t *testing.T) { +func TestBuzzerOnError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) a.digitalWriteFunc = func(string, byte) error { @@ -62,7 +82,7 @@ func TestBuzzerDriverOnError(t *testing.T) { require.EqualError(t, d.On(), "write error") } -func TestBuzzerDriverOffError(t *testing.T) { +func TestBuzzerOffError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) a.digitalWriteFunc = func(string, byte) error { @@ -72,7 +92,7 @@ func TestBuzzerDriverOffError(t *testing.T) { require.EqualError(t, d.Off(), "write error") } -func TestBuzzerDriverToneError(t *testing.T) { +func TestBuzzerToneError(t *testing.T) { a := newGpioTestAdaptor() d := initTestBuzzerDriver(a) a.digitalWriteFunc = func(string, byte) error { diff --git a/drivers/gpio/direct_pin_driver.go b/drivers/gpio/direct_pin_driver.go index 65afdcf26..c62dabbfd 100644 --- a/drivers/gpio/direct_pin_driver.go +++ b/drivers/gpio/direct_pin_driver.go @@ -8,26 +8,24 @@ import ( // DirectPinDriver represents a GPIO pin type DirectPinDriver struct { - name string - pin string - connection gobot.Connection - gobot.Commander + *driver } // NewDirectPinDriver return a new DirectPinDriver given a Connection and pin. // +// Supported options: +// +// "WithName" +// // Adds the following API Commands: // // "DigitalRead" - See DirectPinDriver.DigitalRead // "DigitalWrite" - See DirectPinDriver.DigitalWrite // "PwmWrite" - See DirectPinDriver.PwmWrite // "ServoWrite" - See DirectPinDriver.ServoWrite -func NewDirectPinDriver(a gobot.Connection, pin string) *DirectPinDriver { +func NewDirectPinDriver(a gobot.Connection, pin string, opts ...interface{}) *DirectPinDriver { d := &DirectPinDriver{ - name: gobot.DefaultName("DirectPin"), - connection: a, - pin: pin, - Commander: gobot.NewCommander(), + driver: newDriver(a, "DirectPin", append(opts, withPin(pin))...), } d.AddCommand("DigitalRead", func(params map[string]interface{}) interface{} { @@ -50,74 +48,32 @@ func NewDirectPinDriver(a gobot.Connection, pin string) *DirectPinDriver { 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() error { return nil } - -// Halt implements the Driver interface -func (d *DirectPinDriver) Halt() error { return nil } - // Off turn off pin func (d *DirectPinDriver) Off() error { - if writer, ok := d.Connection().(DigitalWriter); ok { - return writer.DigitalWrite(d.Pin(), byte(0)) - } - - return ErrDigitalWriteUnsupported + return d.digitalWrite(d.driverCfg.pin, byte(0)) } // On turn on pin func (d *DirectPinDriver) On() error { - if writer, ok := d.Connection().(DigitalWriter); ok { - return writer.DigitalWrite(d.Pin(), byte(1)) - } - - return ErrDigitalWriteUnsupported + return d.digitalWrite(d.driverCfg.pin, byte(1)) } // DigitalRead returns the current digital state of the pin func (d *DirectPinDriver) DigitalRead() (int, error) { - if reader, ok := d.Connection().(DigitalReader); ok { - return reader.DigitalRead(d.Pin()) - } - - return 0, ErrDigitalReadUnsupported + return d.digitalRead(d.driverCfg.pin) } // DigitalWrite writes to the pin. Acceptable values are 1 or 0 func (d *DirectPinDriver) DigitalWrite(level byte) error { - if writer, ok := d.Connection().(DigitalWriter); ok { - return writer.DigitalWrite(d.Pin(), level) - } - - return ErrDigitalWriteUnsupported + return d.digitalWrite(d.driverCfg.pin, level) } // PwmWrite writes the 0-254 value to the specified pin func (d *DirectPinDriver) PwmWrite(level byte) error { - if writer, ok := d.Connection().(PwmWriter); ok { - return writer.PwmWrite(d.Pin(), level) - } - - return ErrPwmWriteUnsupported + return d.pwmWrite(d.driverCfg.pin, level) } // ServoWrite writes value to the specified pin func (d *DirectPinDriver) ServoWrite(level byte) error { - if writer, ok := d.Connection().(ServoWriter); ok { - return writer.ServoWrite(d.Pin(), level) - } - - return ErrServoWriteUnsupported + return d.servoWrite(d.driverCfg.pin, level) } diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index 9512467f9..0fd876fa2 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*DirectPinDriver)(nil) @@ -31,14 +32,48 @@ func initTestDirectPinDriver() *DirectPinDriver { return NewDirectPinDriver(a, "1") } -func TestDirectPinDriver(t *testing.T) { +func TestNewDirectPinDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewDirectPinDriver(a, "10") + // assert + assert.IsType(t, &DirectPinDriver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "DirectPin")) + assert.Equal(t, "10", d.driverCfg.pin) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) +} + +func TestNewDirectPinDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "count up" + ) + panicFunc := func() { + NewDirectPinDriver(newGpioTestAdaptor(), "1", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewDirectPinDriver(newGpioTestAdaptor(), "1", WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + +func TestDirectPin_Commands(t *testing.T) { var ret map[string]interface{} var err interface{} d := initTestDirectPinDriver() - assert.Equal(t, "1", d.Pin()) - assert.NotNil(t, d.Connection()) - ret = d.Command("DigitalRead")(nil).(map[string]interface{}) assert.Equal(t, 1, ret["val"].(int)) @@ -54,17 +89,7 @@ func TestDirectPinDriver(t *testing.T) { require.EqualError(t, err.(error), "write error") } -func TestDirectPinDriverStart(t *testing.T) { - d := initTestDirectPinDriver() - require.NoError(t, d.Start()) -} - -func TestDirectPinDriverHalt(t *testing.T) { - d := initTestDirectPinDriver() - require.NoError(t, d.Halt()) -} - -func TestDirectPinDriverOff(t *testing.T) { +func TestDirectPinOff(t *testing.T) { d := initTestDirectPinDriver() require.Error(t, d.Off()) @@ -73,101 +98,90 @@ func TestDirectPinDriverOff(t *testing.T) { require.NoError(t, d.Off()) } -func TestDirectPinDriverOffNotSupported(t *testing.T) { +func TestDirectPinOffNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") require.EqualError(t, d.Off(), "DigitalWrite is not supported by this platform") } -func TestDirectPinDriverOn(t *testing.T) { +func TestDirectPinOn(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") require.NoError(t, d.On()) } -func TestDirectPinDriverOnError(t *testing.T) { +func TestDirectPinOnError(t *testing.T) { d := initTestDirectPinDriver() require.Error(t, d.On()) } -func TestDirectPinDriverOnNotSupported(t *testing.T) { +func TestDirectPinOnNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") require.EqualError(t, d.On(), "DigitalWrite is not supported by this platform") } -func TestDirectPinDriverDigitalWrite(t *testing.T) { +func TestDirectPinDigitalWrite(t *testing.T) { adaptor := newGpioTestAdaptor() d := NewDirectPinDriver(adaptor, "1") require.NoError(t, d.DigitalWrite(1)) } -func TestDirectPinDriverDigitalWriteNotSupported(t *testing.T) { +func TestDirectPinDigitalWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") require.EqualError(t, d.DigitalWrite(1), "DigitalWrite is not supported by this platform") } -func TestDirectPinDriverDigitalWriteError(t *testing.T) { +func TestDirectPinDigitalWriteError(t *testing.T) { d := initTestDirectPinDriver() require.Error(t, d.DigitalWrite(1)) } -func TestDirectPinDriverDigitalRead(t *testing.T) { +func TestDirectPinDigitalRead(t *testing.T) { d := initTestDirectPinDriver() ret, err := d.DigitalRead() assert.Equal(t, 1, ret) require.NoError(t, err) } -func TestDirectPinDriverDigitalReadNotSupported(t *testing.T) { +func TestDirectPinDigitalReadNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") _, e := d.DigitalRead() require.EqualError(t, e, "DigitalRead is not supported by this platform") } -func TestDirectPinDriverPwmWrite(t *testing.T) { +func TestDirectPinPwmWrite(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") require.NoError(t, d.PwmWrite(1)) } -func TestDirectPinDriverPwmWriteNotSupported(t *testing.T) { +func TestDirectPinPwmWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") require.EqualError(t, d.PwmWrite(1), "PwmWrite is not supported by this platform") } -func TestDirectPinDriverPwmWriteError(t *testing.T) { +func TestDirectPinPwmWriteError(t *testing.T) { d := initTestDirectPinDriver() require.Error(t, d.PwmWrite(1)) } -func TestDirectPinDriverServoWrite(t *testing.T) { +func TestDirectPinServoWrite(t *testing.T) { a := newGpioTestAdaptor() d := NewDirectPinDriver(a, "1") require.NoError(t, d.ServoWrite(1)) } -func TestDirectPinDriverServoWriteNotSupported(t *testing.T) { +func TestDirectPinServoWriteNotSupported(t *testing.T) { a := &gpioTestBareAdaptor{} d := NewDirectPinDriver(a, "1") require.EqualError(t, d.ServoWrite(1), "ServoWrite is not supported by this platform") } -func TestDirectPinDriverServoWriteError(t *testing.T) { +func TestDirectPinServoWriteError(t *testing.T) { d := initTestDirectPinDriver() require.Error(t, d.ServoWrite(1)) } - -func TestDirectPinDriverDefaultName(t *testing.T) { - d := initTestDirectPinDriver() - assert.True(t, strings.HasPrefix(d.Name(), "Direct")) -} - -func TestDirectPinDriverSetName(t *testing.T) { - d := initTestDirectPinDriver() - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) -} diff --git a/drivers/gpio/easy_driver.go b/drivers/gpio/easy_driver.go index 4bf22cf0e..2774badc8 100644 --- a/drivers/gpio/easy_driver.go +++ b/drivers/gpio/easy_driver.go @@ -10,19 +10,36 @@ import ( const easyDriverDebug = false +// easyOptionApplier needs to be implemented by each configurable option type +type easyOptionApplier interface { + apply(cfg *easyConfiguration) +} + +// easyConfiguration contains all changeable attributes of the driver. +type easyConfiguration struct { + dirPin string + enPin string + sleepPin string +} + +// easyDirPinOption is the type for applying a pin for change direction +type easyDirPinOption string + +// easyEnPinOption is the type for applying a pin for device disabling/enabling +type easyEnPinOption string + +// easySleepPinOption is the type for applying a pin for setting device to sleep/wake +type easySleepPinOption string + // EasyDriver is an driver for stepper hardware board from SparkFun (https://www.sparkfun.com/products/12779) // This should also work for the BigEasyDriver (untested). It is basically a wrapper for the common StepperDriver{} // with the specific additions for the board, e.g. direction, enable and sleep outputs. type EasyDriver struct { *StepperDriver - + easyCfg *easyConfiguration stepPin string - dirPin string - enPin string - sleepPin string anglePerStep float32 - - sleeping bool + sleeping bool } // NewEasyDriver returns a new driver @@ -30,39 +47,32 @@ type EasyDriver struct { // A - DigitalWriter // anglePerStep - Step angle of motor // stepPin - Pin corresponding to step input on EasyDriver -// dirPin - Pin corresponding to dir input on EasyDriver. Optional -// enPin - Pin corresponding to enabled input on EasyDriver. Optional -// sleepPin - Pin corresponding to sleep input on EasyDriver. Optional -func NewEasyDriver( - a DigitalWriter, - anglePerStep float32, - stepPin string, - dirPin string, - enPin string, - sleepPin string, -) *EasyDriver { +// +// Supported options: +// +// "WithName" +// "WithEasyDirectionPin" +// "WithEasyEnablePin" +// "WithEasySleepPin" +func NewEasyDriver(a DigitalWriter, anglePerStep float32, stepPin string, opts ...interface{}) *EasyDriver { if anglePerStep <= 0 { panic("angle per step needs to be greater than zero") } - // panic if step pin isn't set + if stepPin == "" { - panic("Step pin is not set") + panic("step pin is mandatory for easy driver") } stepper := NewStepperDriver(a, [4]string{}, nil, 1) - stepper.name = gobot.DefaultName("EasyDriver") + stepper.driverCfg.name = gobot.DefaultName("EasyDriver") stepper.stepperDebug = easyDriverDebug stepper.haltIfRunning = false stepper.stepsPerRev = 360.0 / anglePerStep d := &EasyDriver{ StepperDriver: stepper, + easyCfg: &easyConfiguration{}, stepPin: stepPin, - dirPin: dirPin, - enPin: enPin, - sleepPin: sleepPin, anglePerStep: anglePerStep, - - sleeping: false, } d.stepFunc = d.onePinStepping d.sleepFunc = d.sleepWithSleepPin @@ -71,28 +81,56 @@ func NewEasyDriver( // 1/4 of max speed. Not too fast, not too slow d.speedRpm = d.MaxSpeed() / 4 + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case easyOptionApplier: + o.apply(d.easyCfg) + default: + oNames := []string{"WithEasyDirectionPin", "WithEasyEnablePin", "WithEasySleepPin"} + msg := fmt.Sprintf("'%s' can not be applied on '%s', consider to use one of the options instead: %s", + opt, d.driverCfg.name, strings.Join(oNames, ", ")) + panic(msg) + } + } + return d } +// WithEasyDirectionPin configure a pin for change the moving direction. +func WithEasyDirectionPin(pin string) easyOptionApplier { + return easyDirPinOption(pin) +} + +// WithEasyEnablePin configure a pin for disabling/enabling the driver. +func WithEasyEnablePin(pin string) easyOptionApplier { + return easyEnPinOption(pin) +} + +// WithEasySleepPin configure a pin for sleep/wake the driver. +func WithEasySleepPin(pin string) easyOptionApplier { + return easySleepPinOption(pin) +} + // SetDirection sets the direction to be moving. func (d *EasyDriver) SetDirection(direction string) error { + if d.easyCfg.dirPin == "" { + return fmt.Errorf("dirPin is not set for '%s'", d.driverCfg.name) + } + direction = strings.ToLower(direction) if direction != StepperDriverForward && direction != StepperDriverBackward { return fmt.Errorf("Invalid direction '%s'. Value should be '%s' or '%s'", direction, StepperDriverForward, StepperDriverBackward) } - if d.dirPin == "" { - return fmt.Errorf("dirPin is not set for '%s'", d.name) - } - writeVal := byte(0) // low is forward if direction == StepperDriverBackward { writeVal = 1 // high is backward } - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(d.dirPin, writeVal); err != nil { + if err := d.digitalWrite(d.easyCfg.dirPin, writeVal); err != nil { return err } @@ -106,14 +144,13 @@ func (d *EasyDriver) SetDirection(direction string) error { // Enable enables all motor output func (d *EasyDriver) Enable() error { - if d.enPin == "" { + if d.easyCfg.enPin == "" { d.disabled = false - return fmt.Errorf("enPin is not set - board '%s' is enabled by default", d.name) + return fmt.Errorf("enPin is not set - board '%s' is enabled by default", d.driverCfg.name) } // enPin is active low - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(d.enPin, 0); err != nil { + if err := d.digitalWrite(d.easyCfg.enPin, 0); err != nil { return err } @@ -123,15 +160,14 @@ func (d *EasyDriver) Enable() error { // Disable disables all motor output func (d *EasyDriver) Disable() error { - if d.enPin == "" { - return fmt.Errorf("enPin is not set for '%s'", d.name) + if d.easyCfg.enPin == "" { + return fmt.Errorf("enPin is not set for '%s'", d.driverCfg.name) } _ = d.stopIfRunning() // drop step errors // enPin is active low - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(d.enPin, 1); err != nil { + if err := d.digitalWrite(d.easyCfg.enPin, 1); err != nil { return err } d.disabled = true @@ -146,13 +182,12 @@ func (d *EasyDriver) IsEnabled() bool { // Wake wakes up the driver func (d *EasyDriver) Wake() error { - if d.sleepPin == "" { - return fmt.Errorf("sleepPin is not set for '%s'", d.name) + if d.easyCfg.sleepPin == "" { + return fmt.Errorf("sleepPin is not set for '%s'", d.driverCfg.name) } // sleepPin is active low - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(d.sleepPin, 1); err != nil { + if err := d.digitalWrite(d.easyCfg.sleepPin, 1); err != nil { return err } @@ -175,14 +210,12 @@ func (d *EasyDriver) onePinStepping() error { defer d.valueMutex.Unlock() // a valid steps occurs for a low to high transition - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(d.stepPin, 0); err != nil { + if err := d.digitalWrite(d.stepPin, 0); err != nil { return err } time.Sleep(d.getDelayPerStep()) - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(d.stepPin, 1); err != nil { + if err := d.digitalWrite(d.stepPin, 1); err != nil { return err } @@ -197,18 +230,41 @@ func (d *EasyDriver) onePinStepping() error { // sleepWithSleepPin puts the driver to sleep and disables all motor output. Low power mode. func (d *EasyDriver) sleepWithSleepPin() error { - if d.sleepPin == "" { - return fmt.Errorf("sleepPin is not set for '%s'", d.name) + if d.easyCfg.sleepPin == "" { + return fmt.Errorf("sleepPin is not set for '%s'", d.driverCfg.name) } _ = d.stopIfRunning() // drop step errors // sleepPin is active low - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(d.sleepPin, 0); err != nil { + if err := d.digitalWrite(d.easyCfg.sleepPin, 0); err != nil { return err } d.sleeping = true return nil } + +func (o easyDirPinOption) String() string { + return "direction pin option easy driver" +} + +func (o easyEnPinOption) String() string { + return "enable pin option easy driver" +} + +func (o easySleepPinOption) String() string { + return "sleep pin option easy driver" +} + +func (o easyDirPinOption) apply(cfg *easyConfiguration) { + cfg.dirPin = string(o) +} + +func (o easyEnPinOption) apply(cfg *easyConfiguration) { + cfg.enPin = string(o) +} + +func (o easySleepPinOption) apply(cfg *easyConfiguration) { + cfg.sleepPin = string(o) +} diff --git a/drivers/gpio/easy_driver_test.go b/drivers/gpio/easy_driver_test.go index 11c5cd6f6..d12099613 100644 --- a/drivers/gpio/easy_driver_test.go +++ b/drivers/gpio/easy_driver_test.go @@ -8,13 +8,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2/drivers/aio" ) func initTestEasyDriverWithStubbedAdaptor() (*EasyDriver, *gpioTestAdaptor) { const anglePerStep = 0.5 // use non int step angle to check int math a := newGpioTestAdaptor() - d := NewEasyDriver(a, anglePerStep, "1", "2", "3", "4") + d := NewEasyDriver(a, anglePerStep, "1") return d, a } @@ -24,19 +26,19 @@ func TestNewEasyDriver(t *testing.T) { a := newGpioTestAdaptor() // act - d := NewEasyDriver(a, anglePerStep, "1", "2", "3", "4") + d := NewEasyDriver(a, anglePerStep, "1") // assert assert.IsType(t, &EasyDriver{}, d) - assert.True(t, strings.HasPrefix(d.name, "EasyDriver")) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "EasyDriver")) assert.Equal(t, a, d.connection) require.NoError(t, d.afterStart()) require.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) + // assert: driver specific attributes assert.Equal(t, "1", d.stepPin) - assert.Equal(t, "2", d.dirPin) - assert.Equal(t, "3", d.enPin) - assert.Equal(t, "4", d.sleepPin) assert.InDelta(t, float32(anglePerStep), d.anglePerStep, 0.0) assert.Equal(t, uint(14), d.speedRpm) assert.Equal(t, "forward", d.direction) @@ -44,9 +46,55 @@ func TestNewEasyDriver(t *testing.T) { assert.False(t, d.disabled) assert.False(t, d.sleeping) assert.Nil(t, d.stopAsynchRunFunc) + require.NotNil(t, d.easyCfg) + assert.Empty(t, d.easyCfg.dirPin) + assert.Empty(t, d.easyCfg.enPin) + assert.Empty(t, d.easyCfg.sleepPin) +} + +func TestNewEasyDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "front wheel" + dirPin = "2" + ) + panicFunc := func() { + NewEasyDriver(newGpioTestAdaptor(), 0.1, "1", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewEasyDriver(newGpioTestAdaptor(), 0.2, "1", WithName(myName), WithEasyDirectionPin(dirPin)) + // assert + assert.Equal(t, dirPin, d.easyCfg.dirPin) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy', "+ + "consider to use one of the options instead: WithEasyDirectionPin, WithEasyEnablePin, WithEasySleepPin", panicFunc) +} + +func TestEasy_WithEasyEnablePin(t *testing.T) { + // arrange + const myEnablePin = "3" + cfg := easyConfiguration{} + // act + WithEasyEnablePin(myEnablePin).apply(&cfg) + // assert + assert.Equal(t, myEnablePin, cfg.enPin) +} + +func TestEasy_WithEasySleepPin(t *testing.T) { + // arrange + const mySleepPin = "4" + cfg := easyConfiguration{} + // act + WithEasySleepPin(mySleepPin).apply(&cfg) + // assert + assert.Equal(t, mySleepPin, cfg.sleepPin) } -func TestEasyDriverMoveDeg_IsMoving(t *testing.T) { +func TestEasyMoveDeg_IsMoving(t *testing.T) { tests := map[string]struct { inputDeg int simulateDisabled bool @@ -121,7 +169,7 @@ func TestEasyDriverMoveDeg_IsMoving(t *testing.T) { } } -func TestEasyDriverRun_IsMoving(t *testing.T) { +func TestEasyRun_IsMoving(t *testing.T) { tests := map[string]struct { simulateDisabled bool simulateAlreadyRunning bool @@ -177,7 +225,7 @@ func TestEasyDriverRun_IsMoving(t *testing.T) { } } -func TestEasyDriverStop_IsMoving(t *testing.T) { +func TestEasyStop_IsMoving(t *testing.T) { // arrange d, _ := initTestEasyDriverWithStubbedAdaptor() require.NoError(t, d.Run()) @@ -201,7 +249,7 @@ func TestEasyDriverHalt_IsMoving(t *testing.T) { assert.False(t, d.IsMoving()) } -func TestEasyDriverSetDirection(t *testing.T) { +func TestEasySetDirection(t *testing.T) { const anglePerStep = 0.5 // use non int step angle to check int math tests := map[string]struct { @@ -251,7 +299,7 @@ func TestEasyDriverSetDirection(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, anglePerStep, "1", tc.dirPin, "3", "4") + d := NewEasyDriver(a, anglePerStep, "1", WithEasyDirectionPin(tc.dirPin)) a.written = nil // reset writes of Start() a.simulateWriteError = tc.simulateWriteErr require.Equal(t, "forward", d.direction) @@ -270,7 +318,7 @@ func TestEasyDriverSetDirection(t *testing.T) { } } -func TestEasyDriverMaxSpeed(t *testing.T) { +func TestEasyMaxSpeed(t *testing.T) { const delayForMaxSpeed = 1428 * time.Microsecond // 1/700Hz tests := map[string]struct { @@ -315,7 +363,7 @@ func TestEasyDriverMaxSpeed(t *testing.T) { } } -func TestEasyDriverSetSpeed(t *testing.T) { +func TestEasySetSpeed(t *testing.T) { const ( anglePerStep = 10 maxRpm = 1166 @@ -365,7 +413,7 @@ func TestEasyDriverSetSpeed(t *testing.T) { } } -func TestEasyDriver_onePinStepping(t *testing.T) { +func TestEasy_onePinStepping(t *testing.T) { tests := map[string]struct { countCallsForth int countCallsBack int @@ -469,7 +517,7 @@ func TestEasyDriver_onePinStepping(t *testing.T) { } } -func TestEasyDriverEnable_IsEnabled(t *testing.T) { +func TestEasyEnable_IsEnabled(t *testing.T) { const anglePerStep = 0.5 // use non int step angle to check int math tests := map[string]struct { @@ -507,7 +555,7 @@ func TestEasyDriverEnable_IsEnabled(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, anglePerStep, "1", "2", tc.enPin, "4") + d := NewEasyDriver(a, anglePerStep, "1", WithEasyEnablePin(tc.enPin)) a.written = nil // reset writes of Start() a.simulateWriteError = tc.simulateWriteErr d.disabled = true @@ -528,7 +576,7 @@ func TestEasyDriverEnable_IsEnabled(t *testing.T) { } } -func TestEasyDriverDisable_IsEnabled(t *testing.T) { +func TestEasyDisable_IsEnabled(t *testing.T) { const anglePerStep = 0.5 // use non int step angle to check int math tests := map[string]struct { @@ -568,7 +616,7 @@ func TestEasyDriverDisable_IsEnabled(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, anglePerStep, "1", "2", tc.enPin, "4") + d := NewEasyDriver(a, anglePerStep, "1", WithEasyEnablePin(tc.enPin)) var numCallsWrite int var writtenPin string writtenValue := byte(0xFF) @@ -609,7 +657,7 @@ func TestEasyDriverDisable_IsEnabled(t *testing.T) { } } -func TestEasyDriverSleep_IsSleeping(t *testing.T) { +func TestEasySleep_IsSleeping(t *testing.T) { const anglePerStep = 0.5 // use non int step angle to check int math tests := map[string]struct { @@ -649,7 +697,7 @@ func TestEasyDriverSleep_IsSleeping(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, anglePerStep, "1", "2", "3", tc.sleepPin) + d := NewEasyDriver(a, anglePerStep, "1", WithEasySleepPin(tc.sleepPin)) d.sleeping = false require.False(t, d.IsSleeping()) // arrange: writes @@ -688,7 +736,7 @@ func TestEasyDriverSleep_IsSleeping(t *testing.T) { } } -func TestEasyDriverWake_IsSleeping(t *testing.T) { +func TestEasyWake_IsSleeping(t *testing.T) { const anglePerStep = 0.5 // use non int step angle to check int math tests := map[string]struct { @@ -721,7 +769,7 @@ func TestEasyDriverWake_IsSleeping(t *testing.T) { t.Run(name, func(t *testing.T) { // arrange a := newGpioTestAdaptor() - d := NewEasyDriver(a, anglePerStep, "1", "2", "3", tc.sleepPin) + d := NewEasyDriver(a, anglePerStep, "1", WithEasySleepPin(tc.sleepPin)) d.sleeping = true require.True(t, d.IsSleeping()) // arrange: writes diff --git a/drivers/gpio/gpio_driver.go b/drivers/gpio/gpio_driver.go index 52d11a919..97659755a 100644 --- a/drivers/gpio/gpio_driver.go +++ b/drivers/gpio/gpio_driver.go @@ -2,6 +2,7 @@ package gpio import ( "errors" + "fmt" "log" "sync" @@ -15,18 +16,12 @@ var ( // ErrPwmWriteUnsupported is the error resulting when a driver attempts to use // hardware capabilities which a connection does not support ErrPwmWriteUnsupported = errors.New("PwmWrite is not supported by this platform") - // 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") // ErrDigitalWriteUnsupported is the error resulting when a driver attempts to use // hardware capabilities which a connection does not support ErrDigitalWriteUnsupported = errors.New("DigitalWrite is not supported by this platform") // ErrDigitalReadUnsupported is the error resulting when a driver attempts to use // hardware capabilities which a connection does not support ErrDigitalReadUnsupported = errors.New("DigitalRead is not supported by this platform") - // ErrServoOutOfRange is the error resulting when a driver attempts to use - // hardware capabilities which a connection does not support - ErrServoOutOfRange = errors.New("servo angle must be between 0-180") ) const ( @@ -36,10 +31,6 @@ const ( ButtonRelease = "release" // ButtonPush event ButtonPush = "push" - // Data event - Data = "data" - // Vibration event - Vibration = "vibration" // MotionDetected event MotionDetected = "motion-detected" // MotionStopped event @@ -66,9 +57,26 @@ type DigitalReader interface { DigitalRead(pin string) (val int, err error) } +// optionApplier needs to be implemented by each configurable option type +type optionApplier interface { + apply(cfg *configuration) +} + +// configuration contains all changeable attributes of the driver. +type configuration struct { + name string + pin string +} + +// nameOption is the type for applying another name to the configuration +type nameOption string + +// pinOption is the type for applying a pin to the configuration +type pinOption string + // Driver implements the interface gobot.Driver. -type Driver struct { - name string +type driver struct { + driverCfg *configuration connection gobot.Adaptor afterStart func() error beforeHalt func() error @@ -76,10 +84,15 @@ type Driver struct { mutex *sync.Mutex // mutex often needed to ensure that write-read sequences are not interrupted } -// NewDriver creates a new generic and basic gpio gobot driver. -func NewDriver(a gobot.Adaptor, name string) *Driver { - d := &Driver{ - name: gobot.DefaultName(name), +// newDriver creates a new generic and basic gpio gobot driver. +// +// Supported options: +// +// "WithName" +// "withPin" +func newDriver(a gobot.Adaptor, name string, opts ...interface{}) *driver { + d := &driver{ + driverCfg: &configuration{name: gobot.DefaultName(name)}, connection: a, afterStart: func() error { return nil }, beforeHalt: func() error { return nil }, @@ -87,31 +100,57 @@ func NewDriver(a gobot.Adaptor, name string) *Driver { mutex: &sync.Mutex{}, } + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } + } + return d } +// WithName is used to replace the default name of the driver. +func WithName(name string) optionApplier { + return nameOption(name) +} + +// withPin is used to add a pin to the driver. Only one pin can be linked. +// This option is not available outside gpio package. +func withPin(pin string) optionApplier { + return pinOption(pin) +} + // Name returns the name of the gpio device. -func (d *Driver) Name() string { - return d.name +func (d *driver) Name() string { + return d.driverCfg.name } // SetName sets the name of the gpio device. -func (d *Driver) SetName(name string) { - d.name = name +// Deprecated: Please use option [gpio.WithName] instead. +func (d *driver) SetName(name string) { + WithName(name).apply(d.driverCfg) +} + +// Pin returns the pin associated with the driver. +func (d *driver) Pin() string { + return d.driverCfg.pin } // Connection returns the connection of the gpio device. -func (d *Driver) Connection() gobot.Connection { +func (d *driver) Connection() gobot.Connection { if conn, ok := d.connection.(gobot.Connection); ok { return conn } - log.Printf("%s has no gobot connection\n", d.name) + log.Printf("%s has no gobot connection\n", d.driverCfg.name) return nil } // Start initializes the gpio device. -func (d *Driver) Start() error { +func (d *driver) Start() error { d.mutex.Lock() defer d.mutex.Unlock() @@ -121,7 +160,7 @@ func (d *Driver) Start() error { } // Halt halts the gpio device. -func (d *Driver) Halt() error { +func (d *driver) Halt() error { d.mutex.Lock() defer d.mutex.Unlock() @@ -129,3 +168,57 @@ func (d *Driver) Halt() error { return d.beforeHalt() } + +// digitalRead is a helper function with check that the connection implements DigitalReader +func (d *driver) digitalRead(pin string) (int, error) { + if reader, ok := d.connection.(DigitalReader); ok { + return reader.DigitalRead(pin) + } + + return 0, ErrDigitalReadUnsupported +} + +// digitalWrite is a helper function with check that the connection implements DigitalWriter +func (d *driver) digitalWrite(pin string, val byte) error { + if writer, ok := d.connection.(DigitalWriter); ok { + return writer.DigitalWrite(pin, val) + } + + return ErrDigitalWriteUnsupported +} + +// pwmWrite is a helper function with check that the connection implements PwmWriter +func (d *driver) pwmWrite(pin string, level byte) error { + if writer, ok := d.connection.(PwmWriter); ok { + return writer.PwmWrite(pin, level) + } + + return ErrPwmWriteUnsupported +} + +// servoWrite is a helper function with check that the connection implements ServoWriter +func (d *driver) servoWrite(pin string, level byte) error { + if writer, ok := d.connection.(ServoWriter); ok { + return writer.ServoWrite(pin, level) + } + + return ErrServoWriteUnsupported +} + +func (o nameOption) String() string { + return "name option for digital drivers" +} + +func (o pinOption) String() string { + return "pin option for digital drivers" +} + +// apply change the name in the configuration. +func (o nameOption) apply(c *configuration) { + c.name = string(o) +} + +// apply change the pins list of the configuration. +func (o pinOption) apply(c *configuration) { + c.pin = string(o) +} diff --git a/drivers/gpio/gpio_driver_test.go b/drivers/gpio/gpio_driver_test.go index 753c1fd55..624e04ace 100644 --- a/drivers/gpio/gpio_driver_test.go +++ b/drivers/gpio/gpio_driver_test.go @@ -10,15 +10,15 @@ import ( "gobot.io/x/gobot/v2" ) -var _ gobot.Driver = (*Driver)(nil) +var _ gobot.Driver = (*driver)(nil) -func initTestDriverWithStubbedAdaptor() (*Driver, *gpioTestAdaptor) { +func initTestDriverWithStubbedAdaptor() (*driver, *gpioTestAdaptor) { a := newGpioTestAdaptor() - d := NewDriver(a, "GPIO_BASIC") + d := newDriver(a, "GPIO_BASIC") return d, a } -func initTestDriver() *Driver { +func initTestDriver() *driver { d, _ := initTestDriverWithStubbedAdaptor() return d } @@ -27,10 +27,10 @@ func TestNewDriver(t *testing.T) { // arrange a := newGpioTestAdaptor() // act - d := NewDriver(a, "GPIO_BASIC") + d := newDriver(a, "GPIO_BASIC") // assert - assert.IsType(t, &Driver{}, d) - assert.Contains(t, d.name, "GPIO_BASIC") + assert.IsType(t, &driver{}, d) + assert.Contains(t, d.driverCfg.name, "GPIO_BASIC") assert.Equal(t, a, d.connection) require.NoError(t, d.afterStart()) require.NoError(t, d.beforeHalt()) @@ -38,13 +38,24 @@ func TestNewDriver(t *testing.T) { assert.NotNil(t, d.mutex) } -func TestSetName(t *testing.T) { +func Test_applyWithName(t *testing.T) { // arrange - d := initTestDriver() + const name = "mybot" + cfg := configuration{name: "oldname"} + // act + WithName(name).apply(&cfg) + // assert + assert.Equal(t, name, cfg.name) +} + +func Test_applywithPin(t *testing.T) { + // arrange + const pin = "36" + cfg := configuration{pin: "oldpin"} // act - d.SetName("TESTME") + withPin(pin).apply(&cfg) // assert - assert.Equal(t, "TESTME", d.Name()) + assert.Equal(t, pin, cfg.pin) } func TestConnection(t *testing.T) { diff --git a/drivers/gpio/grove_drivers.go b/drivers/gpio/grove_drivers.go index 017fa7338..d5da86f6f 100644 --- a/drivers/gpio/grove_drivers.go +++ b/drivers/gpio/grove_drivers.go @@ -1,9 +1,5 @@ package gpio -import ( - "time" -) - // GroveRelayDriver represents a Relay with a Grove connector type GroveRelayDriver struct { *RelayDriver @@ -11,11 +7,17 @@ type GroveRelayDriver struct { // NewGroveRelayDriver return a new GroveRelayDriver given a DigitalWriter and pin. // +// Supported options: +// +// "WithName" +// // Adds the following API Commands: // // "Toggle" - See RelayDriver.Toggle // "On" - See RelayDriver.On // "Off" - See RelayDriver.Off +// +// Deprecated: Please use [gpio.NewRelayDriver] instead. Development will be discontinued. func NewGroveRelayDriver(a DigitalWriter, pin string) *GroveRelayDriver { return &GroveRelayDriver{ RelayDriver: NewRelayDriver(a, pin), @@ -27,7 +29,11 @@ type GroveLedDriver struct { *LedDriver } -// NewGroveLedDriver return a new GroveLedDriver given a DigitalWriter and pin. +// NewGroveLedDriver return a new driver for Grove Led given a DigitalWriter and pin. +// +// Supported options: +// +// "WithName" // // Adds the following API Commands: // @@ -35,40 +41,49 @@ type GroveLedDriver struct { // "Toggle" - See LedDriver.Toggle // "On" - See LedDriver.On // "Off" - See LedDriver.Off +// +// Deprecated: Please use [gpio.NewLedDriver] instead. Development will be discontinued. func NewGroveLedDriver(a DigitalWriter, pin string) *GroveLedDriver { return &GroveLedDriver{ LedDriver: NewLedDriver(a, pin), } } -// GroveBuzzerDriver represents a buzzer -// with a Grove connector +// GroveBuzzerDriver represents a buzzer with a Grove connector type GroveBuzzerDriver struct { *BuzzerDriver } -// NewGroveBuzzerDriver return a new GroveBuzzerDriver given a DigitalWriter and pin. -func NewGroveBuzzerDriver(a DigitalWriter, pin string) *GroveBuzzerDriver { +// NewGroveBuzzerDriver return a new driver for Grove buzzer given a DigitalWriter and pin. +// +// Supported options: +// +// "WithName" +// +// Deprecated: Please use [gpio.NewBuzzerDriver] instead. Development will be discontinued. +func NewGroveBuzzerDriver(a DigitalWriter, pin string, opts ...interface{}) *GroveBuzzerDriver { return &GroveBuzzerDriver{ - BuzzerDriver: NewBuzzerDriver(a, pin), + BuzzerDriver: NewBuzzerDriver(a, pin, opts...), } } -// GroveButtonDriver represents a button sensor -// with a Grove connector +// GroveButtonDriver represents a button sensor with a Grove connector type GroveButtonDriver struct { *ButtonDriver } -// NewGroveButtonDriver returns a new GroveButtonDriver with a polling interval of -// 10 Milliseconds given a DigitalReader and pin. +// NewGroveButtonDriver returns a new driver for Grove button with a polling interval of 10 milliseconds given +// a DigitalReader and pin. // -// Optionally accepts: +// Supported options: // -// time.Duration: Interval at which the ButtonDriver is polled for new information -func NewGroveButtonDriver(a DigitalReader, pin string, v ...time.Duration) *GroveButtonDriver { +// "WithName" +// "WithButtonPollInterval" +// +// Deprecated: Please use [gpio.NewButtonDriver] instead. Development will be discontinued. +func NewGroveButtonDriver(a DigitalReader, pin string, opts ...interface{}) *GroveButtonDriver { return &GroveButtonDriver{ - ButtonDriver: NewButtonDriver(a, pin, v...), + ButtonDriver: NewButtonDriver(a, pin, opts...), } } @@ -78,32 +93,37 @@ type GroveTouchDriver struct { *ButtonDriver } -// NewGroveTouchDriver returns a new GroveTouchDriver with a polling interval of -// 10 Milliseconds given a DigitalReader and pin. +// NewGroveTouchDriver returns a new driver for Grove touch sensor with a polling interval of 10 milliseconds given +// a DigitalReader and pin. +// +// Supported options: // -// Optionally accepts: +// "WithName" +// "WithButtonPollInterval" // -// time.Duration: Interval at which the ButtonDriver is polled for new information -func NewGroveTouchDriver(a DigitalReader, pin string, v ...time.Duration) *GroveTouchDriver { +// Deprecated: Please use [gpio.NewButtonDriver] instead. Development will be discontinued. +func NewGroveTouchDriver(a DigitalReader, pin string, opts ...interface{}) *GroveTouchDriver { return &GroveTouchDriver{ - ButtonDriver: NewButtonDriver(a, pin, v...), + ButtonDriver: NewButtonDriver(a, pin, opts...), } } -// GroveMagneticSwitchDriver represent a magnetic -// switch sensor with a Grove connector +// GroveMagneticSwitchDriver represent a magnetic switch sensor with a Grove connector type GroveMagneticSwitchDriver struct { *ButtonDriver } -// NewGroveMagneticSwitchDriver returns a new GroveMagneticSwitchDriver with a polling interval of -// 10 Milliseconds given a DigitalReader, name and pin. +// NewGroveMagneticSwitchDriver returns a new driver for Grove magnetic switch sensor with a polling interval of +// 10 milliseconds given a DigitalReader, name and pin. +// +// Supported options: // -// Optionally accepts: +// "WithName" +// "WithButtonPollInterval" // -// time.Duration: Interval at which the ButtonDriver is polled for new information -func NewGroveMagneticSwitchDriver(a DigitalReader, pin string, v ...time.Duration) *GroveMagneticSwitchDriver { +// Deprecated: Please use [gpio.NewButtonDriver] instead. Development will be discontinued. +func NewGroveMagneticSwitchDriver(a DigitalReader, pin string, opts ...interface{}) *GroveMagneticSwitchDriver { return &GroveMagneticSwitchDriver{ - ButtonDriver: NewButtonDriver(a, pin, v...), + ButtonDriver: NewButtonDriver(a, pin, opts...), } } diff --git a/drivers/gpio/grove_drivers_test.go b/drivers/gpio/grove_drivers_test.go index 1606808e2..f705ded4f 100644 --- a/drivers/gpio/grove_drivers_test.go +++ b/drivers/gpio/grove_drivers_test.go @@ -25,38 +25,38 @@ type DriverAndEventer interface { } func TestDriverDefaults(t *testing.T) { - testAdaptor := newGpioTestAdaptor() + a := newGpioTestAdaptor() pin := "456" drivers := []DriverAndPinner{ - NewGroveTouchDriver(testAdaptor, pin), - NewGroveButtonDriver(testAdaptor, pin), - NewGroveBuzzerDriver(testAdaptor, pin), - NewGroveLedDriver(testAdaptor, pin), - NewGroveRelayDriver(testAdaptor, pin), - NewGroveMagneticSwitchDriver(testAdaptor, pin), + NewGroveTouchDriver(a, pin), + NewGroveButtonDriver(a, pin), + NewGroveBuzzerDriver(a, pin), + NewGroveLedDriver(a, pin), + NewGroveRelayDriver(a, pin), + NewGroveMagneticSwitchDriver(a, pin), } for _, driver := range drivers { - assert.Equal(t, testAdaptor, driver.Connection()) + assert.Equal(t, a, driver.Connection()) assert.Equal(t, pin, driver.Pin()) } } func TestDigitalDriverHalt(t *testing.T) { - testAdaptor := newGpioTestAdaptor() + a := newGpioTestAdaptor() pin := "456" drivers := []DriverAndEventer{ - NewGroveTouchDriver(testAdaptor, pin), - NewGroveButtonDriver(testAdaptor, pin), - NewGroveMagneticSwitchDriver(testAdaptor, pin), + NewGroveTouchDriver(a, pin), + NewGroveButtonDriver(a, pin), + NewGroveMagneticSwitchDriver(a, pin), } for _, driver := range drivers { var callCount int32 - testAdaptor.digitalReadFunc = func(string) (int, error) { + a.digitalReadFunc = func(string) (int, error) { atomic.AddInt32(&callCount, 1) return 42, nil } @@ -69,20 +69,21 @@ func TestDigitalDriverHalt(t *testing.T) { 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("DigitalRead was called after driver was halted") + // note: if a reading is already in progress, it will be finished before halt have an impact + if atomic.LoadInt32(&callCount) > lastCallCount+1 { + t.Errorf("DigitalRead was called more than once after driver was halted") } } } func TestDriverPublishesError(t *testing.T) { - testAdaptor := newGpioTestAdaptor() + a := newGpioTestAdaptor() pin := "456" drivers := []DriverAndEventer{ - NewGroveTouchDriver(testAdaptor, pin), - NewGroveButtonDriver(testAdaptor, pin), - NewGroveMagneticSwitchDriver(testAdaptor, pin), + NewGroveTouchDriver(a, pin), + NewGroveButtonDriver(a, pin), + NewGroveMagneticSwitchDriver(a, pin), } for _, driver := range drivers { @@ -91,7 +92,7 @@ func TestDriverPublishesError(t *testing.T) { returnErr := func(string) (int, error) { return 0, errors.New("read error") } - testAdaptor.digitalReadFunc = returnErr + a.digitalReadFunc = returnErr require.NoError(t, driver.Start()) diff --git a/drivers/gpio/hcsr04_driver.go b/drivers/gpio/hcsr04_driver.go index 471c055a4..3ad1e4f4b 100644 --- a/drivers/gpio/hcsr04_driver.go +++ b/drivers/gpio/hcsr04_driver.go @@ -25,12 +25,26 @@ const ( hcsr04PollInputIntervall time.Duration = 10 * time.Microsecond ) +// hcsr04OptionApplier needs to be implemented by each configurable option type +type hcsr04OptionApplier interface { + apply(cfg *hcsr04Configuration) +} + +// hcsr04Configuration contains all changeable attributes of the driver. +type hcsr04Configuration struct { + useEdgePolling bool +} + +// hcsr04UseEdgePollingOption is the type for applying to use discrete edge polling instead pin edge detection +// by "cdev" from gpiod. +type hcsr04UseEdgePollingOption bool + // HCSR04Driver is a driver for ultrasonic range measurement. type HCSR04Driver struct { - *Driver + *driver + hcsr04Cfg *hcsr04Configuration triggerPinID string echoPinID string - useEdgePolling bool // use discrete edge polling instead "cdev" from gpiod measureMutex *sync.Mutex // to ensure that only one measurement is done at a time triggerPin gobot.DigitalPinner echoPin gobot.DigitalPinner @@ -44,16 +58,31 @@ type HCSR04Driver struct { // NewHCSR04Driver creates a new instance of the driver for HC-SR04 (same as SEN-US01). // // Datasheet: https://www.makershop.de/download/HCSR04-datasheet-version-1.pdf -func NewHCSR04Driver(a gobot.Adaptor, triggerPinID string, echoPinID string, useEdgePolling bool) *HCSR04Driver { - h := HCSR04Driver{ - Driver: NewDriver(a, "HCSR04"), - triggerPinID: triggerPinID, - echoPinID: echoPinID, - useEdgePolling: useEdgePolling, - measureMutex: &sync.Mutex{}, +// +// Supported options: +// +// "WithName" +func NewHCSR04Driver(a gobot.Adaptor, triggerPinID, echoPinID string, opts ...interface{}) *HCSR04Driver { + d := HCSR04Driver{ + driver: newDriver(a, "HCSR04"), + hcsr04Cfg: &hcsr04Configuration{}, + triggerPinID: triggerPinID, + echoPinID: echoPinID, + measureMutex: &sync.Mutex{}, + } + + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case hcsr04OptionApplier: + o.apply(d.hcsr04Cfg) + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } } - h.afterStart = func() error { + d.afterStart = func() error { tpin, err := a.(gobot.DigitalPinnerProvider).DigitalPin(triggerPinID) if err != nil { return fmt.Errorf("error on get trigger pin: %v", err) @@ -61,7 +90,7 @@ func NewHCSR04Driver(a gobot.Adaptor, triggerPinID string, echoPinID string, use if err := tpin.ApplyOptions(system.WithPinDirectionOutput(0)); err != nil { return fmt.Errorf("error on apply output for trigger pin: %v", err) } - h.triggerPin = tpin + d.triggerPin = tpin // pins are inputs by default epin, err := a.(gobot.DigitalPinnerProvider).DigitalPin(echoPinID) @@ -69,99 +98,104 @@ func NewHCSR04Driver(a gobot.Adaptor, triggerPinID string, echoPinID string, use return fmt.Errorf("error on get echo pin: %v", err) } - epinOptions := []func(gobot.DigitalPinOptioner) bool{system.WithPinEventOnBothEdges(h.createEventHandler())} - if h.useEdgePolling { - h.pollQuitChan = make(chan struct{}) - epinOptions = append(epinOptions, system.WithPinPollForEdgeDetection(hcsr04PollInputIntervall, h.pollQuitChan)) + epinOptions := []func(gobot.DigitalPinOptioner) bool{system.WithPinEventOnBothEdges(d.createEventHandler())} + if d.hcsr04Cfg.useEdgePolling { + d.pollQuitChan = make(chan struct{}) + epinOptions = append(epinOptions, system.WithPinPollForEdgeDetection(hcsr04PollInputIntervall, d.pollQuitChan)) } if err := epin.ApplyOptions(epinOptions...); err != nil { return fmt.Errorf("error on apply options for echo pin: %v", err) } - h.echoPin = epin + d.echoPin = epin - h.delayMicroSecChan = make(chan int64) + d.delayMicroSecChan = make(chan int64) return nil } - h.beforeHalt = func() error { - if useEdgePolling { - close(h.pollQuitChan) + d.beforeHalt = func() error { + if d.hcsr04Cfg.useEdgePolling { + close(d.pollQuitChan) } - if err := h.stopDistanceMonitor(); err != nil { + if err := d.stopDistanceMonitor(); err != nil { fmt.Printf("no need to stop distance monitoring: %v\n", err) } // note: Unexport() of all pins will be done on adaptor.Finalize() - close(h.delayMicroSecChan) + close(d.delayMicroSecChan) return nil } - return &h + return &d +} + +// WithHCSR04UseEdgePolling use discrete edge polling instead pin edge detection by "cdev" from gpiod. +func WithHCSR04UseEdgePolling() hcsr04OptionApplier { + return hcsr04UseEdgePollingOption(true) } // MeasureDistance retrieves the distance in front of sensor in meters and returns the measure. It is not designed // to work in a fast loop! For this specific usage, use StartDistanceMonitor() associated with Distance() instead. -func (h *HCSR04Driver) MeasureDistance() (float64, error) { - err := h.measureDistance() +func (d *HCSR04Driver) MeasureDistance() (float64, error) { + err := d.measureDistance() if err != nil { return 0, err } - return h.Distance(), nil + return d.Distance(), nil } // Distance returns the last distance measured in meter, it does not trigger a distance measurement -func (h *HCSR04Driver) Distance() float64 { - distMm := h.lastMeasureMicroSec * hcsr04SoundSpeed / 1000 / 2 +func (d *HCSR04Driver) Distance() float64 { + distMm := d.lastMeasureMicroSec * hcsr04SoundSpeed / 1000 / 2 return float64(distMm) / 1000.0 } // StartDistanceMonitor starts continuous measurement. The current value can be read by Distance() -func (h *HCSR04Driver) StartDistanceMonitor() error { +func (d *HCSR04Driver) StartDistanceMonitor() error { // ensure that start and stop can not interfere - h.mutex.Lock() - defer h.mutex.Unlock() + d.mutex.Lock() + defer d.mutex.Unlock() - if h.distanceMonitorStopChan != nil { - return fmt.Errorf("distance monitor already started for '%s'", h.name) + if d.distanceMonitorStopChan != nil { + return fmt.Errorf("distance monitor already started for '%s'", d.driverCfg.name) } - h.distanceMonitorStopChan = make(chan struct{}) - h.distanceMonitorStopWaitGroup = &sync.WaitGroup{} - h.distanceMonitorStopWaitGroup.Add(1) + d.distanceMonitorStopChan = make(chan struct{}) + d.distanceMonitorStopWaitGroup = &sync.WaitGroup{} + d.distanceMonitorStopWaitGroup.Add(1) go func(name string) { - defer h.distanceMonitorStopWaitGroup.Done() + defer d.distanceMonitorStopWaitGroup.Done() for { select { - case <-h.distanceMonitorStopChan: - h.distanceMonitorStopChan = nil + case <-d.distanceMonitorStopChan: + d.distanceMonitorStopChan = nil return default: - if err := h.measureDistance(); err != nil { + if err := d.measureDistance(); err != nil { fmt.Printf("continuous measure distance skipped for '%s': %v\n", name, err) } time.Sleep(hcsr04MonitorUpdate) } } - }(h.name) + }(d.driverCfg.name) return nil } // StopDistanceMonitor stop the monitor process -func (h *HCSR04Driver) StopDistanceMonitor() error { +func (d *HCSR04Driver) StopDistanceMonitor() error { // ensure that start and stop can not interfere - h.mutex.Lock() - defer h.mutex.Unlock() + d.mutex.Lock() + defer d.mutex.Unlock() - return h.stopDistanceMonitor() + return d.stopDistanceMonitor() } -func (h *HCSR04Driver) createEventHandler() func(int, time.Duration, string, uint32, uint32) { +func (d *HCSR04Driver) createEventHandler() func(int, time.Duration, string, uint32, uint32) { var startTimestamp time.Duration return func(offset int, t time.Duration, et string, sn uint32, lsn uint32) { switch et { @@ -173,28 +207,28 @@ func (h *HCSR04Driver) createEventHandler() func(int, time.Duration, string, uin if startTimestamp == 0 { return } - h.delayMicroSecChan <- (t - startTimestamp).Microseconds() + d.delayMicroSecChan <- (t - startTimestamp).Microseconds() startTimestamp = 0 } } } -func (h *HCSR04Driver) stopDistanceMonitor() error { - if h.distanceMonitorStopChan == nil { - return fmt.Errorf("distance monitor is not yet started for '%s'", h.name) +func (d *HCSR04Driver) stopDistanceMonitor() error { + if d.distanceMonitorStopChan == nil { + return fmt.Errorf("distance monitor is not yet started for '%s'", d.driverCfg.name) } - h.distanceMonitorStopChan <- struct{}{} - h.distanceMonitorStopWaitGroup.Wait() + d.distanceMonitorStopChan <- struct{}{} + d.distanceMonitorStopWaitGroup.Wait() return nil } -func (h *HCSR04Driver) measureDistance() error { - h.measureMutex.Lock() - defer h.measureMutex.Unlock() +func (d *HCSR04Driver) measureDistance() error { + d.measureMutex.Lock() + defer d.measureMutex.Unlock() - if err := h.emitTrigger(); err != nil { + if err := d.emitTrigger(); err != nil { return err } @@ -202,17 +236,25 @@ func (h *HCSR04Driver) measureDistance() error { timeout := hcsr04StartTransmitTimeout + hcsr04ReceiveTimeout select { case <-time.After(timeout): - return fmt.Errorf("timeout %s reached while waiting for value with echo pin %s", timeout, h.echoPinID) - case h.lastMeasureMicroSec = <-h.delayMicroSecChan: + return fmt.Errorf("timeout %s reached while waiting for value with echo pin %s", timeout, d.echoPinID) + case d.lastMeasureMicroSec = <-d.delayMicroSecChan: } return nil } -func (h *HCSR04Driver) emitTrigger() error { - if err := h.triggerPin.Write(1); err != nil { +func (d *HCSR04Driver) emitTrigger() error { + if err := d.triggerPin.Write(1); err != nil { return err } time.Sleep(hcsr04EmitTriggerDuration) - return h.triggerPin.Write(0) + return d.triggerPin.Write(0) +} + +func (o hcsr04UseEdgePollingOption) String() string { + return "hcsr04 use edge polling option" +} + +func (o hcsr04UseEdgePollingOption) apply(cfg *hcsr04Configuration) { + cfg.useEdgePolling = bool(o) } diff --git a/drivers/gpio/hcsr04_driver_test.go b/drivers/gpio/hcsr04_driver_test.go index 0d49b5fe7..4c32cae5e 100644 --- a/drivers/gpio/hcsr04_driver_test.go +++ b/drivers/gpio/hcsr04_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/system" ) @@ -17,7 +18,7 @@ func initTestHCSR04DriverWithStubbedAdaptor(triggerPinID string, echoPinID strin a := newGpioTestAdaptor() tpin := a.addDigitalPin(triggerPinID) _ = a.addDigitalPin(echoPinID) - d := NewHCSR04Driver(a, triggerPinID, echoPinID, false) + d := NewHCSR04Driver(a, triggerPinID, echoPinID) if err := d.Start(); err != nil { panic(err) } @@ -34,23 +35,47 @@ func TestNewHCSR04Driver(t *testing.T) { tpin := a.addDigitalPin(triggerPinID) epin := a.addDigitalPin(echoPinID) // act - d := NewHCSR04Driver(a, triggerPinID, echoPinID, false) + d := NewHCSR04Driver(a, triggerPinID, echoPinID) // assert assert.IsType(t, &HCSR04Driver{}, d) - assert.NotNil(t, d.Driver) - assert.True(t, strings.HasPrefix(d.name, "HCSR04")) + // assert: gpio.driver attributes + assert.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "HCSR04")) assert.Equal(t, a, d.connection) require.NoError(t, d.afterStart()) require.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.False(t, d.hcsr04Cfg.useEdgePolling) assert.Equal(t, triggerPinID, d.triggerPinID) assert.Equal(t, echoPinID, d.echoPinID) - assert.False(t, d.useEdgePolling) + assert.NotNil(t, d.measureMutex) assert.Equal(t, tpin, d.triggerPin) assert.Equal(t, epin, d.echoPin) } +func TestNewHCSR04Driver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "count up" + cycReadDur = 30 * time.Millisecond + ) + panicFunc := func() { + NewHCSR04Driver(newGpioTestAdaptor(), "1", "2", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewHCSR04Driver(newGpioTestAdaptor(), "1", "2", WithName(myName), WithHCSR04UseEdgePolling()) + // assert + assert.True(t, d.hcsr04Cfg.useEdgePolling) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + func TestHCSR04MeasureDistance(t *testing.T) { tests := map[string]struct { measureMicroSec int64 diff --git a/drivers/gpio/hd44780_driver.go b/drivers/gpio/hd44780_driver.go index 0c24ca707..69642ff66 100644 --- a/drivers/gpio/hd44780_driver.go +++ b/drivers/gpio/hd44780_driver.go @@ -3,7 +3,6 @@ package gpio import ( "errors" "fmt" - "sync" "time" "gobot.io/x/gobot/v2" @@ -67,10 +66,24 @@ type HD44780DataPin struct { D7 string } +// hd44780OptionApplier needs to be implemented by each configurable option type +type hd44780OptionApplier interface { + apply(cfg *hd44780Configuration) +} + +// hd44780Configuration contains all changeable attributes of the driver +type hd44780Configuration struct { + pinRW string +} + +// hd44780PinRWOption is the type for applying a R/W pin to the configuration +type hd44780PinRWOption string + // HD44780Driver is the gobot driver for the HD44780 LCD controller // Datasheet: https://www.sparkfun.com/datasheets/LCD/HD44780.pdf type HD44780Driver struct { - name string + *driver + hd44780Cfg *hd44780Configuration cols int rows int rowOffsets [4]int @@ -82,9 +95,6 @@ type HD44780Driver struct { displayCtrl int displayFunc int displayMode int - connection gobot.Connection - gobot.Commander - mutex *sync.Mutex // mutex is needed for sequences, like CreateChar(), Write(), Start(), Halt() } // NewHD44780Driver return a new HD44780Driver @@ -95,6 +105,10 @@ type HD44780Driver struct { // pinRS: register select pin // pinEN: clock enable pin // pinDataBits: databit pins +// +// Supported options: +// +// "WithName" func NewHD44780Driver( a gobot.Connection, cols int, @@ -103,73 +117,71 @@ func NewHD44780Driver( pinRS string, pinEN string, pinDataBits HD44780DataPin, + opts ...interface{}, ) *HD44780Driver { - h := &HD44780Driver{ - name: "HD44780Driver", + d := &HD44780Driver{ + driver: newDriver(a, "HD44780"), + hd44780Cfg: &hd44780Configuration{}, cols: cols, rows: rows, busMode: busMode, pinRS: NewDirectPinDriver(a, pinRS), pinEN: NewDirectPinDriver(a, pinEN), - connection: a, - Commander: gobot.NewCommander(), - mutex: &sync.Mutex{}, + } + d.afterStart = d.initialize + + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case hd44780OptionApplier: + o.apply(d.hd44780Cfg) + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } } - if h.busMode == HD44780_4BITMODE { - h.pinDataBits = make([]*DirectPinDriver, 4) - h.pinDataBits[0] = NewDirectPinDriver(a, pinDataBits.D4) - h.pinDataBits[1] = NewDirectPinDriver(a, pinDataBits.D5) - h.pinDataBits[2] = NewDirectPinDriver(a, pinDataBits.D6) - h.pinDataBits[3] = NewDirectPinDriver(a, pinDataBits.D7) + if d.busMode == HD44780_4BITMODE { + d.pinDataBits = make([]*DirectPinDriver, 4) + d.pinDataBits[0] = NewDirectPinDriver(a, pinDataBits.D4) + d.pinDataBits[1] = NewDirectPinDriver(a, pinDataBits.D5) + d.pinDataBits[2] = NewDirectPinDriver(a, pinDataBits.D6) + d.pinDataBits[3] = NewDirectPinDriver(a, pinDataBits.D7) } else { - h.pinDataBits = make([]*DirectPinDriver, 8) - h.pinDataBits[0] = NewDirectPinDriver(a, pinDataBits.D0) - h.pinDataBits[1] = NewDirectPinDriver(a, pinDataBits.D1) - h.pinDataBits[2] = NewDirectPinDriver(a, pinDataBits.D2) - h.pinDataBits[3] = NewDirectPinDriver(a, pinDataBits.D3) - h.pinDataBits[4] = NewDirectPinDriver(a, pinDataBits.D4) - h.pinDataBits[5] = NewDirectPinDriver(a, pinDataBits.D5) - h.pinDataBits[6] = NewDirectPinDriver(a, pinDataBits.D6) - h.pinDataBits[7] = NewDirectPinDriver(a, pinDataBits.D7) - } - - h.rowOffsets[0] = 0x00 - h.rowOffsets[1] = HD44780_2NDLINEOFFSET - h.rowOffsets[2] = 0x00 + cols - h.rowOffsets[3] = HD44780_2NDLINEOFFSET + cols + d.pinDataBits = make([]*DirectPinDriver, 8) + d.pinDataBits[0] = NewDirectPinDriver(a, pinDataBits.D0) + d.pinDataBits[1] = NewDirectPinDriver(a, pinDataBits.D1) + d.pinDataBits[2] = NewDirectPinDriver(a, pinDataBits.D2) + d.pinDataBits[3] = NewDirectPinDriver(a, pinDataBits.D3) + d.pinDataBits[4] = NewDirectPinDriver(a, pinDataBits.D4) + d.pinDataBits[5] = NewDirectPinDriver(a, pinDataBits.D5) + d.pinDataBits[6] = NewDirectPinDriver(a, pinDataBits.D6) + d.pinDataBits[7] = NewDirectPinDriver(a, pinDataBits.D7) + } - /* TODO : Add commands */ + if d.hd44780Cfg.pinRW != "" { + d.pinRW = NewDirectPinDriver(d.connection, d.hd44780Cfg.pinRW) + } - return h -} + d.rowOffsets[0] = 0x00 + d.rowOffsets[1] = HD44780_2NDLINEOFFSET + d.rowOffsets[2] = 0x00 + cols + d.rowOffsets[3] = HD44780_2NDLINEOFFSET + cols -// SetRWPin initializes the RW pin -func (h *HD44780Driver) SetRWPin(pinRW string) { - h.mutex.Lock() - defer h.mutex.Unlock() + /* TODO : Add commands */ - h.pinRW = NewDirectPinDriver(h.connection, pinRW) + return d } -// Name returns the HD44780Driver name -func (h *HD44780Driver) Name() string { return h.name } - -// SetName sets the HD44780Driver name -func (h *HD44780Driver) SetName(n string) { h.name = n } - -// Connection returns the HD44780Driver Connection -func (h *HD44780Driver) Connection() gobot.Connection { - return h.connection +// WithHD44780RWPin sets the RW pin for next initializing. +func WithHD44780RWPin(pin string) hd44780OptionApplier { + return hd44780PinRWOption(pin) } -// Start initializes the HD44780 LCD controller +// initialize initializes the HD44780 LCD controller // refer to page 45/46 of Hitachi HD44780 datasheet -func (h *HD44780Driver) Start() error { - h.mutex.Lock() - defer h.mutex.Unlock() - - for _, bitPin := range h.pinDataBits { +func (d *HD44780Driver) initialize() error { + for _, bitPin := range d.pinDataBits { if bitPin.Pin() == "" { return errors.New("Initialization error") } @@ -177,71 +189,71 @@ func (h *HD44780Driver) Start() error { time.Sleep(50 * time.Millisecond) - if err := h.activateWriteMode(); err != nil { + if err := d.activateWriteMode(); err != nil { return err } // for initialization refer to documentation, page 45 and 46 - if h.busMode == HD44780_4BITMODE { - if err := h.writeDataPins(0x03); err != nil { + if d.busMode == HD44780_4BITMODE { + if err := d.writeDataPins(0x03); err != nil { return err } time.Sleep(5 * time.Millisecond) - if err := h.writeDataPins(0x03); err != nil { + if err := d.writeDataPins(0x03); err != nil { return err } time.Sleep(100 * time.Microsecond) - if err := h.writeDataPins(0x03); err != nil { + if err := d.writeDataPins(0x03); err != nil { return err } // no additional delay is necessary now - if err := h.writeDataPins(0x02); err != nil { + if err := d.writeDataPins(0x02); err != nil { return err } } else { - if err := h.sendCommand(0x30); err != nil { + if err := d.sendCommand(0x30); err != nil { return err } time.Sleep(5 * time.Millisecond) - if err := h.sendCommand(0x30); err != nil { + if err := d.sendCommand(0x30); err != nil { return err } time.Sleep(100 * time.Microsecond) - if err := h.sendCommand(0x30); err != nil { + if err := d.sendCommand(0x30); err != nil { return err } // no additional delay is necessary now } - if h.busMode == HD44780_4BITMODE { - h.displayFunc |= HD44780_4BITBUS + if d.busMode == HD44780_4BITMODE { + d.displayFunc |= HD44780_4BITBUS } else { - h.displayFunc |= HD44780_8BITBUS + d.displayFunc |= HD44780_8BITBUS } - if h.rows > 1 { - h.displayFunc |= HD44780_2LINE + if d.rows > 1 { + d.displayFunc |= HD44780_2LINE } else { - h.displayFunc |= HD44780_1LINE + d.displayFunc |= HD44780_1LINE } - h.displayFunc |= HD44780_5x8DOTS - h.displayCtrl = HD44780_DISPLAYON | HD44780_BLINKOFF | HD44780_CURSOROFF - h.displayMode = HD44780_ENTRYLEFT | HD44780_ENTRYSHIFTDECREMENT + d.displayFunc |= HD44780_5x8DOTS + d.displayCtrl = HD44780_DISPLAYON | HD44780_BLINKOFF | HD44780_CURSOROFF + d.displayMode = HD44780_ENTRYLEFT | HD44780_ENTRYSHIFTDECREMENT - if err := h.sendCommand(HD44780_FUNCTIONSET | h.displayFunc); err != nil { + if err := d.sendCommand(HD44780_FUNCTIONSET | d.displayFunc); err != nil { return err } - if err := h.sendCommand(HD44780_DISPLAYCONTROL | h.displayCtrl); err != nil { + if err := d.sendCommand(HD44780_DISPLAYCONTROL | d.displayCtrl); err != nil { return err } - if err := h.clear(); err != nil { + if err := d.clear(); err != nil { return err } - if err := h.sendCommand(HD44780_ENTRYMODESET | h.displayMode); err != nil { + if err := d.sendCommand(HD44780_ENTRYMODESET | d.displayMode); err != nil { return err } @@ -249,36 +261,26 @@ func (h *HD44780Driver) Start() error { return nil } -// Halt implements the Driver interface -func (h *HD44780Driver) Halt() error { - // mutex: bad characters and device locking can be prevented - // if the last action is finished before return - h.mutex.Lock() - defer h.mutex.Unlock() - - return nil -} - // Write output text to the display -func (h *HD44780Driver) Write(message string) error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) Write(message string) error { + d.mutex.Lock() + defer d.mutex.Unlock() col := 0 - if (h.displayMode & HD44780_ENTRYLEFT) == 0 { - col = h.cols - 1 + if (d.displayMode & HD44780_ENTRYLEFT) == 0 { + col = d.cols - 1 } row := 0 for _, c := range message { if c == '\n' { row++ - if err := h.setCursor(col, row); err != nil { + if err := d.setCursor(col, row); err != nil { return err } continue } - if err := h.writeChar(int(c)); err != nil { + if err := d.writeChar(int(c)); err != nil { return err } } @@ -287,19 +289,19 @@ func (h *HD44780Driver) Write(message string) error { } // Clear clear the display -func (h *HD44780Driver) Clear() error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) Clear() error { + d.mutex.Lock() + defer d.mutex.Unlock() - return h.clear() + return d.clear() } // Home return cursor to home -func (h *HD44780Driver) Home() error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) Home() error { + d.mutex.Lock() + defer d.mutex.Unlock() - if err := h.sendCommand(HD44780_RETURNHOME); err != nil { + if err := d.sendCommand(HD44780_RETURNHOME); err != nil { return err } time.Sleep(2 * time.Millisecond) @@ -308,120 +310,120 @@ func (h *HD44780Driver) Home() error { } // SetCursor move the cursor to the specified position -func (h *HD44780Driver) SetCursor(col int, row int) error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) SetCursor(col int, row int) error { + d.mutex.Lock() + defer d.mutex.Unlock() - return h.setCursor(col, row) + return d.setCursor(col, row) } // Display turn the display on and off -func (h *HD44780Driver) Display(on bool) error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) Display(on bool) error { + d.mutex.Lock() + defer d.mutex.Unlock() if on { - h.displayCtrl |= HD44780_DISPLAYON + d.displayCtrl |= HD44780_DISPLAYON } else { - h.displayCtrl &= ^HD44780_DISPLAYON + d.displayCtrl &= ^HD44780_DISPLAYON } - return h.sendCommand(HD44780_DISPLAYCONTROL | h.displayCtrl) + return d.sendCommand(HD44780_DISPLAYCONTROL | d.displayCtrl) } // Cursor turn the cursor on and off -func (h *HD44780Driver) Cursor(on bool) error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) Cursor(on bool) error { + d.mutex.Lock() + defer d.mutex.Unlock() if on { - h.displayCtrl |= HD44780_CURSORON + d.displayCtrl |= HD44780_CURSORON } else { - h.displayCtrl &= ^HD44780_CURSORON + d.displayCtrl &= ^HD44780_CURSORON } - return h.sendCommand(HD44780_DISPLAYCONTROL | h.displayCtrl) + return d.sendCommand(HD44780_DISPLAYCONTROL | d.displayCtrl) } // Blink turn the blink on and off -func (h *HD44780Driver) Blink(on bool) error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) Blink(on bool) error { + d.mutex.Lock() + defer d.mutex.Unlock() if on { - h.displayCtrl |= HD44780_BLINKON + d.displayCtrl |= HD44780_BLINKON } else { - h.displayCtrl &= ^HD44780_BLINKON + d.displayCtrl &= ^HD44780_BLINKON } - return h.sendCommand(HD44780_DISPLAYCONTROL | h.displayCtrl) + return d.sendCommand(HD44780_DISPLAYCONTROL | d.displayCtrl) } // ScrollLeft scroll text left -func (h *HD44780Driver) ScrollLeft() error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) ScrollLeft() error { + d.mutex.Lock() + defer d.mutex.Unlock() - return h.sendCommand(HD44780_CURSORSHIFT | HD44780_DISPLAYMOVE | HD44780_MOVELEFT) + return d.sendCommand(HD44780_CURSORSHIFT | HD44780_DISPLAYMOVE | HD44780_MOVELEFT) } // ScrollRight scroll text right -func (h *HD44780Driver) ScrollRight() error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) ScrollRight() error { + d.mutex.Lock() + defer d.mutex.Unlock() - return h.sendCommand(HD44780_CURSORSHIFT | HD44780_DISPLAYMOVE | HD44780_MOVERIGHT) + return d.sendCommand(HD44780_CURSORSHIFT | HD44780_DISPLAYMOVE | HD44780_MOVERIGHT) } // LeftToRight display text from left to right -func (h *HD44780Driver) LeftToRight() error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) LeftToRight() error { + d.mutex.Lock() + defer d.mutex.Unlock() - h.displayMode |= HD44780_ENTRYLEFT - return h.sendCommand(HD44780_ENTRYMODESET | h.displayMode) + d.displayMode |= HD44780_ENTRYLEFT + return d.sendCommand(HD44780_ENTRYMODESET | d.displayMode) } // RightToLeft display text from right to left -func (h *HD44780Driver) RightToLeft() error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) RightToLeft() error { + d.mutex.Lock() + defer d.mutex.Unlock() - h.displayMode &= ^HD44780_ENTRYLEFT - return h.sendCommand(HD44780_ENTRYMODESET | h.displayMode) + d.displayMode &= ^HD44780_ENTRYLEFT + return d.sendCommand(HD44780_ENTRYMODESET | d.displayMode) } // SendCommand send control command -func (h *HD44780Driver) SendCommand(data int) error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) SendCommand(data int) error { + d.mutex.Lock() + defer d.mutex.Unlock() - return h.sendCommand(data) + return d.sendCommand(data) } // WriteChar output a character to the display -func (h *HD44780Driver) WriteChar(data int) error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) WriteChar(data int) error { + d.mutex.Lock() + defer d.mutex.Unlock() - return h.writeChar(data) + return d.writeChar(data) } // CreateChar create custom character -func (h *HD44780Driver) CreateChar(pos int, charMap [8]byte) error { - h.mutex.Lock() - defer h.mutex.Unlock() +func (d *HD44780Driver) CreateChar(pos int, charMap [8]byte) error { + d.mutex.Lock() + defer d.mutex.Unlock() if pos > 7 { return errors.New("can't set a custom character at a position greater than 7") } - if err := h.sendCommand(HD44780_SETCGRAMADDR | (pos << 3)); err != nil { + if err := d.sendCommand(HD44780_SETCGRAMADDR | (pos << 3)); err != nil { return err } for i := range charMap { - if err := h.writeChar(int(charMap[i])); err != nil { + if err := d.writeChar(int(charMap[i])); err != nil { return err } } @@ -429,41 +431,41 @@ func (h *HD44780Driver) CreateChar(pos int, charMap [8]byte) error { return nil } -func (h *HD44780Driver) sendCommand(data int) error { - if err := h.activateWriteMode(); err != nil { +func (d *HD44780Driver) sendCommand(data int) error { + if err := d.activateWriteMode(); err != nil { return err } - if err := h.pinRS.Off(); err != nil { + if err := d.pinRS.Off(); err != nil { return err } - if h.busMode == HD44780_4BITMODE { - if err := h.writeDataPins(data >> 4); err != nil { + if d.busMode == HD44780_4BITMODE { + if err := d.writeDataPins(data >> 4); err != nil { return err } } - return h.writeDataPins(data) + return d.writeDataPins(data) } -func (h *HD44780Driver) writeChar(data int) error { - if err := h.activateWriteMode(); err != nil { +func (d *HD44780Driver) writeChar(data int) error { + if err := d.activateWriteMode(); err != nil { return err } - if err := h.pinRS.On(); err != nil { + if err := d.pinRS.On(); err != nil { return err } - if h.busMode == HD44780_4BITMODE { - if err := h.writeDataPins(data >> 4); err != nil { + if d.busMode == HD44780_4BITMODE { + if err := d.writeDataPins(data >> 4); err != nil { return err } } - return h.writeDataPins(data) + return d.writeDataPins(data) } -func (h *HD44780Driver) clear() error { - if err := h.sendCommand(HD44780_CLEARDISPLAY); err != nil { +func (d *HD44780Driver) clear() error { + if err := d.sendCommand(HD44780_CLEARDISPLAY); err != nil { return err } @@ -474,16 +476,16 @@ func (h *HD44780Driver) clear() error { return nil } -func (h *HD44780Driver) setCursor(col int, row int) error { - if col < 0 || row < 0 || col >= h.cols || row >= h.rows { - return fmt.Errorf("Invalid position value (%d, %d), range (%d, %d)", col, row, h.cols-1, h.rows-1) +func (d *HD44780Driver) setCursor(col int, row int) error { + if col < 0 || row < 0 || col >= d.cols || row >= d.rows { + return fmt.Errorf("Invalid position value (%d, %d), range (%d, %d)", col, row, d.cols-1, d.rows-1) } - return h.sendCommand(HD44780_SETDDRAMADDR | col + h.rowOffsets[row]) + return d.sendCommand(HD44780_SETDDRAMADDR | col + d.rowOffsets[row]) } -func (h *HD44780Driver) writeDataPins(data int) error { - for i, pin := range h.pinDataBits { +func (d *HD44780Driver) writeDataPins(data int) error { + for i, pin := range d.pinDataBits { if ((data >> i) & 0x01) == 0x01 { if err := pin.On(); err != nil { return err @@ -494,17 +496,17 @@ func (h *HD44780Driver) writeDataPins(data int) error { } } } - return h.fallingEdge() + return d.fallingEdge() } // fallingEdge creates falling edge to trigger data transmission -func (h *HD44780Driver) fallingEdge() error { - if err := h.pinEN.On(); err != nil { +func (d *HD44780Driver) fallingEdge() error { + if err := d.pinEN.On(); err != nil { return err } time.Sleep(1 * time.Microsecond) - if err := h.pinEN.Off(); err != nil { + if err := d.pinEN.Off(); err != nil { return err } // fastest write operation at 190kHz mode takes 53 us @@ -513,9 +515,17 @@ func (h *HD44780Driver) fallingEdge() error { return nil } -func (h *HD44780Driver) activateWriteMode() error { - if h.pinRW == nil { +func (d *HD44780Driver) activateWriteMode() error { + if d.pinRW == nil { return nil } - return h.pinRW.Off() + return d.pinRW.Off() +} + +func (o hd44780PinRWOption) String() string { + return "hd44780 RW pin option" +} + +func (o hd44780PinRWOption) apply(cfg *hd44780Configuration) { + cfg.pinRW = string(o) } diff --git a/drivers/gpio/hd44780_driver_test.go b/drivers/gpio/hd44780_driver_test.go index 3fbd13f77..69cbc027a 100644 --- a/drivers/gpio/hd44780_driver_test.go +++ b/drivers/gpio/hd44780_driver_test.go @@ -9,11 +9,11 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*HD44780Driver)(nil) -// --------- HELPERS func initTestHD44780Driver() *HD44780Driver { d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() if err := d.Start(); err != nil { @@ -23,7 +23,7 @@ func initTestHD44780Driver() *HD44780Driver { } func initTestHD44780Driver4BitModeWithStubbedAdaptor() (*HD44780Driver, *gpioTestAdaptor) { - adaptor := newGpioTestAdaptor() + a := newGpioTestAdaptor() dataPins := HD44780DataPin{ D4: "22", D5: "18", @@ -31,11 +31,11 @@ func initTestHD44780Driver4BitModeWithStubbedAdaptor() (*HD44780Driver, *gpioTes D7: "12", } - return NewHD44780Driver(adaptor, 2, 16, HD44780_4BITMODE, "13", "15", dataPins), adaptor + return NewHD44780Driver(a, 2, 16, HD44780_4BITMODE, "13", "15", dataPins), a } func initTestHD44780Driver8BitModeWithStubbedAdaptor() (*HD44780Driver, *gpioTestAdaptor) { - adaptor := newGpioTestAdaptor() + a := newGpioTestAdaptor() dataPins := HD44780DataPin{ D0: "31", D1: "33", @@ -47,41 +47,85 @@ func initTestHD44780Driver8BitModeWithStubbedAdaptor() (*HD44780Driver, *gpioTes D7: "12", } - return NewHD44780Driver(adaptor, 2, 16, HD44780_8BITMODE, "13", "15", dataPins), adaptor + return NewHD44780Driver(a, 2, 16, HD44780_8BITMODE, "13", "15", dataPins), a } -// --------- TESTS -func TestHD44780Driver(t *testing.T) { - d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() - var a interface{} = d - _, ok := a.(*HD44780Driver) - if !ok { - t.Errorf("NewHD44780Driver() should have returned a *HD44780Driver") +func TestNewHD44780Driver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + dataPins := HD44780DataPin{ + D4: "22", + D5: "18", + D6: "16", + D7: "12", } + // act + d := NewHD44780Driver(a, 16, 2, HD44780_4BITMODE, "13", "15", dataPins) + // assert + assert.IsType(t, &HD44780Driver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "HD44780")) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.Equal(t, "", d.hd44780Cfg.pinRW) + assert.Equal(t, 16, d.cols) + assert.Equal(t, 2, d.rows) + assert.Equal(t, HD44780_4BITMODE, d.busMode) + assert.NotNil(t, d.pinRS) + assert.NotNil(t, d.pinEN) + assert.Nil(t, d.pinRW) // will be set optionally + assert.NotNil(t, d.pinRS) + assert.Equal(t, [4]int{0, 64, 16, 80}, d.rowOffsets) + assert.Len(t, d.pinDataBits, 4) + for _, b := range d.pinDataBits { + assert.NotNil(t, b) + } + assert.Equal(t, 0, d.displayCtrl) + assert.Equal(t, 0, d.displayFunc) + assert.Equal(t, 0, d.displayMode) } -func TestHD44780DriverHalt(t *testing.T) { - d := initTestHD44780Driver() - require.NoError(t, d.Halt()) -} - -func TestHD44780DriverDefaultName(t *testing.T) { - d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() - assert.True(t, strings.HasPrefix(d.Name(), "HD44780Driver")) -} - -func TestHD44780DriverSetName(t *testing.T) { - d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() - d.SetName("my driver") - assert.Equal(t, "my driver", d.Name()) +func TestNewHD44780Driver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "LCD output" + pinRW = "3" + ) + dataPins := HD44780DataPin{ + D4: "22", + D5: "18", + D6: "16", + D7: "12", + } + panicFunc := func() { + NewHD44780Driver(newGpioTestAdaptor(), 16, 2, HD44780_4BITMODE, "1", "2", dataPins, WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewHD44780Driver(newGpioTestAdaptor(), 16, 2, HD44780_4BITMODE, "1", "2", dataPins, WithName(myName), + WithHD44780RWPin(pinRW)) + // assert + assert.Equal(t, pinRW, d.hd44780Cfg.pinRW) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } -func TestHD44780DriverStart(t *testing.T) { +func TestHD44780Start(t *testing.T) { + // arrange d, _ := initTestHD44780Driver4BitModeWithStubbedAdaptor() + // act & assert: tests also initialize() require.NoError(t, d.Start()) } -func TestHD44780DriverStartError(t *testing.T) { +func TestHD44780StartError(t *testing.T) { a := newGpioTestAdaptor() var pins HD44780DataPin @@ -110,7 +154,7 @@ func TestHD44780DriverStartError(t *testing.T) { require.EqualError(t, d.Start(), "Initialization error") } -func TestHD44780DriverWrite(t *testing.T) { +func TestHD44780Write(t *testing.T) { var d *HD44780Driver d, _ = initTestHD44780Driver4BitModeWithStubbedAdaptor() @@ -122,7 +166,7 @@ func TestHD44780DriverWrite(t *testing.T) { require.NoError(t, d.Write("hello gobot")) } -func TestHD44780DriverWriteError(t *testing.T) { +func TestHD44780WriteError(t *testing.T) { var d *HD44780Driver var a *gpioTestAdaptor @@ -141,22 +185,22 @@ func TestHD44780DriverWriteError(t *testing.T) { require.EqualError(t, d.Write("hello gobot"), "write error") } -func TestHD44780DriverClear(t *testing.T) { +func TestHD44780Clear(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.Clear()) } -func TestHD44780DriverHome(t *testing.T) { +func TestHD44780Home(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.Home()) } -func TestHD44780DriverSetCursor(t *testing.T) { +func TestHD44780SetCursor(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.SetCursor(0, 3)) } -func TestHD44780DriverSetCursorInvalid(t *testing.T) { +func TestHD44780SetCursorInvalid(t *testing.T) { d := initTestHD44780Driver() require.EqualError(t, d.SetCursor(-1, 3), "Invalid position value (-1, 3), range (1, 15)") @@ -165,73 +209,73 @@ func TestHD44780DriverSetCursorInvalid(t *testing.T) { require.EqualError(t, d.SetCursor(0, 16), "Invalid position value (0, 16), range (1, 15)") } -func TestHD44780DriverDisplayOn(t *testing.T) { +func TestHD44780DisplayOn(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.Display(true)) } -func TestHD44780DriverDisplayOff(t *testing.T) { +func TestHD44780DisplayOff(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.Display(false)) } -func TestHD44780DriverCursorOn(t *testing.T) { +func TestHD44780CursorOn(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.Cursor(true)) } -func TestHD44780DriverCursorOff(t *testing.T) { +func TestHD44780CursorOff(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.Cursor(false)) } -func TestHD44780DriverBlinkOn(t *testing.T) { +func TestHD44780BlinkOn(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.Blink(true)) } -func TestHD44780DriverBlinkOff(t *testing.T) { +func TestHD44780BlinkOff(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.Blink(false)) } -func TestHD44780DriverScrollLeft(t *testing.T) { +func TestHD44780ScrollLeft(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.ScrollLeft()) } -func TestHD44780DriverScrollRight(t *testing.T) { +func TestHD44780ScrollRight(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.ScrollRight()) } -func TestHD44780DriverLeftToRight(t *testing.T) { +func TestHD44780LeftToRight(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.LeftToRight()) } -func TestHD44780DriverRightToLeft(t *testing.T) { +func TestHD44780RightToLeft(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.RightToLeft()) } -func TestHD44780DriverSendCommand(t *testing.T) { +func TestHD44780SendCommand(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.SendCommand(0x33)) } -func TestHD44780DriverWriteChar(t *testing.T) { +func TestHD44780WriteChar(t *testing.T) { d := initTestHD44780Driver() require.NoError(t, d.WriteChar(0x41)) } -func TestHD44780DriverCreateChar(t *testing.T) { +func TestHD44780CreateChar(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} require.NoError(t, d.CreateChar(0, charMap)) } -func TestHD44780DriverCreateCharError(t *testing.T) { +func TestHD44780CreateCharError(t *testing.T) { d := initTestHD44780Driver() charMap := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} require.EqualError(t, d.CreateChar(8, charMap), "can't set a custom character at a position greater than 7") diff --git a/drivers/gpio/led_driver.go b/drivers/gpio/led_driver.go index c69121424..94b4216c8 100644 --- a/drivers/gpio/led_driver.go +++ b/drivers/gpio/led_driver.go @@ -1,35 +1,31 @@ package gpio import ( - "log" - "gobot.io/x/gobot/v2" ) // LedDriver represents a digital Led type LedDriver struct { - pin string - name string - connection DigitalWriter - high bool - gobot.Commander + *driver + high bool } // NewLedDriver return a new LedDriver given a DigitalWriter and pin. // +// Supported options: +// +// "WithName" +// // Adds the following API Commands: // // "Brightness" - See LedDriver.Brightness // "Toggle" - See LedDriver.Toggle // "On" - See LedDriver.On // "Off" - See LedDriver.Off -func NewLedDriver(a DigitalWriter, pin string) *LedDriver { +func NewLedDriver(a DigitalWriter, pin string, opts ...interface{}) *LedDriver { + //nolint:forcetypeassert // no error return value, so there is no better way d := &LedDriver{ - name: gobot.DefaultName("LED"), - pin: pin, - connection: a, - high: false, - Commander: gobot.NewCommander(), + driver: newDriver(a.(gobot.Connection), "LED", append(opts, withPin(pin))...), } d.AddCommand("Brightness", func(params map[string]interface{}) interface{} { @@ -52,31 +48,6 @@ func NewLedDriver(a DigitalWriter, pin string) *LedDriver { return d } -// Start implements the Driver interface -func (d *LedDriver) Start() error { return nil } - -// Halt implements the Driver interface -func (d *LedDriver) Halt() error { return nil } - -// Name returns the LedDrivers name -func (d *LedDriver) Name() string { return d.name } - -// SetName sets the LedDrivers name -func (d *LedDriver) SetName(n string) { d.name = n } - -// Pin returns the LedDrivers name -func (d *LedDriver) Pin() string { return d.pin } - -// Connection returns the LedDrivers Connection -func (d *LedDriver) Connection() gobot.Connection { - if conn, ok := d.connection.(gobot.Connection); ok { - return conn - } - - log.Printf("%s has no gobot connection\n", d.name) - return nil -} - // State return true if the led is On and false if the led is Off func (d *LedDriver) State() bool { return d.high @@ -84,7 +55,7 @@ func (d *LedDriver) State() bool { // On sets the led to a high state. func (d *LedDriver) On() error { - if err := d.connection.DigitalWrite(d.Pin(), 1); err != nil { + if err := d.digitalWrite(d.driverCfg.pin, 1); err != nil { return err } d.high = true @@ -93,7 +64,7 @@ func (d *LedDriver) On() error { // Off sets the led to a low state. func (d *LedDriver) Off() error { - if err := d.connection.DigitalWrite(d.Pin(), 0); err != nil { + if err := d.digitalWrite(d.driverCfg.pin, 0); err != nil { return err } d.high = false @@ -110,8 +81,5 @@ func (d *LedDriver) Toggle() error { // Brightness sets the led to the specified level of brightness func (d *LedDriver) Brightness(level byte) error { - if writer, ok := d.connection.(PwmWriter); ok { - return writer.PwmWrite(d.Pin(), level) - } - return ErrPwmWriteUnsupported + return d.pwmWrite(d.driverCfg.pin, level) } diff --git a/drivers/gpio/led_driver_test.go b/drivers/gpio/led_driver_test.go index 56bda0efa..9c31b4b74 100644 --- a/drivers/gpio/led_driver_test.go +++ b/drivers/gpio/led_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*LedDriver)(nil) @@ -25,14 +26,49 @@ func initTestLedDriver() *LedDriver { return NewLedDriver(a, "1") } -func TestLedDriver(t *testing.T) { +func TestNewLedDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewLedDriver(a, "10") + // assert + assert.IsType(t, &LedDriver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "LED")) + assert.Equal(t, "10", d.driverCfg.pin) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.False(t, d.high) +} + +func TestNewLedDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "back light" + ) + panicFunc := func() { + NewLedDriver(newGpioTestAdaptor(), "1", WithName("crazy"), aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewLedDriver(newGpioTestAdaptor(), "1", WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + +func TestLed_Commands(t *testing.T) { var err interface{} a := newGpioTestAdaptor() d := NewLedDriver(a, "1") - assert.Equal(t, "1", d.Pin()) - assert.NotNil(t, d.Connection()) - a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } @@ -53,26 +89,16 @@ func TestLedDriver(t *testing.T) { require.EqualError(t, err.(error), "pwm error") } -func TestLedDriverStart(t *testing.T) { +func TestLedToggle(t *testing.T) { d := initTestLedDriver() - require.NoError(t, d.Start()) -} - -func TestLedDriverHalt(t *testing.T) { - d := initTestLedDriver() - require.NoError(t, d.Halt()) -} - -func TestLedDriverToggle(t *testing.T) { - d := initTestLedDriver() - _ = d.Off() - _ = d.Toggle() + require.NoError(t, d.Off()) + require.NoError(t, d.Toggle()) assert.True(t, d.State()) - _ = d.Toggle() + require.NoError(t, d.Toggle()) assert.False(t, d.State()) } -func TestLedDriverBrightness(t *testing.T) { +func TestLedBrightness(t *testing.T) { a := newGpioTestAdaptor() d := NewLedDriver(a, "1") a.pwmWriteFunc = func(string, byte) error { @@ -80,16 +106,3 @@ func TestLedDriverBrightness(t *testing.T) { } require.EqualError(t, d.Brightness(150), "pwm error") } - -func TestLEDDriverDefaultName(t *testing.T) { - a := newGpioTestAdaptor() - d := NewLedDriver(a, "1") - assert.True(t, strings.HasPrefix(d.Name(), "LED")) -} - -func TestLEDDriverSetName(t *testing.T) { - a := newGpioTestAdaptor() - d := NewLedDriver(a, "1") - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) -} diff --git a/drivers/gpio/max7219_driver.go b/drivers/gpio/max7219_driver.go index c4bb713c6..d73543537 100644 --- a/drivers/gpio/max7219_driver.go +++ b/drivers/gpio/max7219_driver.go @@ -28,89 +28,51 @@ const ( // // Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf type MAX7219Driver struct { - pinClock *DirectPinDriver - pinData *DirectPinDriver - pinCS *DirectPinDriver - name string - count uint - connection gobot.Connection - gobot.Commander + *driver + pinClock *DirectPinDriver + pinData *DirectPinDriver + pinCS *DirectPinDriver + count uint } // NewMAX7219Driver return a new MAX7219Driver given a gobot.Connection, pins and how many chips are chained -func NewMAX7219Driver(a gobot.Connection, clockPin string, dataPin string, csPin string, count uint) *MAX7219Driver { - t := &MAX7219Driver{ - name: gobot.DefaultName("MAX7219Driver"), - pinClock: NewDirectPinDriver(a, clockPin), - pinData: NewDirectPinDriver(a, dataPin), - pinCS: NewDirectPinDriver(a, csPin), - count: count, - connection: a, - Commander: gobot.NewCommander(), - } +// +// Supported options: +// +// "WithName" +func NewMAX7219Driver( + a gobot.Connection, + clockPin, dataPin, csPin string, + count uint, + opts ...interface{}, +) *MAX7219Driver { + d := &MAX7219Driver{ + driver: newDriver(a, "MAX7219", opts...), + pinClock: NewDirectPinDriver(a, clockPin), + pinData: NewDirectPinDriver(a, dataPin), + pinCS: NewDirectPinDriver(a, csPin), + count: count, + } + d.afterStart = d.initialize /* TODO : Add commands */ - return t -} - -// Start initializes the max7219, it uses a SPI-like communication protocol -func (a *MAX7219Driver) Start() error { - if err := a.pinData.On(); err != nil { - return err - } - if err := a.pinClock.On(); err != nil { - return err - } - if err := a.pinCS.On(); err != nil { - return err - } - - if err := a.All(MAX7219ScanLimit, 0x07); err != nil { - return err - } - if err := a.All(MAX7219DecodeMode, 0x00); err != nil { - return err - } - if err := a.All(MAX7219Shutdown, 0x01); err != nil { - return err - } - if err := a.All(MAX7219DisplayTest, 0x00); err != nil { - return err - } - if err := a.ClearAll(); err != nil { - return err - } - return a.All(MAX7219Intensity, 0x0f) -} - -// Halt implements the Driver interface -func (a *MAX7219Driver) Halt() error { return nil } - -// Name returns the MAX7219Drivers name -func (a *MAX7219Driver) Name() string { return a.name } - -// SetName sets the MAX7219Drivers name -func (a *MAX7219Driver) SetName(n string) { a.name = n } - -// Connection returns the MAX7219Driver Connection -func (a *MAX7219Driver) Connection() gobot.Connection { - return a.connection + return d } // SetIntensity changes the intensity (from 1 to 7) of the display -func (a *MAX7219Driver) SetIntensity(level byte) error { +func (d *MAX7219Driver) SetIntensity(level byte) error { if level > 15 { level = 15 } - return a.All(MAX7219Intensity, level) + return d.All(MAX7219Intensity, level) } // ClearAll turns off all LEDs of all modules -func (a *MAX7219Driver) ClearAll() error { +func (d *MAX7219Driver) ClearAll() error { var err error for i := 1; i <= 8; i++ { - if e := a.All(byte(i), 0); e != nil { + if e := d.All(byte(i), 0); e != nil { err = multierror.Append(err, e) } } @@ -119,10 +81,10 @@ func (a *MAX7219Driver) ClearAll() error { } // ClearOne turns off all LEDs of the given module -func (a *MAX7219Driver) ClearOne(which uint) error { +func (d *MAX7219Driver) ClearOne(which uint) error { var err error for i := 1; i <= 8; i++ { - if e := a.One(which, byte(i), 0); e != nil { + if e := d.One(which, byte(i), 0); e != nil { err = multierror.Append(err, e) } } @@ -130,71 +92,101 @@ func (a *MAX7219Driver) ClearOne(which uint) error { return err } -// send writes data on the module -func (a *MAX7219Driver) send(data byte) error { - var i byte - for i = 8; i > 0; i-- { - mask := byte(0x01 << (i - 1)) - - if err := a.pinClock.Off(); err != nil { - return err - } - if data&mask > 0 { - if err := a.pinData.On(); err != nil { - return err - } - } else { - if err := a.pinData.Off(); err != nil { - return err - } - } - if err := a.pinClock.On(); err != nil { - return err - } - } - - return nil -} - // All sends the same data to all the modules -func (a *MAX7219Driver) All(address byte, data byte) error { - if err := a.pinCS.Off(); err != nil { +func (d *MAX7219Driver) All(address byte, data byte) error { + if err := d.pinCS.Off(); err != nil { return err } var c uint - for c = 0; c < a.count; c++ { - if err := a.send(address); err != nil { + for c = 0; c < d.count; c++ { + if err := d.send(address); err != nil { return err } - if err := a.send(data); err != nil { + if err := d.send(data); err != nil { return err } } - return a.pinCS.On() + return d.pinCS.On() } // One sends data to a specific module -func (a *MAX7219Driver) One(which uint, address byte, data byte) error { - if err := a.pinCS.Off(); err != nil { +func (d *MAX7219Driver) One(which uint, address byte, data byte) error { + if err := d.pinCS.Off(); err != nil { return err } var c uint - for c = 0; c < a.count; c++ { + for c = 0; c < d.count; c++ { if c == which { - if err := a.send(address); err != nil { + if err := d.send(address); err != nil { return err } - if err := a.send(data); err != nil { + if err := d.send(data); err != nil { return err } } else { - if err := a.send(0); err != nil { + if err := d.send(0); err != nil { + return err + } + if err := d.send(0); err != nil { + return err + } + } + } + return d.pinCS.On() +} + +// initialize initializes the max7219, it uses a SPI-like communication protocol +func (d *MAX7219Driver) initialize() error { + if err := d.pinData.On(); err != nil { + return err + } + if err := d.pinClock.On(); err != nil { + return err + } + if err := d.pinCS.On(); err != nil { + return err + } + + if err := d.All(MAX7219ScanLimit, 0x07); err != nil { + return err + } + if err := d.All(MAX7219DecodeMode, 0x00); err != nil { + return err + } + if err := d.All(MAX7219Shutdown, 0x01); err != nil { + return err + } + if err := d.All(MAX7219DisplayTest, 0x00); err != nil { + return err + } + if err := d.ClearAll(); err != nil { + return err + } + return d.All(MAX7219Intensity, 0x0f) +} + +// send writes data on the module +func (d *MAX7219Driver) send(data byte) error { + var i byte + for i = 8; i > 0; i-- { + mask := byte(0x01 << (i - 1)) + + if err := d.pinClock.Off(); err != nil { + return err + } + if data&mask > 0 { + if err := d.pinData.On(); err != nil { return err } - if err := a.send(0); err != nil { + } else { + if err := d.pinData.Off(); err != nil { return err } } + if err := d.pinClock.On(); err != nil { + return err + } } - return a.pinCS.On() + + return nil } diff --git a/drivers/gpio/max7219_driver_test.go b/drivers/gpio/max7219_driver_test.go index e668c8952..13afb1d8b 100644 --- a/drivers/gpio/max7219_driver_test.go +++ b/drivers/gpio/max7219_driver_test.go @@ -8,47 +8,65 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*MAX7219Driver)(nil) -// --------- HELPERS func initTestMAX7219Driver() *MAX7219Driver { d, _ := initTestMAX7219DriverWithStubbedAdaptor() return d } func initTestMAX7219DriverWithStubbedAdaptor() (*MAX7219Driver, *gpioTestAdaptor) { - adaptor := newGpioTestAdaptor() - return NewMAX7219Driver(adaptor, "1", "2", "3", 1), adaptor + a := newGpioTestAdaptor() + return NewMAX7219Driver(a, "1", "2", "3", 1), a } -// --------- TESTS -func TestMAX7219Driver(t *testing.T) { - var a interface{} = initTestMAX7219Driver() - _, ok := a.(*MAX7219Driver) - if !ok { - t.Errorf("NewMAX7219Driver() should have returned a *MAX7219Driver") - } -} - -func TestMAX7219DriverStart(t *testing.T) { - d := initTestMAX7219Driver() - require.NoError(t, d.Start()) +func TestNewMAX7219Driver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewMAX7219Driver(a, "1", "2", "3", 4) + // assert + assert.IsType(t, &MAX7219Driver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "MAX7219")) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.NotNil(t, d.pinClock) + assert.NotNil(t, d.pinData) + assert.NotNil(t, d.pinCS) + assert.Equal(t, uint(4), d.count) } -func TestMAX7219DriverHalt(t *testing.T) { - d := initTestMAX7219Driver() - require.NoError(t, d.Halt()) -} - -func TestMAX7219DriverDefaultName(t *testing.T) { - d := initTestMAX7219Driver() - assert.True(t, strings.HasPrefix(d.Name(), "MAX7219Driver")) +func TestNewMAX7219Driver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "light chain 5" + ) + panicFunc := func() { + NewMAX7219Driver(newGpioTestAdaptor(), "1", "2", "3", 4, WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewMAX7219Driver(newGpioTestAdaptor(), "1", "2", "3", 4, WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } -func TestMAX7219DriverSetName(t *testing.T) { +func TestMAX7219Start(t *testing.T) { + // arrange d := initTestMAX7219Driver() - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) + // act & assert: tests also initialize() + require.NoError(t, d.Start()) } diff --git a/drivers/gpio/motor_driver.go b/drivers/gpio/motor_driver.go index 9f6dcfa97..6bc9b34ec 100644 --- a/drivers/gpio/motor_driver.go +++ b/drivers/gpio/motor_driver.go @@ -1,106 +1,134 @@ package gpio import ( - "log" + "fmt" "gobot.io/x/gobot/v2" ) +// motorOptionApplier needs to be implemented by each configurable option type +type motorOptionApplier interface { + apply(cfg *motorConfiguration) +} + +// motorConfiguration contains all changeable attributes of the driver. +type motorConfiguration struct { + modeIsAnalog bool + directionPin string + forwardPin string + backwardPin string +} + +// motorModeIsAnalogOption is the type for applying analog mode to the configuration +type motorModeIsAnalogOption bool + +// motorDirectionPinOption is the type for applying a direction pin to the configuration +type motorDirectionPinOption string + +// motorForwardPinOption is the type for applying a forward pin to the configuration +type motorForwardPinOption string + +// motorBackwardPinOption is the type for applying a backward pin to the configuration +type motorBackwardPinOption string + // MotorDriver Represents a Motor type MotorDriver struct { - name string - connection DigitalWriter - SpeedPin string - SwitchPin string - DirectionPin string - ForwardPin string - BackwardPin string - CurrentState byte - CurrentSpeed byte - CurrentMode string - CurrentDirection string + *driver + motorCfg *motorConfiguration + currentState byte + currentSpeed byte + currentDirection string } -// NewMotorDriver return a new MotorDriver given a DigitalWriter and pin -func NewMotorDriver(a DigitalWriter, speedPin string) *MotorDriver { - return &MotorDriver{ - name: gobot.DefaultName("Motor"), - connection: a, - SpeedPin: speedPin, - CurrentState: 0, - CurrentSpeed: 0, - CurrentMode: "digital", - CurrentDirection: "forward", +// NewMotorDriver return a new MotorDriver given a DigitalWriter and pin. This defaults to digital mode and just switch +// on and off in forward direction. Optional pins can be given, depending on your hardware. So the direction can be +// changed with one pin or by using separated forward and backward pins. +// +// If the given pin supports the PwmWriter the motor can be used/switched to analog mode by writing once to SetSpeed() +// or by calling SetAnalogMode(). The optional pins can be used for direction control. +// +// Supported options: +// +// "WithName" +// "WithMotorAnalog" +// "WithMotorDirectionPin" +// "WithMotorForwardPin" +// "WithMotorBackwardPin" +func NewMotorDriver(a DigitalWriter, speedPin string, opts ...interface{}) *MotorDriver { + //nolint:forcetypeassert // no error return value, so there is no better way + d := &MotorDriver{ + driver: newDriver(a.(gobot.Connection), "Motor", withPin(speedPin)), + motorCfg: &motorConfiguration{}, + currentDirection: "forward", } -} -// Name returns the MotorDrivers name -func (d *MotorDriver) Name() string { return d.name } + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case motorOptionApplier: + o.apply(d.motorCfg) + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } + } -// SetName sets the MotorDrivers name -func (d *MotorDriver) SetName(n string) { d.name = n } + return d +} -// Connection returns the MotorDrivers Connection -func (d *MotorDriver) Connection() gobot.Connection { - if conn, ok := d.connection.(gobot.Connection); ok { - return conn - } +// WithMotorAnalog change the default mode "digital" to analog for the motor. +func WithMotorAnalog() motorOptionApplier { + return motorModeIsAnalogOption(true) +} - log.Printf("%s has no gobot connection\n", d.name) - return nil +// WithMotorDirectionPin introduces a pin for change the direction of the motor. +func WithMotorDirectionPin(pin string) motorOptionApplier { + return motorDirectionPinOption(pin) } -// Start implements the Driver interface -func (d *MotorDriver) Start() error { return nil } +// WithMotorForwardPin introduces a pin for setting the direction to forward. +func WithMotorForwardPin(pin string) motorOptionApplier { + return motorForwardPinOption(pin) +} -// Halt implements the Driver interface -func (d *MotorDriver) Halt() error { return nil } +// WithMotorBackwardPin introduces a pin for setting the direction to backward. +func WithMotorBackwardPin(pin string) motorOptionApplier { + return motorBackwardPinOption(pin) +} -// Off turns the motor off or sets the motor to a 0 speed +// Off turns the motor off or sets the motor to a 0 speed. func (d *MotorDriver) Off() error { - if d.isDigital() { + if d.IsDigital() { return d.changeState(0) } - return d.Speed(0) + return d.SetSpeed(0) } -// On turns the motor on or sets the motor to a maximum speed +// On turns the motor on or sets the motor to a maximum speed. func (d *MotorDriver) On() error { - if d.isDigital() { + if d.IsDigital() { return d.changeState(1) } - if d.CurrentSpeed == 0 { - d.CurrentSpeed = 255 + + if d.currentSpeed == 0 { + d.currentSpeed = 255 } - return d.Speed(d.CurrentSpeed) + return d.SetSpeed(d.currentSpeed) } -// Min sets the motor to the minimum speed -func (d *MotorDriver) Min() error { +// RunMin sets the motor to the minimum speed. +func (d *MotorDriver) RunMin() error { return d.Off() } -// Max sets the motor to the maximum speed -func (d *MotorDriver) Max() error { - return d.Speed(255) -} - -// IsOn returns true if the motor is on -func (d *MotorDriver) IsOn() bool { - if d.isDigital() { - return d.CurrentState == 1 - } - return d.CurrentSpeed > 0 +// RunMax sets the motor to the maximum speed. +func (d *MotorDriver) RunMax() error { + return d.SetSpeed(255) } -// IsOff returns true if the motor is off -func (d *MotorDriver) IsOff() bool { - return !d.IsOn() -} - -// Toggle sets the motor to the opposite of it's current state +// Toggle sets the motor to the opposite of it's current state. func (d *MotorDriver) Toggle() error { if d.IsOn() { return d.Off() @@ -109,51 +137,51 @@ func (d *MotorDriver) Toggle() error { return d.On() } -// Speed sets the speed of the motor -func (d *MotorDriver) Speed(value byte) error { +// SetSpeed change the speed of the motor, without change the direction. +func (d *MotorDriver) SetSpeed(value byte) error { if writer, ok := d.connection.(PwmWriter); ok { - d.CurrentMode = "analog" - d.CurrentSpeed = value - return writer.PwmWrite(d.SpeedPin, value) + WithMotorAnalog().apply(d.motorCfg) + d.currentSpeed = value + return writer.PwmWrite(d.driverCfg.pin, value) } return ErrPwmWriteUnsupported } -// Forward sets the forward pin to the specified speed +// Forward runs the motor forward with the specified speed. func (d *MotorDriver) Forward(speed byte) error { - if err := d.Direction("forward"); err != nil { + if err := d.SetDirection("forward"); err != nil { return err } - if err := d.Speed(speed); err != nil { + if err := d.SetSpeed(speed); err != nil { return err } return nil } -// Backward sets the backward pin to the specified speed +// Backward runs the motor backward with the specified speed. func (d *MotorDriver) Backward(speed byte) error { - if err := d.Direction("backward"); err != nil { + if err := d.SetDirection("backward"); err != nil { return err } - if err := d.Speed(speed); err != nil { + if err := d.SetSpeed(speed); err != nil { return err } return nil } -// Direction sets the direction pin to the specified speed -func (d *MotorDriver) Direction(direction string) error { - d.CurrentDirection = direction - if d.DirectionPin != "" { +// Direction sets the direction pin to the specified direction. +func (d *MotorDriver) SetDirection(direction string) error { + d.currentDirection = direction + if d.motorCfg.directionPin != "" { var level byte if direction == "forward" { level = 1 } else { level = 0 } - return d.connection.DigitalWrite(d.DirectionPin, level) + return d.digitalWrite(d.motorCfg.directionPin, level) } var forwardLevel, backwardLevel byte @@ -169,41 +197,108 @@ func (d *MotorDriver) Direction(direction string) error { backwardLevel = 0 } - if err := d.connection.DigitalWrite(d.ForwardPin, forwardLevel); err != nil { - return err + if d.motorCfg.forwardPin != "" { + if err := d.digitalWrite(d.motorCfg.forwardPin, forwardLevel); err != nil { + return err + } + } + + if d.motorCfg.backwardPin != "" { + return d.digitalWrite(d.motorCfg.backwardPin, backwardLevel) } - return d.connection.DigitalWrite(d.BackwardPin, backwardLevel) + return nil +} + +// IsAnalog returns true if the motor is in analog mode. +func (d *MotorDriver) IsAnalog() bool { + return d.motorCfg.modeIsAnalog +} + +// IsDigital returns true if the motor is in digital mode. +func (d *MotorDriver) IsDigital() bool { + return !d.motorCfg.modeIsAnalog +} + +// IsOn returns true if the motor is on. +func (d *MotorDriver) IsOn() bool { + if d.IsDigital() { + return d.currentState == 1 + } + return d.currentSpeed > 0 +} + +// IsOff returns true if the motor is off. +func (d *MotorDriver) IsOff() bool { + return !d.IsOn() +} + +// Direction returns the current direction ("forward" or "backward") of the motor. +func (d *MotorDriver) Direction() string { + return d.currentDirection } -func (d *MotorDriver) isDigital() bool { - return d.CurrentMode == "digital" +// Speed returns the current speed of the motor. +func (d *MotorDriver) Speed() byte { + return d.currentSpeed } func (d *MotorDriver) changeState(state byte) error { - d.CurrentState = state + d.currentState = state if state == 1 { - d.CurrentSpeed = 255 + d.currentSpeed = 255 } else { - d.CurrentSpeed = 0 + d.currentSpeed = 0 } - if d.ForwardPin == "" { - return d.connection.DigitalWrite(d.SpeedPin, state) + if d.motorCfg.forwardPin == "" { + return d.digitalWrite(d.driverCfg.pin, state) } if state != 1 { - return d.Direction("none") + return d.SetDirection("none") } - if err := d.Direction(d.CurrentDirection); err != nil { + if err := d.SetDirection(d.currentDirection); err != nil { return err } - if d.SpeedPin != "" { - if err := d.Speed(d.CurrentSpeed); err != nil { + if d.driverCfg.pin != "" { + if err := d.SetSpeed(d.currentSpeed); err != nil { return err } } return nil } + +func (o motorModeIsAnalogOption) String() string { + return "motor mode (analog, digital) option" +} + +func (o motorDirectionPinOption) String() string { + return "direction pin option for motors" +} + +func (o motorForwardPinOption) String() string { + return "forward pin option for motors" +} + +func (o motorBackwardPinOption) String() string { + return "backward pin option for motors" +} + +func (o motorModeIsAnalogOption) apply(cfg *motorConfiguration) { + cfg.modeIsAnalog = bool(o) +} + +func (o motorDirectionPinOption) apply(cfg *motorConfiguration) { + cfg.directionPin = string(o) +} + +func (o motorForwardPinOption) apply(cfg *motorConfiguration) { + cfg.forwardPin = string(o) +} + +func (o motorBackwardPinOption) apply(cfg *motorConfiguration) { + cfg.backwardPin = string(o) +} diff --git a/drivers/gpio/motor_driver_test.go b/drivers/gpio/motor_driver_test.go index f8610fb32..3e1a789b1 100644 --- a/drivers/gpio/motor_driver_test.go +++ b/drivers/gpio/motor_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*MotorDriver)(nil) @@ -21,120 +22,180 @@ func TestMotorDriver(t *testing.T) { assert.NotNil(t, d.Connection()) } -func TestMotorDriverStart(t *testing.T) { - d := initTestMotorDriver() - require.NoError(t, d.Start()) -} - -func TestMotorDriverHalt(t *testing.T) { - d := initTestMotorDriver() - require.NoError(t, d.Halt()) -} - -func TestMotorDriverIsOn(t *testing.T) { - d := initTestMotorDriver() - d.CurrentMode = "digital" - d.CurrentState = 1 +func TestNewMotorDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewMotorDriver(a, "10") + // assert + assert.IsType(t, &MotorDriver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "Motor")) + assert.Equal(t, "10", d.driverCfg.pin) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.Equal(t, "", d.motorCfg.directionPin) + assert.Equal(t, "", d.motorCfg.forwardPin) + assert.Equal(t, "", d.motorCfg.backwardPin) + assert.False(t, d.motorCfg.modeIsAnalog) + assert.Equal(t, uint8(0), d.currentState) + assert.Equal(t, uint8(0), d.currentSpeed) + assert.Equal(t, "forward", d.currentDirection) +} + +func TestNewMotorDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "move analog" + ) + panicFunc := func() { + NewMotorDriver(newGpioTestAdaptor(), "1", WithName("crazy"), aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewMotorDriver(newGpioTestAdaptor(), "1", WithName(myName), WithMotorAnalog()) + // assert + assert.True(t, d.motorCfg.modeIsAnalog) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + +func TestMotor_WithMotorDirectionPin(t *testing.T) { + // arrange + const myPin = "8" + cfg := motorConfiguration{directionPin: "old_pin"} + // act + WithMotorDirectionPin(myPin).apply(&cfg) + // assert + assert.Equal(t, myPin, cfg.directionPin) +} + +func TestMotor_WithMotorForwardPin(t *testing.T) { + // arrange + const myPin = "3" + cfg := motorConfiguration{directionPin: "old_pin"} + // act + WithMotorForwardPin(myPin).apply(&cfg) + // assert + assert.Equal(t, myPin, cfg.forwardPin) +} + +func TestMotor_WithMotorBackwardPin(t *testing.T) { + // arrange + const myPin = "6" + cfg := motorConfiguration{directionPin: "old_pin"} + // act + WithMotorBackwardPin(myPin).apply(&cfg) + // assert + assert.Equal(t, myPin, cfg.backwardPin) +} + +func TestMotorIsOn(t *testing.T) { + d := initTestMotorDriver() + d.motorCfg.modeIsAnalog = false + d.currentState = 1 + assert.True(t, d.IsDigital()) assert.True(t, d.IsOn()) - d.CurrentMode = "analog" - d.CurrentSpeed = 100 + d.motorCfg.modeIsAnalog = true + d.currentSpeed = 100 + assert.False(t, d.IsDigital()) assert.True(t, d.IsOn()) } -func TestMotorDriverIsOff(t *testing.T) { +func TestMotorIsOff(t *testing.T) { d := initTestMotorDriver() - _ = d.Off() + require.NoError(t, d.Off()) assert.True(t, d.IsOff()) } -func TestMotorDriverOn(t *testing.T) { +func TestMotorOn(t *testing.T) { d := initTestMotorDriver() - d.CurrentMode = "digital" - _ = d.On() - assert.Equal(t, uint8(1), d.CurrentState) - d.CurrentMode = "analog" - d.CurrentSpeed = 0 - _ = d.On() - assert.Equal(t, uint8(255), d.CurrentSpeed) + d.motorCfg.modeIsAnalog = false + assert.True(t, d.IsDigital()) + require.NoError(t, d.On()) + assert.Equal(t, uint8(1), d.currentState) + d.motorCfg.modeIsAnalog = true + d.currentSpeed = 0 + assert.False(t, d.IsDigital()) + require.NoError(t, d.On()) + assert.Equal(t, uint8(255), d.currentSpeed) } -func TestMotorDriverOff(t *testing.T) { +func TestMotorOff(t *testing.T) { d := initTestMotorDriver() - d.CurrentMode = "digital" - _ = d.Off() - assert.Equal(t, uint8(0), d.CurrentState) - d.CurrentMode = "analog" - d.CurrentSpeed = 100 - _ = d.Off() - assert.Equal(t, uint8(0), d.CurrentSpeed) + d.motorCfg.modeIsAnalog = false + assert.True(t, d.IsDigital()) + require.NoError(t, d.Off()) + assert.Equal(t, uint8(0), d.currentState) + d.motorCfg.modeIsAnalog = true + d.currentSpeed = 100 + assert.False(t, d.IsDigital()) + require.NoError(t, d.Off()) + assert.Equal(t, uint8(0), d.currentSpeed) } -func TestMotorDriverToggle(t *testing.T) { +func TestMotorToggle(t *testing.T) { d := initTestMotorDriver() - _ = d.Off() - _ = d.Toggle() + require.NoError(t, d.Off()) + require.NoError(t, d.Toggle()) assert.True(t, d.IsOn()) - _ = d.Toggle() + require.NoError(t, d.Toggle()) assert.False(t, d.IsOn()) } -func TestMotorDriverMin(t *testing.T) { +func TestMotorRunMin(t *testing.T) { d := initTestMotorDriver() - _ = d.Min() + require.NoError(t, d.RunMin()) } -func TestMotorDriverMax(t *testing.T) { +func TestMotorRunMax(t *testing.T) { d := initTestMotorDriver() - _ = d.Max() + require.NoError(t, d.RunMax()) } -func TestMotorDriverSpeed(t *testing.T) { +func TestMotorSetSpeed(t *testing.T) { d := initTestMotorDriver() - _ = d.Speed(100) + require.NoError(t, d.SetSpeed(100)) } -func TestMotorDriverForward(t *testing.T) { +func TestMotorForward(t *testing.T) { d := initTestMotorDriver() - _ = d.Forward(100) - assert.Equal(t, uint8(100), d.CurrentSpeed) - assert.Equal(t, "forward", d.CurrentDirection) + require.NoError(t, d.Forward(100)) + assert.Equal(t, uint8(100), d.currentSpeed) + assert.Equal(t, "forward", d.currentDirection) } -func TestMotorDriverBackward(t *testing.T) { +func TestMotorBackward(t *testing.T) { d := initTestMotorDriver() - _ = d.Backward(100) - assert.Equal(t, uint8(100), d.CurrentSpeed) - assert.Equal(t, "backward", d.CurrentDirection) + require.NoError(t, d.Backward(100)) + assert.Equal(t, uint8(100), d.currentSpeed) + assert.Equal(t, "backward", d.currentDirection) } -func TestMotorDriverDirection(t *testing.T) { +func TestMotorSetDirection(t *testing.T) { d := initTestMotorDriver() - _ = d.Direction("none") - d.DirectionPin = "2" - _ = d.Direction("forward") - _ = d.Direction("backward") + require.NoError(t, d.SetDirection("none")) + d.motorCfg.directionPin = "2" + require.NoError(t, d.SetDirection("forward")) + require.NoError(t, d.SetDirection("backward")) } -func TestMotorDriverDigital(t *testing.T) { +func TestMotorDigital(t *testing.T) { d := initTestMotorDriver() - d.SpeedPin = "" // Disable speed - d.CurrentMode = "digital" - d.ForwardPin = "2" - d.BackwardPin = "3" + d.driverCfg.pin = "" // Disable speed + d.motorCfg.modeIsAnalog = false + d.motorCfg.forwardPin = "2" + d.motorCfg.backwardPin = "3" - _ = d.On() - assert.Equal(t, uint8(1), d.CurrentState) - _ = d.Off() - assert.Equal(t, uint8(0), d.CurrentState) -} - -func TestMotorDriverDefaultName(t *testing.T) { - d := initTestMotorDriver() - assert.True(t, strings.HasPrefix(d.Name(), "Motor")) -} - -func TestMotorDriverSetName(t *testing.T) { - d := initTestMotorDriver() - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) + require.NoError(t, d.On()) + assert.Equal(t, uint8(1), d.currentState) + require.NoError(t, d.Off()) + assert.Equal(t, uint8(0), d.currentState) } diff --git a/drivers/gpio/pir_motion_driver.go b/drivers/gpio/pir_motion_driver.go index e75ef2b0d..5145a8d8c 100644 --- a/drivers/gpio/pir_motion_driver.go +++ b/drivers/gpio/pir_motion_driver.go @@ -1,53 +1,75 @@ package gpio import ( + "fmt" "time" "gobot.io/x/gobot/v2" ) +// pirMotionOptionApplier needs to be implemented by each configurable option type +type pirMotionOptionApplier interface { + apply(cfg *pirMotionConfiguration) +} + +// pirMotionConfiguration contains all changeable attributes of the driver. +type pirMotionConfiguration struct { + readInterval time.Duration +} + +// pirMotionReadIntervalOption is the type for applying another read interval to the configuration +type pirMotionReadIntervalOption time.Duration + // PIRMotionDriver represents a digital Proximity Infra Red (PIR) motion detecter +// +// Supported options: +// +// "WithName" type PIRMotionDriver struct { - *Driver + *driver + pirMotionCfg *pirMotionConfiguration gobot.Eventer - pin string - active bool - halt chan bool - interval time.Duration + active bool + halt chan struct{} } -// NewPIRMotionDriver returns a new PIRMotionDriver with a polling interval of -// 10 Milliseconds given a DigitalReader and pin. +// NewPIRMotionDriver returns a new driver for PIR motion sensor with a polling interval of 10 Milliseconds, +// given a DigitalReader and pin. // -// Optionally accepts: +// Supported options: // -// time.Duration: Interval at which the PIRMotionDriver is polled for new information -func NewPIRMotionDriver(a DigitalReader, pin string, v ...time.Duration) *PIRMotionDriver { +// "WithName" +// "WithButtonPollInterval" +func NewPIRMotionDriver(a DigitalReader, pin string, opts ...interface{}) *PIRMotionDriver { //nolint:forcetypeassert // no error return value, so there is no better way d := &PIRMotionDriver{ - Driver: NewDriver(a.(gobot.Connection), "PIRMotion"), - Eventer: gobot.NewEventer(), - pin: pin, - active: false, - interval: 10 * time.Millisecond, - halt: make(chan bool), + driver: newDriver(a.(gobot.Connection), "PIRMotion", withPin(pin)), + pirMotionCfg: &pirMotionConfiguration{readInterval: 10 * time.Millisecond}, } d.afterStart = d.initialize d.beforeHalt = d.shutdown - if len(v) > 0 { - d.interval = v[0] + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case pirMotionOptionApplier: + o.apply(d.pirMotionCfg) + case time.Duration: + // TODO this is only for backward compatibility and will be removed after version 2.x + d.pirMotionCfg.readInterval = o + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } } - d.AddEvent(MotionDetected) - d.AddEvent(MotionStopped) - d.AddEvent(Error) - return d } -// Pin returns the PIRMotionDriver pin -func (d *PIRMotionDriver) Pin() string { return d.pin } +// WithPIRMotionPollInterval change the asynchronous cyclic reading interval from default 10ms to the given value. +func WithPIRMotionPollInterval(interval time.Duration) pirMotionOptionApplier { + return pirMotionReadIntervalOption(interval) +} // Active gets the current state func (d *PIRMotionDriver) Active() bool { @@ -64,22 +86,33 @@ func (d *PIRMotionDriver) Active() bool { // // MotionDetected - On motion detected // MotionStopped int - On motion stopped -// Error error - On button error +// Error error - On pirMotion error // // The PIRMotionDriver will send the MotionDetected event over and over, // just as long as motion is still being detected. // It will only send the MotionStopped event once, however, until // motion starts being detected again func (d *PIRMotionDriver) initialize() error { + if d.pirMotionCfg.readInterval == 0 { + return fmt.Errorf("the read interval for pirMotion needs to be greater than zero") + } + + d.Eventer = gobot.NewEventer() + d.AddEvent(MotionDetected) + d.AddEvent(MotionStopped) + d.AddEvent(Error) + + d.halt = make(chan struct{}) + go func() { for { - newValue, err := d.connection.(DigitalReader).DigitalRead(d.Pin()) - if err != nil { - d.Publish(Error, err) - } - d.update(newValue) select { - case <-time.After(d.interval): + case <-time.After(d.pirMotionCfg.readInterval): + newValue, err := d.digitalRead(d.driverCfg.pin) + if err != nil { + d.Publish(Error, err) + } + d.update(newValue) case <-d.halt: return } @@ -90,7 +123,12 @@ func (d *PIRMotionDriver) initialize() error { // shutdown stops polling func (d *PIRMotionDriver) shutdown() error { - d.halt <- true + if d.pirMotionCfg.readInterval == 0 || d.halt == nil { + // cyclic reading deactivated + return nil + } + + close(d.halt) // broadcast halt, also to the test return nil } @@ -112,3 +150,11 @@ func (d *PIRMotionDriver) update(newValue int) { } } } + +func (o pirMotionReadIntervalOption) String() string { + return "read interval option for PIR motion sensor" +} + +func (o pirMotionReadIntervalOption) apply(cfg *pirMotionConfiguration) { + cfg.readInterval = time.Duration(o) +} diff --git a/drivers/gpio/pir_motion_driver_test.go b/drivers/gpio/pir_motion_driver_test.go index 04e4c3f79..2b4ba4695 100644 --- a/drivers/gpio/pir_motion_driver_test.go +++ b/drivers/gpio/pir_motion_driver_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*PIRMotionDriver)(nil) @@ -30,20 +31,41 @@ func TestNewPIRMotionDriver(t *testing.T) { d := NewPIRMotionDriver(a, "1") // assert assert.IsType(t, &PIRMotionDriver{}, d) - assert.True(t, strings.HasPrefix(d.name, "PIRMotion")) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "PIRMotion")) + assert.Equal(t, "1", d.driverCfg.pin) assert.Equal(t, a, d.connection) assert.NotNil(t, d.afterStart) assert.NotNil(t, d.beforeHalt) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) - assert.NotNil(t, d.Eventer) - assert.Equal(t, "1", d.pin) + // assert: driver specific attributes assert.False(t, d.active) - assert.Equal(t, 10*time.Millisecond, d.interval) - assert.NotNil(t, d.halt) - // act & assert other interval - d = NewPIRMotionDriver(newGpioTestAdaptor(), "1", 30*time.Second) - assert.Equal(t, 30*time.Second, d.interval) + assert.Equal(t, 10*time.Millisecond, d.pirMotionCfg.readInterval) + assert.Nil(t, d.Eventer) // will be created on initialize + assert.Nil(t, d.halt) // will be created on initialize +} + +func TestNewPIRMotionDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "voltage 1" + cycReadDur = 30 * time.Millisecond + ) + panicFunc := func() { + NewPIRMotionDriver(newGpioTestAdaptor(), "1", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewPIRMotionDriver(newGpioTestAdaptor(), "1", WithName(myName), WithPIRMotionPollInterval(cycReadDur)) + // assert + assert.Equal(t, cycReadDur, d.pirMotionCfg.readInterval) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } func TestPIRMotionStart(t *testing.T) { @@ -67,15 +89,15 @@ func TestPIRMotionStart(t *testing.T) { } } + // act: start cyclic reading + err := d.Start() + _ = d.Once(MotionDetected, func(data interface{}) { assert.True(t, d.active) nextVal <- 0 sem <- true }) - // act - err := d.Start() - // assert & rearrange require.NoError(t, err) @@ -111,7 +133,7 @@ func TestPIRMotionStart(t *testing.T) { sem <- true }) - d.halt <- true + require.NoError(t, d.Halt()) nextVal <- 1 select { @@ -124,15 +146,16 @@ func TestPIRMotionStart(t *testing.T) { func TestPIRMotionHalt(t *testing.T) { // arrange d, _ := initTestPIRMotionDriverWithStubbedAdaptor() - const timeout = 10 * time.Microsecond + require.NoError(t, d.Start()) + timeout := 2 * d.pirMotionCfg.readInterval wg := sync.WaitGroup{} wg.Add(1) go func() { defer wg.Done() select { - case <-d.halt: // wait until halt was set to the channel + case <-d.halt: // wait until halt is broadcasted by close the channel case <-time.After(timeout): // otherwise run into the timeout - t.Errorf("halt was not received within %s", timeout) + assert.Fail(t, "halt was not received within %s", timeout) } }() // act & assert @@ -140,23 +163,6 @@ func TestPIRMotionHalt(t *testing.T) { wg.Wait() // wait until the go function was really finished } -func TestPIRMotionPin(t *testing.T) { - tests := map[string]struct { - want string - }{ - "10": {want: "10"}, - "36": {want: "36"}, - } - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - // arrange - d := PIRMotionDriver{pin: name} - // act & assert - assert.Equal(t, tc.want, d.Pin()) - }) - } -} - func TestPIRMotionActive(t *testing.T) { tests := map[string]struct { want bool @@ -167,7 +173,7 @@ func TestPIRMotionActive(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { // arrange - d := PIRMotionDriver{Driver: NewDriver(nil, "PIRMotion")} // just for mutex + d := PIRMotionDriver{driver: newDriver(nil, "PIRMotion")} // just for mutex d.active = tc.want // act & assert assert.Equal(t, tc.want, d.Active()) diff --git a/drivers/gpio/relay_driver.go b/drivers/gpio/relay_driver.go index 0516e5f91..48debcd38 100644 --- a/drivers/gpio/relay_driver.go +++ b/drivers/gpio/relay_driver.go @@ -1,36 +1,59 @@ package gpio import ( - "log" + "fmt" "gobot.io/x/gobot/v2" ) +// relayOptionApplier needs to be implemented by each configurable option type +type relayOptionApplier interface { + apply(cfg *relayConfiguration) +} + +// relayConfiguration contains all changeable attributes of the driver. +type relayConfiguration struct { + inverted bool +} + +// relayInvertedOption is the type for applying inverted behavior to the configuration +type relayInvertedOption bool + // RelayDriver represents a digital relay type RelayDriver struct { - pin string - name string - connection DigitalWriter - high bool - Inverted bool - gobot.Commander + *driver + relayCfg *relayConfiguration + high bool } // NewRelayDriver return a new RelayDriver given a DigitalWriter and pin. // +// Supported options: +// +// "WithName" +// "WithRelayInverted" +// // Adds the following API Commands: // // "Toggle" - See RelayDriver.Toggle // "On" - See RelayDriver.On // "Off" - See RelayDriver.Off -func NewRelayDriver(a DigitalWriter, pin string) *RelayDriver { +func NewRelayDriver(a DigitalWriter, pin string, opts ...interface{}) *RelayDriver { + //nolint:forcetypeassert // no error return value, so there is no better way d := &RelayDriver{ - name: gobot.DefaultName("Relay"), - pin: pin, - connection: a, - high: false, - Inverted: false, - Commander: gobot.NewCommander(), + driver: newDriver(a.(gobot.Connection), "Relay", withPin(pin)), + relayCfg: &relayConfiguration{}, + } + + for _, opt := range opts { + switch o := opt.(type) { + case optionApplier: + o.apply(d.driverCfg) + case relayOptionApplier: + o.apply(d.relayCfg) + default: + panic(fmt.Sprintf("'%s' can not be applied on '%s'", opt, d.driverCfg.name)) + } } d.AddCommand("Toggle", func(params map[string]interface{}) interface{} { @@ -48,34 +71,14 @@ func NewRelayDriver(a DigitalWriter, pin string) *RelayDriver { return d } -// Start implements the Driver interface -func (d *RelayDriver) Start() error { return nil } - -// Halt implements the Driver interface -func (d *RelayDriver) Halt() error { return nil } - -// Name returns the RelayDrivers name -func (d *RelayDriver) Name() string { return d.name } - -// SetName sets the RelayDrivers name -func (d *RelayDriver) SetName(n string) { d.name = n } - -// Pin returns the RelayDrivers name -func (d *RelayDriver) Pin() string { return d.pin } - -// Connection returns the RelayDrivers Connection -func (d *RelayDriver) Connection() gobot.Connection { - if conn, ok := d.connection.(gobot.Connection); ok { - return conn - } - - log.Printf("%s has no gobot connection\n", d.name) - return nil +// WithRelayInverted change the relay action to inverted. +func WithRelayInverted() relayOptionApplier { + return relayInvertedOption(true) } // State return true if the relay is On and false if the relay is Off func (d *RelayDriver) State() bool { - if d.Inverted { + if d.relayCfg.inverted { return !d.high } return d.high @@ -84,14 +87,14 @@ func (d *RelayDriver) State() bool { // On sets the relay to a high state. func (d *RelayDriver) On() error { newValue := byte(1) - if d.Inverted { + if d.relayCfg.inverted { newValue = 0 } - if err := d.connection.DigitalWrite(d.Pin(), newValue); err != nil { + if err := d.digitalWrite(d.driverCfg.pin, newValue); err != nil { return err } - d.high = !d.Inverted + d.high = !d.relayCfg.inverted return nil } @@ -99,14 +102,14 @@ func (d *RelayDriver) On() error { // Off sets the relay to a low state. func (d *RelayDriver) Off() error { newValue := byte(0) - if d.Inverted { + if d.relayCfg.inverted { newValue = 1 } - if err := d.connection.DigitalWrite(d.Pin(), newValue); err != nil { + if err := d.digitalWrite(d.driverCfg.pin, newValue); err != nil { return err } - d.high = d.Inverted + d.high = d.relayCfg.inverted return nil } @@ -119,3 +122,16 @@ func (d *RelayDriver) Toggle() error { return d.On() } + +// IsInverted returns true if the relay acts inverted +func (d *RelayDriver) IsInverted() bool { + return d.relayCfg.inverted +} + +func (o relayInvertedOption) String() string { + return "relay acts inverted option" +} + +func (o relayInvertedOption) apply(cfg *relayConfiguration) { + cfg.inverted = bool(o) +} diff --git a/drivers/gpio/relay_driver_test.go b/drivers/gpio/relay_driver_test.go index 6cf319c60..d30db0762 100644 --- a/drivers/gpio/relay_driver_test.go +++ b/drivers/gpio/relay_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*RelayDriver)(nil) @@ -26,29 +27,47 @@ func initTestRelayDriver() (*RelayDriver, *gpioTestAdaptor) { return NewRelayDriver(a, "1"), a } -func TestRelayDriverDefaultName(t *testing.T) { - g, _ := initTestRelayDriver() - assert.NotNil(t, g.Connection()) - assert.True(t, strings.HasPrefix(g.Name(), "Relay")) -} - -func TestRelayDriverSetName(t *testing.T) { - g, _ := initTestRelayDriver() - g.SetName("mybot") - assert.Equal(t, "mybot", g.Name()) -} - -func TestRelayDriverStart(t *testing.T) { - d, _ := initTestRelayDriver() - require.NoError(t, d.Start()) +func TestNewRelayDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewRelayDriver(a, "10") + // assert + assert.IsType(t, &RelayDriver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "Relay")) + assert.Equal(t, "10", d.driverCfg.pin) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.False(t, d.relayCfg.inverted) + assert.False(t, d.high) } -func TestRelayDriverHalt(t *testing.T) { - d, _ := initTestRelayDriver() - require.NoError(t, d.Halt()) +func TestNewRelayDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "switch alarm relay" + ) + panicFunc := func() { + NewRelayDriver(newGpioTestAdaptor(), "1", WithName("crazy"), aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewRelayDriver(newGpioTestAdaptor(), "1", WithName(myName), WithRelayInverted()) + // assert + assert.True(t, d.relayCfg.inverted) + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } -func TestRelayDriverToggle(t *testing.T) { +func TestRelayToggle(t *testing.T) { d, a := initTestRelayDriver() var lastVal byte a.digitalWriteFunc = func(pin string, val byte) error { @@ -67,7 +86,7 @@ func TestRelayDriverToggle(t *testing.T) { assert.Equal(t, byte(0), lastVal) } -func TestRelayDriverToggleInverted(t *testing.T) { +func TestRelayToggleInverted(t *testing.T) { d, a := initTestRelayDriver() var lastVal byte a.digitalWriteFunc = func(pin string, val byte) error { @@ -75,7 +94,7 @@ func TestRelayDriverToggleInverted(t *testing.T) { return nil } - d.Inverted = true + WithRelayInverted().apply(d.relayCfg) _ = d.Off() assert.False(t, d.State()) assert.Equal(t, byte(1), lastVal) @@ -87,7 +106,7 @@ func TestRelayDriverToggleInverted(t *testing.T) { assert.Equal(t, byte(1), lastVal) } -func TestRelayDriverCommands(t *testing.T) { +func TestRelay_Commands(t *testing.T) { d, a := initTestRelayDriver() var lastVal byte a.digitalWriteFunc = func(pin string, val byte) error { @@ -108,14 +127,14 @@ func TestRelayDriverCommands(t *testing.T) { assert.Equal(t, byte(0), lastVal) } -func TestRelayDriverCommandsInverted(t *testing.T) { +func TestRelay_CommandsInverted(t *testing.T) { d, a := initTestRelayDriver() var lastVal byte a.digitalWriteFunc = func(pin string, val byte) error { lastVal = val return nil } - d.Inverted = true + WithRelayInverted().apply(d.relayCfg) assert.Nil(t, d.Command("Off")(nil)) assert.True(t, d.High()) diff --git a/drivers/gpio/rgb_led_driver.go b/drivers/gpio/rgb_led_driver.go index c67b90080..a2b2f6736 100644 --- a/drivers/gpio/rgb_led_driver.go +++ b/drivers/gpio/rgb_led_driver.go @@ -1,27 +1,26 @@ package gpio import ( - "log" - "gobot.io/x/gobot/v2" ) // RgbLedDriver represents a digital RGB Led type RgbLedDriver struct { + *driver pinRed string redColor byte pinGreen string greenColor byte pinBlue string blueColor byte - name string - connection DigitalWriter high bool - gobot.Commander } -// NewRgbLedDriver return a new RgbLedDriver given a DigitalWriter and -// 3 pins: redPin, greenPin, and bluePin +// NewRgbLedDriver return a new RgbLedDriver given a PwmWriter and 3 pins: redPin, greenPin, and bluePin +// +// Supported options: +// +// "WithName" // // Adds the following API Commands: // @@ -29,15 +28,13 @@ type RgbLedDriver struct { // "Toggle" - See RgbLedDriver.Toggle // "On" - See RgbLedDriver.On // "Off" - See RgbLedDriver.Off -func NewRgbLedDriver(a DigitalWriter, redPin string, greenPin string, bluePin string) *RgbLedDriver { +func NewRgbLedDriver(a PwmWriter, redPin string, greenPin string, bluePin string, opts ...interface{}) *RgbLedDriver { + //nolint:forcetypeassert // no error return value, so there is no better way d := &RgbLedDriver{ - name: gobot.DefaultName("RGBLED"), - pinRed: redPin, - pinGreen: greenPin, - pinBlue: bluePin, - connection: a, - high: false, - Commander: gobot.NewCommander(), + driver: newDriver(a.(gobot.Connection), "RGBLED", opts...), + pinRed: redPin, + pinGreen: greenPin, + pinBlue: bluePin, } //nolint:forcetypeassert // ok here @@ -63,18 +60,6 @@ func NewRgbLedDriver(a DigitalWriter, redPin string, greenPin string, bluePin st return d } -// Start implements the Driver interface -func (d *RgbLedDriver) Start() error { return nil } - -// Halt implements the Driver interface -func (d *RgbLedDriver) Halt() error { return nil } - -// Name returns the RGBLEDDrivers name -func (d *RgbLedDriver) Name() string { return d.name } - -// SetName sets the RGBLEDDrivers name -func (d *RgbLedDriver) SetName(n string) { d.name = n } - // Pin returns the RgbLedDrivers pins func (d *RgbLedDriver) Pin() string { return "r=" + d.pinRed + ", g=" + d.pinGreen + ", b=" + d.pinBlue @@ -89,16 +74,6 @@ func (d *RgbLedDriver) GreenPin() string { return d.pinGreen } // BluePin returns the RgbLedDrivers bluePin func (d *RgbLedDriver) BluePin() string { return d.pinBlue } -// Connection returns the RgbLedDriver Connection -func (d *RgbLedDriver) Connection() gobot.Connection { - if conn, ok := d.connection.(gobot.Connection); ok { - return conn - } - - log.Printf("%s has no gobot connection\n", d.name) - return nil -} - // State return true if the led is On and false if the led is Off func (d *RgbLedDriver) State() bool { return d.high @@ -151,10 +126,7 @@ func (d *RgbLedDriver) Toggle() error { // SetLevel sets the led to the specified color level func (d *RgbLedDriver) SetLevel(pin string, level byte) error { - if writer, ok := d.connection.(PwmWriter); ok { - return writer.PwmWrite(pin, level) - } - return ErrPwmWriteUnsupported + return d.pwmWrite(pin, level) } // SetRGB sets the Red Green Blue value of the LED. diff --git a/drivers/gpio/rgb_led_driver_test.go b/drivers/gpio/rgb_led_driver_test.go index 27d9870d1..004f4dc15 100644 --- a/drivers/gpio/rgb_led_driver_test.go +++ b/drivers/gpio/rgb_led_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*RgbLedDriver)(nil) @@ -25,18 +26,57 @@ func initTestRgbLedDriver() *RgbLedDriver { return NewRgbLedDriver(a, "1", "2", "3") } -func TestRgbLedDriver(t *testing.T) { +func TestNewRgbLedDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewRgbLedDriver(a, "10", "20", "30") + // assert + assert.IsType(t, &RgbLedDriver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "RGBLED")) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.Equal(t, "10", d.RedPin()) + assert.Equal(t, "20", d.GreenPin()) + assert.Equal(t, "30", d.BluePin()) + assert.Equal(t, "r=10, g=20, b=30", d.Pin()) + assert.Equal(t, uint8(0), d.redColor) + assert.Equal(t, uint8(0), d.greenColor) + assert.Equal(t, uint8(0), d.blueColor) + assert.False(t, d.high) +} + +func TestNewRgbLedDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "colored light" + ) + panicFunc := func() { + NewRgbLedDriver(newGpioTestAdaptor(), "1", "2", "3", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewRgbLedDriver(newGpioTestAdaptor(), "1", "2", "3", WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + +func TestRgbLed_Commands(t *testing.T) { var err interface{} a := newGpioTestAdaptor() d := NewRgbLedDriver(a, "1", "2", "3") - assert.Equal(t, "r=1, g=2, b=3", d.Pin()) - assert.Equal(t, "1", d.RedPin()) - assert.Equal(t, "2", d.GreenPin()) - assert.Equal(t, "3", d.BluePin()) - assert.NotNil(t, d.Connection()) - a.digitalWriteFunc = func(string, byte) error { return errors.New("write error") } @@ -57,16 +97,6 @@ func TestRgbLedDriver(t *testing.T) { require.EqualError(t, err.(error), "pwm error") } -func TestRgbLedDriverStart(t *testing.T) { - d := initTestRgbLedDriver() - require.NoError(t, d.Start()) -} - -func TestRgbLedDriverHalt(t *testing.T) { - d := initTestRgbLedDriver() - require.NoError(t, d.Halt()) -} - func TestRgbLedDriverToggle(t *testing.T) { d := initTestRgbLedDriver() _ = d.Off() @@ -76,7 +106,7 @@ func TestRgbLedDriverToggle(t *testing.T) { assert.False(t, d.State()) } -func TestRgbLedDriverSetLevel(t *testing.T) { +func TestRgbLedSetLevel(t *testing.T) { a := newGpioTestAdaptor() d := NewRgbLedDriver(a, "1", "2", "3") require.NoError(t, d.SetLevel("1", 150)) @@ -87,16 +117,3 @@ func TestRgbLedDriverSetLevel(t *testing.T) { } require.EqualError(t, d.SetLevel("1", 150), "pwm error") } - -func TestRgbLedDriverDefaultName(t *testing.T) { - a := newGpioTestAdaptor() - d := NewRgbLedDriver(a, "1", "2", "3") - assert.True(t, strings.HasPrefix(d.Name(), "RGB")) -} - -func TestRgbLedDriverSetName(t *testing.T) { - a := newGpioTestAdaptor() - d := NewRgbLedDriver(a, "1", "2", "3") - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) -} diff --git a/drivers/gpio/servo_driver.go b/drivers/gpio/servo_driver.go index 57a4ffea8..60faf5b0f 100644 --- a/drivers/gpio/servo_driver.go +++ b/drivers/gpio/servo_driver.go @@ -1,99 +1,77 @@ package gpio import ( - "log" + "fmt" "gobot.io/x/gobot/v2" ) // ServoDriver Represents a Servo type ServoDriver struct { - name string - pin string - connection ServoWriter - gobot.Commander - CurrentAngle byte + *driver + currentAngle byte } // NewServoDriver returns a new ServoDriver given a ServoWriter and pin. // +// Supported options: +// +// "WithName" +// // Adds the following API Commands: // // "Move" - See ServoDriver.Move -// "Min" - See ServoDriver.Min -// "Center" - See ServoDriver.Center -// "Max" - See ServoDriver.Max -func NewServoDriver(a ServoWriter, pin string) *ServoDriver { +// "Min" - See ServoDriver.ToMin +// "Center" - See ServoDriver.ToCenter +// "Max" - See ServoDriver.ToMax +func NewServoDriver(a ServoWriter, pin string, opts ...interface{}) *ServoDriver { + //nolint:forcetypeassert // no error return value, so there is no better way d := &ServoDriver{ - name: gobot.DefaultName("Servo"), - connection: a, - pin: pin, - Commander: gobot.NewCommander(), - CurrentAngle: 0, + driver: newDriver(a.(gobot.Connection), "Servo", append(opts, withPin(pin))...), } d.AddCommand("Move", func(params map[string]interface{}) interface{} { angle := byte(params["angle"].(float64)) //nolint:forcetypeassert // ok here return d.Move(angle) }) - d.AddCommand("Min", func(params map[string]interface{}) interface{} { - return d.Min() + d.AddCommand("ToMin", func(params map[string]interface{}) interface{} { + return d.ToMin() }) - d.AddCommand("Center", func(params map[string]interface{}) interface{} { - return d.Center() + d.AddCommand("ToCenter", func(params map[string]interface{}) interface{} { + return d.ToCenter() }) - d.AddCommand("Max", func(params map[string]interface{}) interface{} { - return d.Max() + d.AddCommand("ToMax", func(params map[string]interface{}) interface{} { + return d.ToMax() }) return d } -// Name returns the ServoDrivers name -func (d *ServoDriver) Name() string { return d.name } - -// SetName sets the ServoDrivers name -func (d *ServoDriver) SetName(n string) { d.name = n } - -// Pin returns the ServoDrivers pin -func (d *ServoDriver) Pin() string { return d.pin } - -// Connection returns the ServoDrivers connection -func (d *ServoDriver) Connection() gobot.Connection { - if conn, ok := d.connection.(gobot.Connection); ok { - return conn - } - - log.Printf("%s has no gobot connection\n", d.name) - return nil -} - -// Start implements the Driver interface -func (d *ServoDriver) Start() error { return nil } - -// Halt implements the Driver interface -func (d *ServoDriver) Halt() error { return nil } - // Move sets the servo to the specified angle. Acceptable angles are 0-180 func (d *ServoDriver) Move(angle uint8) error { if angle > 180 { - return ErrServoOutOfRange + return fmt.Errorf("servo angle (%d) must be between 0-180", angle) } - d.CurrentAngle = angle - return d.connection.ServoWrite(d.Pin(), angle) + d.currentAngle = angle + return d.servoWrite(d.driverCfg.pin, angle) } // Min sets the servo to it's minimum position -func (d *ServoDriver) Min() error { +func (d *ServoDriver) ToMin() error { return d.Move(0) } // Center sets the servo to it's center position -func (d *ServoDriver) Center() error { +func (d *ServoDriver) ToCenter() error { return d.Move(90) } // Max sets the servo to its maximum position -func (d *ServoDriver) Max() error { +func (d *ServoDriver) ToMax() error { return d.Move(180) } + +// Angle returns the current angle +func (d *ServoDriver) Angle() uint8 { + return d.currentAngle +} diff --git a/drivers/gpio/servo_driver_test.go b/drivers/gpio/servo_driver_test.go index 8efb5d751..775cc7418 100644 --- a/drivers/gpio/servo_driver_test.go +++ b/drivers/gpio/servo_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*ServoDriver)(nil) @@ -18,75 +19,91 @@ func initTestServoDriver() *ServoDriver { return NewServoDriver(newGpioTestAdaptor(), "1") } -func TestServoDriver(t *testing.T) { +func TestNewServoDriver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewServoDriver(a, "10") + // assert + assert.IsType(t, &ServoDriver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "Servo")) + assert.Equal(t, "10", d.driverCfg.pin) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.Equal(t, uint8(0), d.currentAngle) +} + +func TestNewServoDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "left wheel" + ) + panicFunc := func() { + NewServoDriver(newGpioTestAdaptor(), "1", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewServoDriver(newGpioTestAdaptor(), "1", WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + +func TestServo_Commands(t *testing.T) { var err interface{} a := newGpioTestAdaptor() d := NewServoDriver(a, "1") - assert.Equal(t, "1", d.Pin()) - assert.NotNil(t, d.Connection()) - a.servoWriteFunc = func(string, byte) error { return errors.New("pwm error") } - err = d.Command("Min")(nil) + err = d.Command("ToMin")(nil) require.EqualError(t, err.(error), "pwm error") - err = d.Command("Center")(nil) + err = d.Command("ToCenter")(nil) require.EqualError(t, err.(error), "pwm error") - err = d.Command("Max")(nil) + err = d.Command("ToMax")(nil) require.EqualError(t, err.(error), "pwm error") err = d.Command("Move")(map[string]interface{}{"angle": 100.0}) require.EqualError(t, err.(error), "pwm error") } -func TestServoDriverStart(t *testing.T) { - d := initTestServoDriver() - require.NoError(t, d.Start()) -} - -func TestServoDriverHalt(t *testing.T) { - d := initTestServoDriver() - require.NoError(t, d.Halt()) -} - -func TestServoDriverMove(t *testing.T) { +func TestServoMove(t *testing.T) { d := initTestServoDriver() _ = d.Move(100) - assert.Equal(t, uint8(100), d.CurrentAngle) + assert.Equal(t, uint8(100), d.currentAngle) err := d.Move(200) - assert.Equal(t, ErrServoOutOfRange, err) -} - -func TestServoDriverMin(t *testing.T) { - d := initTestServoDriver() - _ = d.Min() - assert.Equal(t, uint8(0), d.CurrentAngle) -} - -func TestServoDriverMax(t *testing.T) { - d := initTestServoDriver() - _ = d.Max() - assert.Equal(t, uint8(180), d.CurrentAngle) + require.EqualError(t, err, "servo angle (200) must be between 0-180") } -func TestServoDriverCenter(t *testing.T) { +func TestServoMin(t *testing.T) { d := initTestServoDriver() - _ = d.Center() - assert.Equal(t, uint8(90), d.CurrentAngle) + _ = d.ToMin() + assert.Equal(t, uint8(0), d.currentAngle) + assert.Equal(t, d.currentAngle, d.Angle()) } -func TestServoDriverDefaultName(t *testing.T) { +func TestServoMax(t *testing.T) { d := initTestServoDriver() - assert.True(t, strings.HasPrefix(d.Name(), "Servo")) + _ = d.ToMax() + assert.Equal(t, uint8(180), d.currentAngle) } -func TestServoDriverSetName(t *testing.T) { +func TestServoCenter(t *testing.T) { d := initTestServoDriver() - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) + _ = d.ToCenter() + assert.Equal(t, uint8(90), d.currentAngle) } diff --git a/drivers/gpio/stepper_driver.go b/drivers/gpio/stepper_driver.go index f3ae3bdc6..b33b845fd 100644 --- a/drivers/gpio/stepper_driver.go +++ b/drivers/gpio/stepper_driver.go @@ -60,7 +60,7 @@ var StepperModes = struct { // StepperDriver is a common driver for stepper motors. It supports 3 different stepping modes. type StepperDriver struct { - *Driver + *driver pins [4]string phase phase @@ -80,18 +80,27 @@ type StepperDriver struct { stopAsynchRunFunc func(bool) error } -// NewStepperDriver returns a new StepperDriver given a -// DigitalWriter +// NewStepperDriver returns a new StepperDriver given a DigitalWriter // Pins - To which the stepper is connected // Phase - Defined by StepperModes {SinglePhaseStepping, DualPhaseStepping, HalfStepping} // Steps - No of steps per revolution of Stepper motor -func NewStepperDriver(a DigitalWriter, pins [4]string, phase phase, stepsPerRev uint) *StepperDriver { +// +// Supported options: +// +// "WithName" +func NewStepperDriver( + a DigitalWriter, + pins [4]string, + phase phase, + stepsPerRev uint, + opts ...interface{}, +) *StepperDriver { if stepsPerRev <= 0 { panic("steps per revolution needs to be greater than zero") } //nolint:forcetypeassert // no error return value, so there is no better way d := &StepperDriver{ - Driver: NewDriver(a.(gobot.Connection), "Stepper"), + driver: newDriver(a.(gobot.Connection), "Stepper", opts...), pins: pins, phase: phase, stepsPerRev: float32(stepsPerRev), @@ -185,7 +194,7 @@ func (d *StepperDriver) IsMoving() bool { // Stop running the stepper func (d *StepperDriver) Stop() error { if d.stopAsynchRunFunc == nil { - return fmt.Errorf("'%s' is not yet started", d.name) + return fmt.Errorf("'%s' is not yet started", d.driverCfg.name) } err := d.stopAsynchRunFunc(true) @@ -275,13 +284,13 @@ func (d *StepperDriver) shutdown() error { func (d *StepperDriver) stepAsynch(stepsToMove float64) error { if d.disabled { - return fmt.Errorf("'%s' is disabled and can not be running or moving", d.name) + return fmt.Errorf("'%s' is disabled and can not be running or moving", d.driverCfg.name) } // if running, return error or stop automatically if d.stopAsynchRunFunc != nil { if !d.haltIfRunning { - return fmt.Errorf("'%s' already running or moving", d.name) + return fmt.Errorf("'%s' already running or moving", d.driverCfg.name) } d.debug("stop former run forcefully") if err := d.stopAsynchRunFunc(true); err != nil { @@ -293,7 +302,7 @@ func (d *StepperDriver) stepAsynch(stepsToMove float64) error { // prepare stepping behavior stepsLeft := uint64(math.Abs(stepsToMove)) if stepsLeft == 0 { - return fmt.Errorf("no steps to do for '%s'", d.name) + return fmt.Errorf("no steps to do for '%s'", d.driverCfg.name) } // t [min] = steps [st] / (steps_per_revolution [st/u] * speed [u/min]) or @@ -346,7 +355,7 @@ func (d *StepperDriver) stepAsynch(stepsToMove float64) error { if !endlessMovement && forceStop { // do not wait if an normal movement was stopped forcefully - log.Printf("'%s' was forcefully stopped\n", d.name) + log.Printf("'%s' was forcefully stopped\n", d.driverCfg.name) return nil } @@ -356,7 +365,7 @@ func (d *StepperDriver) stepAsynch(stepsToMove float64) error { case err := <-runErrChan: return err case <-time.After(stopTimeout): - return fmt.Errorf("'%s' was not finished in %s", d.name, stopTimeout) + return fmt.Errorf("'%s' was not finished in %s", d.driverCfg.name, stopTimeout) } } @@ -409,7 +418,7 @@ func (d *StepperDriver) stepAsynch(stepsToMove float64) error { } } } - }(d.name) + }(d.driverCfg.name) return nil } @@ -446,8 +455,7 @@ func (d *StepperDriver) phasedStepping() error { r := int(math.Abs(float64(d.stepNum))) % len(d.phase) for i, v := range d.phase[r] { - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(d.pins[i], v); err != nil { + if err := d.digitalWrite(d.pins[i], v); err != nil { d.stepNum = oldStepNum return err } @@ -461,8 +469,7 @@ func (d *StepperDriver) phasedStepping() error { func (d *StepperDriver) sleepOuputs() error { for _, pin := range d.pins { - //nolint:forcetypeassert // type safe by constructor - if err := d.connection.(DigitalWriter).DigitalWrite(pin, 0); err != nil { + if err := d.digitalWrite(pin, 0); err != nil { return err } } diff --git a/drivers/gpio/stepper_driver_test.go b/drivers/gpio/stepper_driver_test.go index b00c31ef5..2b59771cf 100644 --- a/drivers/gpio/stepper_driver_test.go +++ b/drivers/gpio/stepper_driver_test.go @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2/drivers/aio" ) func initTestStepperDriverWithStubbedAdaptor() (*StepperDriver, *gpioTestAdaptor) { @@ -22,18 +24,20 @@ func initTestStepperDriverWithStubbedAdaptor() (*StepperDriver, *gpioTestAdaptor func TestNewStepperDriver(t *testing.T) { // arrange const stepsPerRev = 32 - a := newGpioTestAdaptor() // act d := NewStepperDriver(a, [4]string{"7", "11", "13", "15"}, StepperModes.DualPhaseStepping, stepsPerRev) // assert assert.IsType(t, &StepperDriver{}, d) - assert.True(t, strings.HasPrefix(d.name, "Stepper")) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "Stepper")) assert.Equal(t, a, d.connection) require.NoError(t, d.afterStart()) require.NoError(t, d.beforeHalt()) assert.NotNil(t, d.Commander) assert.NotNil(t, d.mutex) + // assert: driver specific attributes assert.Equal(t, "forward", d.direction) assert.Equal(t, StepperModes.DualPhaseStepping, d.phase) assert.InDelta(t, float32(stepsPerRev), d.stepsPerRev, 0.0) @@ -41,6 +45,26 @@ func TestNewStepperDriver(t *testing.T) { assert.Nil(t, d.stopAsynchRunFunc) } +func TestNewStepperDriver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "left wheel" + ) + panicFunc := func() { + NewStepperDriver(newGpioTestAdaptor(), [4]string{"7", "11", "13", "15"}, StepperModes.DualPhaseStepping, + 32, WithName("crazy"), aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewStepperDriver(newGpioTestAdaptor(), [4]string{"7", "11", "13", "15"}, StepperModes.DualPhaseStepping, + 32, WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) +} + func TestStepperMove_IsMoving(t *testing.T) { const stepsPerRev = 32 diff --git a/drivers/gpio/tm1638_driver.go b/drivers/gpio/tm1638_driver.go index 8b89ccff7..c9966f952 100644 --- a/drivers/gpio/tm1638_driver.go +++ b/drivers/gpio/tm1638_driver.go @@ -26,113 +26,186 @@ const ( ) // TM1638Driver is the driver for modules based on the TM1638, which has 8 7-segment displays, 8 LEDs and 8 buttons. -// Buttons are not supported +// Buttons are not supported yet by this driver. // // Datasheet EN: https://retrocip.cz/files/tm1638.pdf // Datasheet CN: http://www.datasheetspdf.com/pdf/775356/TitanMicro/TM1638/1 // // Ported from the Arduino driver https://github.com/rjbatista/tm1638-library type TM1638Driver struct { - pinClock *DirectPinDriver - pinData *DirectPinDriver - pinStrobe *DirectPinDriver - fonts map[string]byte - name string - connection gobot.Connection - gobot.Commander + *driver + pinClock *DirectPinDriver + pinData *DirectPinDriver + pinStrobe *DirectPinDriver + fonts map[string]byte } // NewTM1638Driver return a new TM1638Driver given a gobot.Connection and the clock, data and strobe pins -func NewTM1638Driver(a gobot.Connection, clockPin string, dataPin string, strobePin string) *TM1638Driver { - t := &TM1638Driver{ - name: gobot.DefaultName("TM1638"), - pinClock: NewDirectPinDriver(a, clockPin), - pinData: NewDirectPinDriver(a, dataPin), - pinStrobe: NewDirectPinDriver(a, strobePin), - fonts: NewTM1638Fonts(), - connection: a, - Commander: gobot.NewCommander(), +// +// Supported options: +// +// "WithName" +func NewTM1638Driver(a gobot.Connection, clockPin, dataPin, strobePin string, opts ...interface{}) *TM1638Driver { + d := &TM1638Driver{ + driver: newDriver(a, "TM1638", opts...), + pinClock: NewDirectPinDriver(a, clockPin), + pinData: NewDirectPinDriver(a, dataPin), + pinStrobe: NewDirectPinDriver(a, strobePin), + fonts: NewTM1638Fonts(), } + d.afterStart = d.initialize /* TODO : Add commands */ - return t + return d +} + +// SetLED changes the color (TM1638None, TM1638Red, TM1638Green) of the specific LED +func (d *TM1638Driver) SetLED(color byte, pos byte) error { + if pos > 7 { + return nil + } + return d.sendData((pos<<1)+1, color) +} + +// SetDisplay cuts and sends a byte array to the display (without dots) +func (d *TM1638Driver) SetDisplay(data []byte) error { + minLength := int(math.Min(8, float64(len(data)))) + for i := 0; i < minLength; i++ { + if err := d.SendChar(byte(i), data[i], false); err != nil { + return err + } + } + return nil } -// Start initializes the tm1638, it uses a SPI-like communication protocol -func (t *TM1638Driver) Start() error { - if err := t.pinStrobe.On(); err != nil { +// SetDisplayText cuts and sends a string to the display (without dots) +func (d *TM1638Driver) SetDisplayText(text string) error { + data := d.fromStringToByteArray(text) + minLength := int(math.Min(8, float64(len(data)))) + for i := 0; i < minLength; i++ { + if err := d.SendChar(byte(i), data[i], false); err != nil { + return err + } + } + return nil +} + +// SendChar sends one byte to the specific position in the display +func (d *TM1638Driver) SendChar(pos byte, data byte, dot bool) error { + if pos > 7 { + return nil + } + var dotData byte + if dot { + dotData = TM1638DispCtrl + } + return d.sendData(pos<<1, data|(dotData)) +} + +// AddFonts adds new custom fonts or modify the representation of existing ones +func (d *TM1638Driver) AddFonts(fonts map[string]byte) { + for k, v := range fonts { + d.fonts[k] = v + } +} + +// ClearFonts removes all the fonts from the driver +func (d *TM1638Driver) ClearFonts() { + d.fonts = make(map[string]byte) +} + +// initialize initializes the tm1638, it uses a SPI-like communication protocol +func (d *TM1638Driver) initialize() error { + if err := d.pinStrobe.On(); err != nil { return err } - if err := t.pinClock.On(); err != nil { + if err := d.pinClock.On(); err != nil { return err } - if err := t.sendCommand(TM1638DataCmd); err != nil { + if err := d.sendCommand(TM1638DataCmd); err != nil { return err } - if err := t.sendCommand(TM1638DispCtrl | 8 | 7); err != nil { + if err := d.sendCommand(TM1638DispCtrl | 8 | 7); err != nil { return err } - if err := t.pinStrobe.Off(); err != nil { + if err := d.pinStrobe.Off(); err != nil { return err } - if err := t.send(TM1638AddrCmd); err != nil { + if err := d.send(TM1638AddrCmd); err != nil { return err } for i := 0; i < 16; i++ { - if err := t.send(TM1638WriteDisp); err != nil { + if err := d.send(TM1638WriteDisp); err != nil { return err } } - return t.pinStrobe.On() + return d.pinStrobe.On() } -// Halt implements the Driver interface -func (t *TM1638Driver) Halt() error { return nil } - -// Name returns the TM1638Drivers name -func (t *TM1638Driver) Name() string { return t.name } +// fromStringToByteArray translates a string to a byte array with the corresponding representation +// for the 7-segment LCD, return and empty character if the font is not available +func (d *TM1638Driver) fromStringToByteArray(str string) []byte { + chars := strings.Split(str, "") + data := make([]byte, len(chars)) -// SetName sets the TM1638Drivers name -func (t *TM1638Driver) SetName(n string) { t.name = n } + for index, char := range chars { + if val, ok := d.fonts[char]; ok { + data[index] = val + } + } + return data +} -// Connection returns the TM1638Driver Connection -func (t *TM1638Driver) Connection() gobot.Connection { - return t.connection +// sendData is an auxiliary function to send data to the TM1638 module +func (d *TM1638Driver) sendData(address byte, data byte) error { + if err := d.sendCommand(TM1638DataCmd | TM1638FixedAddr); err != nil { + return err + } + if err := d.pinStrobe.Off(); err != nil { + return err + } + if err := d.send(TM1638AddrCmd | address); err != nil { + return err + } + if err := d.send(data); err != nil { + return err + } + return d.pinStrobe.On() } // sendCommand is an auxiliary function to send commands to the TM1638 module -func (t *TM1638Driver) sendCommand(cmd byte) error { - if err := t.pinStrobe.Off(); err != nil { +func (d *TM1638Driver) sendCommand(cmd byte) error { + if err := d.pinStrobe.Off(); err != nil { return err } - if err := t.send(cmd); err != nil { + if err := d.send(cmd); err != nil { return err } - return t.pinStrobe.On() + return d.pinStrobe.On() } // send writes data on the module -func (t *TM1638Driver) send(data byte) error { +func (d *TM1638Driver) send(data byte) error { for i := 0; i < 8; i++ { - if err := t.pinClock.Off(); err != nil { + if err := d.pinClock.Off(); err != nil { return err } if (data & 1) > 0 { - if err := t.pinData.On(); err != nil { + if err := d.pinData.On(); err != nil { return err } } else { - if err := t.pinData.Off(); err != nil { + if err := d.pinData.Off(); err != nil { return err } } data >>= 1 - if err := t.pinClock.On(); err != nil { + if err := d.pinClock.On(); err != nil { return err } } @@ -140,92 +213,6 @@ func (t *TM1638Driver) send(data byte) error { return nil } -// sendData is an auxiliary function to send data to the TM1638 module -func (t *TM1638Driver) sendData(address byte, data byte) error { - if err := t.sendCommand(TM1638DataCmd | TM1638FixedAddr); err != nil { - return err - } - if err := t.pinStrobe.Off(); err != nil { - return err - } - if err := t.send(TM1638AddrCmd | address); err != nil { - return err - } - if err := t.send(data); err != nil { - return err - } - return t.pinStrobe.On() -} - -// SetLED changes the color (TM1638None, TM1638Red, TM1638Green) of the specific LED -func (t *TM1638Driver) SetLED(color byte, pos byte) error { - if pos > 7 { - return nil - } - return t.sendData((pos<<1)+1, color) -} - -// SetDisplay cuts and sends a byte array to the display (without dots) -func (t *TM1638Driver) SetDisplay(data []byte) error { - minLength := int(math.Min(8, float64(len(data)))) - for i := 0; i < minLength; i++ { - if err := t.SendChar(byte(i), data[i], false); err != nil { - return err - } - } - return nil -} - -// SetDisplayText cuts and sends a string to the display (without dots) -func (t *TM1638Driver) SetDisplayText(text string) error { - data := t.fromStringToByteArray(text) - minLength := int(math.Min(8, float64(len(data)))) - for i := 0; i < minLength; i++ { - if err := t.SendChar(byte(i), data[i], false); err != nil { - return err - } - } - return nil -} - -// SendChar sends one byte to the specific position in the display -func (t *TM1638Driver) SendChar(pos byte, data byte, dot bool) error { - if pos > 7 { - return nil - } - var dotData byte - if dot { - dotData = TM1638DispCtrl - } - return t.sendData(pos<<1, data|(dotData)) -} - -// fromStringToByteArray translates a string to a byte array with the corresponding representation -// for the 7-segment LCD, return and empty character if the font is not available -func (t *TM1638Driver) fromStringToByteArray(str string) []byte { - chars := strings.Split(str, "") - data := make([]byte, len(chars)) - - for index, char := range chars { - if val, ok := t.fonts[char]; ok { - data[index] = val - } - } - return data -} - -// AddFonts adds new custom fonts or modify the representation of existing ones -func (t *TM1638Driver) AddFonts(fonts map[string]byte) { - for k, v := range fonts { - t.fonts[k] = v - } -} - -// ClearFonts removes all the fonts from the driver -func (t *TM1638Driver) ClearFonts() { - t.fonts = make(map[string]byte) -} - // NewTM1638Fonts returns a map with fonts and their corresponding byte for proper representation on the 7-segment LCD func NewTM1638Fonts() map[string]byte { return map[string]byte{ diff --git a/drivers/gpio/tm1638_driver_test.go b/drivers/gpio/tm1638_driver_test.go index ba60fa8d8..15fb9a7e9 100644 --- a/drivers/gpio/tm1638_driver_test.go +++ b/drivers/gpio/tm1638_driver_test.go @@ -8,65 +8,83 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" ) var _ gobot.Driver = (*TM1638Driver)(nil) -// --------- HELPERS func initTestTM1638Driver() *TM1638Driver { d, _ := initTestTM1638DriverWithStubbedAdaptor() return d } func initTestTM1638DriverWithStubbedAdaptor() (*TM1638Driver, *gpioTestAdaptor) { - adaptor := newGpioTestAdaptor() - return NewTM1638Driver(adaptor, "1", "2", "3"), adaptor + a := newGpioTestAdaptor() + return NewTM1638Driver(a, "1", "2", "3"), a } -// --------- TESTS -func TestTM1638Driver(t *testing.T) { - var a interface{} = initTestTM1638Driver() - _, ok := a.(*TM1638Driver) - if !ok { - t.Errorf("NewTM1638Driver() should have returned a *TM1638Driver") - } -} - -func TestTM1638DriverStart(t *testing.T) { - d := initTestTM1638Driver() - require.NoError(t, d.Start()) +func TestNewTM1638Driver(t *testing.T) { + // arrange + a := newGpioTestAdaptor() + // act + d := NewTM1638Driver(a, "10", "20", "30") + // assert + assert.IsType(t, &TM1638Driver{}, d) + // assert: gpio.driver attributes + require.NotNil(t, d.driver) + assert.True(t, strings.HasPrefix(d.driverCfg.name, "TM1638")) + assert.Equal(t, a, d.connection) + assert.NotNil(t, d.afterStart) + assert.NotNil(t, d.beforeHalt) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) + // assert: driver specific attributes + assert.NotNil(t, d.pinClock) + assert.NotNil(t, d.pinData) + assert.NotNil(t, d.pinStrobe) + assert.NotNil(t, d.fonts) } -func TestTM1638DriverHalt(t *testing.T) { - d := initTestTM1638Driver() - require.NoError(t, d.Halt()) -} - -func TestTM1638DriverDefaultName(t *testing.T) { - d := initTestTM1638Driver() - assert.True(t, strings.HasPrefix(d.Name(), "TM1638")) +func TestNewTM1638Driver_options(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option, least one + // option of this driver and one of another driver (which should lead to panic). Further tests for options can also + // be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + myName = "show rotation count" + ) + panicFunc := func() { + NewTM1638Driver(newGpioTestAdaptor(), "1", "2", "3", WithName("crazy"), + aio.WithActuatorScaler(func(float64) int { return 0 })) + } + // act + d := NewTM1638Driver(newGpioTestAdaptor(), "1", "2", "3", WithName(myName)) + // assert + assert.Equal(t, myName, d.Name()) + assert.PanicsWithValue(t, "'scaler option for analog actuators' can not be applied on 'crazy'", panicFunc) } -func TestTM1638DriverSetName(t *testing.T) { +func TestTM1638Start(t *testing.T) { + // arrange d := initTestTM1638Driver() - d.SetName("mybot") - assert.Equal(t, "mybot", d.Name()) + // act & assert: tests also initialize() + require.NoError(t, d.Start()) } -func TestTM1638DriverFromStringToByteArray(t *testing.T) { +func TestTM1638FromStringToByteArray(t *testing.T) { d := initTestTM1638Driver() data := d.fromStringToByteArray("Hello World") assert.Equal(t, []byte{0x76, 0x7B, 0x30, 0x30, 0x5C, 0x00, 0x1D, 0x5C, 0x50, 0x30, 0x5E}, data) } -func TestTM1638DriverAddFonts(t *testing.T) { +func TestTM1638AddFonts(t *testing.T) { d := initTestTM1638Driver() d.AddFonts(map[string]byte{"µ": 0x1C, "ß": 0x7F}) data := d.fromStringToByteArray("µß") assert.Equal(t, []byte{0x1C, 0x7F}, data) } -func TestTM1638DriverClearFonts(t *testing.T) { +func TestTM1638ClearFonts(t *testing.T) { d := initTestTM1638Driver() d.ClearFonts() data := d.fromStringToByteArray("Hello World") diff --git a/drivers/i2c/adafruit1109_driver.go b/drivers/i2c/adafruit1109_driver.go index c8eabeca9..92781fea4 100644 --- a/drivers/i2c/adafruit1109_driver.go +++ b/drivers/i2c/adafruit1109_driver.go @@ -84,8 +84,9 @@ func NewAdafruit1109Driver(a Connector, options ...func(Config)) *Adafruit1109Dr // but inside the driver the row is used as row and col as column rows := 2 columns := 16 - lcd := gpio.NewHD44780Driver(d, columns, rows, gpio.HD44780_4BITMODE, d.rsPin.String(), d.enPin.String(), dataPins) - lcd.SetRWPin(d.rwPin.String()) + lcd := gpio.NewHD44780Driver(d, columns, rows, gpio.HD44780_4BITMODE, d.rsPin.String(), d.enPin.String(), dataPins, + gpio.WithHD44780RWPin(d.rwPin.String())) + d.HD44780Driver = lcd return d } diff --git a/examples/edison_grove_button.go b/examples/edison_grove_button.go index cd47cc570..af5459400 100644 --- a/examples/edison_grove_button.go +++ b/examples/edison_grove_button.go @@ -16,7 +16,7 @@ import ( func main() { e := edison.NewAdaptor() - button := gpio.NewGroveButtonDriver(e, "2") + button := gpio.NewButtonDriver(e, "2") work := func() { button.On(gpio.ButtonPush, func(data interface{}) { diff --git a/examples/edison_grove_led.go b/examples/edison_grove_led.go index 8df00721a..440f58012 100644 --- a/examples/edison_grove_led.go +++ b/examples/edison_grove_led.go @@ -16,7 +16,7 @@ import ( func main() { e := edison.NewAdaptor() - led := gpio.NewGroveLedDriver(e, "4") + led := gpio.NewLedDriver(e, "4") work := func() { gobot.Every(1*time.Second, func() { diff --git a/examples/edison_grove_touch.go b/examples/edison_grove_touch.go index c44281fe2..3e9696730 100644 --- a/examples/edison_grove_touch.go +++ b/examples/edison_grove_touch.go @@ -16,7 +16,7 @@ import ( func main() { e := edison.NewAdaptor() - touch := gpio.NewGroveTouchDriver(e, "2") + touch := gpio.NewButtonDriver(e, "2") work := func() { touch.On(gpio.ButtonPush, func(data interface{}) { diff --git a/examples/firmata_cat_toy.go b/examples/firmata_cat_toy.go index d1bbef2a4..e80f40c05 100644 --- a/examples/firmata_cat_toy.go +++ b/examples/firmata_cat_toy.go @@ -45,7 +45,7 @@ func main() { gobot.Every(10*time.Millisecond, func() { servo1.Move(uint8(x)) servo2.Move(uint8(z)) - fmt.Println("Current Angle: ", servo1.CurrentAngle, ",", servo2.CurrentAngle) + fmt.Println("Current Angle: ", servo1.Angle(), ",", servo2.Angle()) }) } diff --git a/examples/firmata_motor.go b/examples/firmata_motor.go index ab0d66fe4..f3abbf200 100644 --- a/examples/firmata_motor.go +++ b/examples/firmata_motor.go @@ -31,7 +31,7 @@ func main() { fadeAmount := byte(15) gobot.Every(100*time.Millisecond, func() { - motor.Speed(speed) + motor.SetSpeed(speed) speed = speed + fadeAmount if speed == 0 || speed == 255 { fadeAmount = -fadeAmount diff --git a/examples/firmata_travis.go b/examples/firmata_travis.go index f1e863b27..51862ff9b 100644 --- a/examples/firmata_travis.go +++ b/examples/firmata_travis.go @@ -80,12 +80,9 @@ func checkTravis(robot *gobot.Robot) { func main() { master := gobot.NewMaster() firmataAdaptor := firmata.NewAdaptor(os.Args[1]) - red := gpio.NewLedDriver(firmataAdaptor, "7") - red.SetName("red") - green := gpio.NewLedDriver(firmataAdaptor, "6") - green.SetName("green") - blue := gpio.NewLedDriver(firmataAdaptor, "5") - blue.SetName("blue") + red := gpio.NewLedDriver(firmataAdaptor, "7", gpio.WithName("red")) + green := gpio.NewLedDriver(firmataAdaptor, "6", gpio.WithName("green")) + blue := gpio.NewLedDriver(firmataAdaptor, "5", gpio.WithName("blue")) work := func() { checkTravis(master.Robot("travis")) diff --git a/examples/gopigo3_grove_button.go b/examples/gopigo3_grove_button.go index 36712c485..f1e376130 100644 --- a/examples/gopigo3_grove_button.go +++ b/examples/gopigo3_grove_button.go @@ -18,8 +18,8 @@ import ( func main() { raspiAdaptor := raspi.NewAdaptor() gpg3 := gopigo3.NewDriver(raspiAdaptor) - led := gpio.NewGroveLedDriver(gpg3, "AD_1_1") - button := gpio.NewGroveButtonDriver(gpg3, "AD_2_1") + led := gpio.NewLedDriver(gpg3, "AD_1_1") + button := gpio.NewButtonDriver(gpg3, "AD_2_1") work := func() { button.On(gpio.ButtonPush, func(data interface{}) { diff --git a/examples/gopigo3_led_brightness.go b/examples/gopigo3_led_brightness.go index e6d3fb54b..62a57e556 100644 --- a/examples/gopigo3_led_brightness.go +++ b/examples/gopigo3_led_brightness.go @@ -18,7 +18,7 @@ import ( func main() { raspiAdaptor := raspi.NewAdaptor() gpg3 := gopigo3.NewDriver(raspiAdaptor) - led := gpio.NewGroveLedDriver(gpg3, "AD_1_1") + led := gpio.NewLedDriver(gpg3, "AD_1_1") work := func() { brightness := uint8(0) diff --git a/examples/nanopi_button.go b/examples/nanopi_button.go new file mode 100644 index 000000000..7ea2d6da5 --- /dev/null +++ b/examples/nanopi_button.go @@ -0,0 +1,71 @@ +//go:build example +// +build example + +// Do not build by default. + +package main + +import ( + "fmt" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/adaptors" + "gobot.io/x/gobot/v2/platforms/nanopi" +) + +// PWR NanoPi: 1, 17 (+3.3V, VCC); 2, 4 (+5V, VDD); 6, 9, 14, 20 (GND) +// GPIO NanoPi: header pin 22 is input, pin 7 is normal output +// Button: the input pin is wired with a button to GND, the internal pull up resistor is used +// LED: the output pin is wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC +// Expected behavior: LED is initially on, if button is pressed and released, the state changes +func main() { + const ( + buttonPin = "22" + ledPin = "7" + ) + + a := nanopi.NewNeoAdaptor(adaptors.WithGpiosPullUp(buttonPin)) + button := gpio.NewButtonDriver(a, buttonPin, gpio.WithButtonPollInterval(50*time.Millisecond)) + led := gpio.NewLedDriver(a, ledPin) + if err := led.On(); err != nil { + fmt.Println(err) + } + + work := func() { + if err := button.On(gpio.Error, func(err interface{}) { + fmt.Println("an error occurred:", err) + }); err != nil { + panic(err) + } + + if err := button.On(gpio.ButtonPush, func(interface{}) { + fmt.Println("button pressed") + if err := led.On(); err != nil { + fmt.Println(err) + } + }); err != nil { + panic(err) + } + + if err := button.On(gpio.ButtonRelease, func(interface{}) { + fmt.Println("button released") + if err := led.Off(); err != nil { + fmt.Println(err) + } + }); err != nil { + panic(err) + } + } + + robot := gobot.NewRobot("buttonBot", + []gobot.Connection{a}, + []gobot.Device{button, led}, + work, + ) + + if err := robot.Start(); err != nil { + panic(err) + } +} diff --git a/examples/raspi_grove_pi_button.go b/examples/raspi_grove_pi_button.go index c7818fbac..88cfd6059 100644 --- a/examples/raspi_grove_pi_button.go +++ b/examples/raspi_grove_pi_button.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" @@ -18,7 +19,7 @@ import ( func main() { r := raspi.NewAdaptor() gp := i2c.NewGrovePiDriver(r) - button := gpio.NewButtonDriver(gp, "D3") + button := gpio.NewButtonDriver(gp, "D3", gpio.WithButtonPollInterval(50*time.Millisecond)) led := gpio.NewLedDriver(gp, "D2") work := func() { diff --git a/examples/raspi_hcsr04.go b/examples/raspi_hcsr04.go index 83fd3d31e..a16bf01b0 100644 --- a/examples/raspi_hcsr04.go +++ b/examples/raspi_hcsr04.go @@ -26,9 +26,13 @@ func main() { // this is mandatory for systems with defunct edge detection, although the "cdev" is used with an newer Kernel // keep in mind, that this cause more inaccurate measurements const pollEdgeDetection = true + opts := []interface{}{} + if pollEdgeDetection { + opts = append(opts, gpio.WithHCSR04UseEdgePolling()) + } a := raspi.NewAdaptor() - hcsr04 := gpio.NewHCSR04Driver(a, triggerOutput, echoInput, pollEdgeDetection) + hcsr04 := gpio.NewHCSR04Driver(a, triggerOutput, echoInput, opts...) work := func() { if pollEdgeDetection { diff --git a/examples/tinkerboard_button.go b/examples/tinkerboard_button.go new file mode 100644 index 000000000..8f7067d6b --- /dev/null +++ b/examples/tinkerboard_button.go @@ -0,0 +1,71 @@ +//go:build example +// +build example + +// Do not build by default. + +package main + +import ( + "fmt" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/tinkerboard" +) + +// Wiring +// PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) +// GPIO Tinkerboard: header pin 22 is input, pin 7 is normal output +// Button: the input pin is wired with a button to GND, an external pull up resistor is needed (e.g. 1K) +// LED: the output pin is wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC +// Expected behavior: LED is initially on, if button is pressed and released, the state changes +func main() { + const ( + buttonPin = "22" + ledPin = "7" + ) + + a := tinkerboard.NewAdaptor() + button := gpio.NewButtonDriver(a, buttonPin, gpio.WithButtonPollInterval(100*time.Millisecond)) + led := gpio.NewLedDriver(a, ledPin) + if err := led.On(); err != nil { + fmt.Println(err) + } + + work := func() { + if err := button.On(gpio.Error, func(err interface{}) { + fmt.Println("an error occurred:", err) + }); err != nil { + panic(err) + } + + if err := button.On(gpio.ButtonPush, func(interface{}) { + fmt.Println("button pressed") + if err := led.On(); err != nil { + fmt.Println(err) + } + }); err != nil { + panic(err) + } + + if err := button.On(gpio.ButtonRelease, func(interface{}) { + fmt.Println("button released") + if err := led.Off(); err != nil { + fmt.Println(err) + } + }); err != nil { + panic(err) + } + } + + robot := gobot.NewRobot("buttonBot", + []gobot.Connection{a}, + []gobot.Device{button, led}, + work, + ) + + if err := robot.Start(); err != nil { + panic(err) + } +} diff --git a/examples/tinkerboard_hcsr04.go b/examples/tinkerboard_hcsr04.go index 9c18140be..f7a89f941 100644 --- a/examples/tinkerboard_hcsr04.go +++ b/examples/tinkerboard_hcsr04.go @@ -30,9 +30,13 @@ func main() { // this is mandatory for systems with defunct edge detection, although the "cdev" is used with an newer Kernel // keep in mind, that this cause more inaccurate measurements const pollEdgeDetection = true + opts := []interface{}{} + if pollEdgeDetection { + opts = append(opts, gpio.WithHCSR04UseEdgePolling()) + } a := tinkerboard.NewAdaptor() - hcsr04 := gpio.NewHCSR04Driver(a, triggerOutput, echoInput, pollEdgeDetection) + hcsr04 := gpio.NewHCSR04Driver(a, triggerOutput, echoInput, opts...) work := func() { if pollEdgeDetection { diff --git a/examples/tinkerboard_motor.go b/examples/tinkerboard_motor.go new file mode 100644 index 000000000..754895446 --- /dev/null +++ b/examples/tinkerboard_motor.go @@ -0,0 +1,66 @@ +//go:build example +// +build example + +// Do not build by default. + +package main + +import ( + "fmt" + "log" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/tinkerboard" +) + +// Wiring +// PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) +// PWM Tinkerboard: header pin 33 (PWM2) or pin 32 (PWM3) +// Please decouple the PWM pin with an amplifier, e.g. a simple MOSFET (IRLZ34N, IRF530 etc.), a half H-bridge or +// just use a LED for the first tests. +func main() { + adaptor := tinkerboard.NewAdaptor() + motor := gpio.NewMotorDriver(adaptor, "32", gpio.WithMotorAnalog()) // gpio.WithMotorAnalog() is optional here + + work := func() { + fmt.Println("first try full speed for 5 seconds...") + if err := motor.On(); err != nil { + log.Println(err) + } + + time.Sleep(5 * time.Second) + + fmt.Println("second switch off for 5 seconds...") + if err := motor.Off(); err != nil { + log.Println(err) + } + + time.Sleep(5 * time.Second) + + fmt.Println("finally fade in and out forever...") + speed := byte(0) + fadeAmount := byte(15) + + gobot.Every(100*time.Millisecond, func() { + if err := motor.SetSpeed(speed); err != nil { + log.Println(err) + } + speed = speed + fadeAmount + if speed == 0 || speed == 255 { + fadeAmount = -fadeAmount + } + }) + } + + robot := gobot.NewRobot("motorBot", + []gobot.Connection{adaptor}, + []gobot.Device{motor}, + work, + ) + + if err := robot.Start(); err != nil { + panic(err) + } +} diff --git a/examples/tinkerboard_servo.go b/examples/tinkerboard_servo.go new file mode 100644 index 000000000..5be3fce63 --- /dev/null +++ b/examples/tinkerboard_servo.go @@ -0,0 +1,90 @@ +//go:build example +// +build example + +// Do not build by default. + +package main + +import ( + "fmt" + "log" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/tinkerboard" +) + +// Wiring +// PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) +// PWM Tinkerboard: header pin 33 (PWM2) or pin 32 (PWM3) +func main() { + const ( + pwmPin = "32" + wait = 3 * time.Second + + fiftyHzNanos = 20 * 1000 * 1000 // 50Hz = 0.02 sec = 20 ms + ) + adaptor := tinkerboard.NewAdaptor() + servo := gpio.NewServoDriver(adaptor, pwmPin) + + work := func() { + // usually a frequency of 50Hz is used for servos + if err := adaptor.SetPeriod(pwmPin, fiftyHzNanos); err != nil { + log.Println(err) + } + + fmt.Printf("first move to minimal position for %s...\n", wait) + if err := servo.ToMin(); err != nil { + log.Println(err) + } + + time.Sleep(wait) + + fmt.Printf("second move to center position for %s...\n", wait) + if err := servo.ToCenter(); err != nil { + log.Println(err) + } + + time.Sleep(wait) + + fmt.Printf("third move to maximal position for %s...\n", wait) + if err := servo.ToMax(); err != nil { + log.Println(err) + } + + time.Sleep(wait) + + fmt.Println("finally move 0-180° and back forever...") + angle := 0 + fadeAmount := 45 + + gobot.Every(time.Second, func() { + if err := servo.Move(byte(angle)); err != nil { + log.Println(err) + } + angle = angle + fadeAmount + if angle < 0 || angle > 180 { + if angle < 0 { + angle = 0 + } + if angle > 180 { + angle = 180 + } + // change direction and recalculate + fadeAmount = -fadeAmount + angle = angle + fadeAmount + } + }) + } + + robot := gobot.NewRobot("motorBot", + []gobot.Connection{adaptor}, + []gobot.Device{servo}, + work, + ) + + if err := robot.Start(); err != nil { + panic(err) + } +} diff --git a/platforms/adaptors/pwmpinsadaptor.go b/platforms/adaptors/pwmpinsadaptor.go index 4d0834adc..962c7dd4b 100644 --- a/platforms/adaptors/pwmpinsadaptor.go +++ b/platforms/adaptors/pwmpinsadaptor.go @@ -2,6 +2,7 @@ package adaptors import ( "fmt" + "log" "sync" multierror "github.com/hashicorp/go-multierror" @@ -110,7 +111,7 @@ func (a *PWMPinsAdaptor) Finalize() error { return err } -// PwmWrite writes a PWM signal to the specified pin. +// PwmWrite writes a PWM signal to the specified pin. The given value is between 0 and 255. func (a *PWMPinsAdaptor) PwmWrite(id string, val byte) error { a.mutex.Lock() defer a.mutex.Unlock() @@ -127,7 +128,7 @@ func (a *PWMPinsAdaptor) PwmWrite(id string, val byte) error { return pin.SetDutyCycle(uint32(float64(period) * duty)) } -// ServoWrite writes a servo signal to the specified pin. +// ServoWrite writes a servo signal to the specified pin. The given angle is between 0 and 180°. func (a *PWMPinsAdaptor) ServoWrite(id string, angle byte) error { a.mutex.Lock() defer a.mutex.Unlock() @@ -136,16 +137,43 @@ func (a *PWMPinsAdaptor) ServoWrite(id string, angle byte) error { if err != nil { return err } - period, err := pin.Period() + period, err := pin.Period() // nanoseconds if err != nil { return err } - // 0.5 ms => -90 + // 50Hz = 0.02 sec = 20 ms + const fiftyHzNanos = 20 * 1000 * 1000 + + if period != fiftyHzNanos { + log.Printf("WARNING: the PWM acts with a period of %d, but should use %d (50Hz) for servos\n", period, fiftyHzNanos) + } + + // TODO: implement an option to give another min-max range + // TODO: allow usage of adaptors.WithPWMPinDefaultPeriod() from main.go + // + // for some older servos, this can happen + // 0.5 ms => -90 (1/40 part of period at 50Hz) // 1.5 ms => 0 - // 2.0 ms => 90 - minDuty := 100 * 0.0005 * float64(period) - maxDuty := 100 * 0.0020 * float64(period) + // 2.0 ms => 90 (1/10 part of period at 50Hz) + + // some servos have profiles below/above the 0-180° value + // SG90: 1/90: after position a small smooth movement is done + // SG90: >1/100: endless movement clock wise + // SG90: <1/8: endless movement counter clock wise + + // usually for the most servos (at 50Hz) for 90° + // 1.0 ms => 0 (1/20 part of period at 50Hz) + // 1.5 ms => 45 + // 2.0 ms => 90 (1/10 part of period at 50Hz) + + // usually for the most servos (at 50Hz) for 180° (SG90, AD002) + // 0.5 ms => 0 (1/40 part of period at 50Hz) + // 1.5 ms => 90 + // 2.5 ms => 180 (1/8 part of period at 50Hz) + + minDuty := float64(period) / 40 + maxDuty := float64(period) / 8 duty := uint32(gobot.ToScale(gobot.FromScale(float64(angle), 0, 180), minDuty, maxDuty)) return pin.SetDutyCycle(duty) } diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index 0770695b6..ad0397be5 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -206,13 +206,13 @@ func TestServoWrite(t *testing.T) { assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) assert.Equal(t, fmt.Sprintf("%d", a.periodDefault), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here - assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "250000", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) require.NoError(t, err) err = a.ServoWrite("33", 180) require.NoError(t, err) - assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "1250000", fs.Files[pwmDutyCyclePath].Contents) err = a.ServoWrite("notexist", 42) require.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index 1f5641ba9..879999e3b 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -39,51 +39,53 @@ func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system. return a, fs } +const ( + pwmDir = "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/" //nolint:gosec // false positive + pwmChip0Dir = pwmDir + "pwmchip0/" + pwmChip0ExportPath = pwmChip0Dir + "export" + pwmChip0UnexportPath = pwmChip0Dir + "unexport" + pwmChip0Pwm0Dir = pwmChip0Dir + "pwm0/" + pwm0EnablePath = pwmChip0Pwm0Dir + "enable" + pwm0PeriodPath = pwmChip0Pwm0Dir + "period" + pwm0DutyCyclePath = pwmChip0Pwm0Dir + "duty_cycle" + pwm0PolarityPath = pwmChip0Pwm0Dir + "polarity" + + pwmChip0Pwm1Dir = pwmChip0Dir + "pwm1/" + pwm1EnablePath = pwmChip0Pwm1Dir + "enable" + pwm1PeriodPath = pwmChip0Pwm1Dir + "period" + pwm1DutyCyclePath = pwmChip0Pwm1Dir + "duty_cycle" + pwm1PolarityPath = pwmChip0Pwm1Dir + "polarity" +) + func TestPWM(t *testing.T) { mockPaths := []string{ "/sys/devices/platform/ocp/ocp:P9_22_pinmux/state", "/sys/devices/platform/ocp/ocp:P9_21_pinmux/state", "/sys/bus/iio/devices/iio:device0/in_voltage1_raw", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/export", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/unexport", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm0/enable", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm0/period", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm0/duty_cycle", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm0/polarity", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/enable", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/period", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle", - "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/polarity", + pwmChip0ExportPath, + pwmChip0UnexportPath, + pwm0EnablePath, + pwm0PeriodPath, + pwm0DutyCyclePath, + pwm0PolarityPath, + pwm1EnablePath, + pwm1PeriodPath, + pwm1DutyCyclePath, + pwm1PolarityPath, } a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) - fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents = "0" - fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/period"].Contents = "0" + fs.Files[pwm1DutyCyclePath].Contents = "0" + fs.Files[pwm1PeriodPath].Contents = "0" require.ErrorContains(t, a.PwmWrite("P9_99", 175), "'P9_99' is not a valid id for a PWM pin") _ = a.PwmWrite("P9_21", 175) - assert.Equal( - t, - "500000", - fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/period"].Contents, - ) - assert.Equal( - t, - "343137", - fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents, - ) + assert.Equal(t, "500000", fs.Files[pwm1PeriodPath].Contents) + assert.Equal(t, "343137", fs.Files[pwm1DutyCyclePath].Contents) _ = a.ServoWrite("P9_21", 100) - assert.Equal( - t, - "500000", - fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/period"].Contents, - ) - assert.Equal( - t, - "66666", - fs.Files["/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/pwm1/duty_cycle"].Contents, - ) + assert.Equal(t, "500000", fs.Files[pwm1PeriodPath].Contents) + assert.Equal(t, "40277", fs.Files[pwm1DutyCyclePath].Contents) require.NoError(t, a.Finalize()) } diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index d319119d6..0a3d275ad 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -142,17 +142,20 @@ func TestPWM(t *testing.T) { assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault assert.Equal(t, "normal", fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents) + // prepare 50Hz for servos + const fiftyHzNano = "20000000" + fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = fiftyHzNano err = a.ServoWrite("PWM0", 0) require.NoError(t, err) assert.Equal(t, "500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) - assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) + assert.Equal(t, fiftyHzNano, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) err = a.ServoWrite("PWM0", 180) require.NoError(t, err) - assert.Equal(t, "2000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) - assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault + assert.Equal(t, "2500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) + assert.Equal(t, fiftyHzNano, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault require.NoError(t, a.Finalize()) } diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index b145d6e3b..8c44ce240 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -23,13 +23,15 @@ const ( const ( pwmDir = "/sys/devices/platform/soc/1c21400.pwm/pwm/pwmchip0/" //nolint:gosec // false positive - pwmPwmDir = pwmDir + "pwm0/" pwmExportPath = pwmDir + "export" pwmUnexportPath = pwmDir + "unexport" + pwmPwmDir = pwmDir + "pwm0/" pwmEnablePath = pwmPwmDir + "enable" pwmPeriodPath = pwmPwmDir + "period" pwmDutyCyclePath = pwmPwmDir + "duty_cycle" pwmPolarityPath = pwmPwmDir + "polarity" + + fiftyHzNano = "20000000" ) var pwmMockPaths = []string{ @@ -154,6 +156,8 @@ func TestPwmWrite(t *testing.T) { assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) + // prepare 50Hz for servos + fs.Files[pwmPeriodPath].Contents = fiftyHzNano err = a.ServoWrite("PWM", 0) require.NoError(t, err) @@ -162,7 +166,7 @@ func TestPwmWrite(t *testing.T) { err = a.ServoWrite("PWM", 180) require.NoError(t, err) - assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "2500000", fs.Files[pwmDutyCyclePath].Contents) require.NoError(t, a.Finalize()) } diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 25d1ab778..71b95b39d 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -154,6 +154,8 @@ func TestPwmWrite(t *testing.T) { assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) + // prepare 50Hz for servos + fs.Files[pwmPeriodPath].Contents = strconv.Itoa(20000000) err = a.ServoWrite("33", 0) require.NoError(t, err) @@ -162,7 +164,7 @@ func TestPwmWrite(t *testing.T) { err = a.ServoWrite("33", 180) require.NoError(t, err) - assert.Equal(t, "2000000", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "2500000", fs.Files[pwmDutyCyclePath].Contents) require.NoError(t, a.Finalize()) } diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index 0c8c0f348..610af5b2c 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -28,13 +28,25 @@ var ( _ spi.Connector = (*Adaptor)(nil) ) +const ( + pwmDir = "/sys/class/pwm/pwmchip0/" //nolint:gosec // false positive + pwmExportPath = pwmDir + "export" + pwmUnexportPath = pwmDir + "unexport" + pwmEnablePath = pwmDir + "pwm0/enable" + pwmDutyCyclePath = pwmDir + "pwm0/duty_cycle" + pwmPeriodPath = pwmDir + "pwm0/period" + pwmPolarityPath = pwmDir + "pwm0/polarity" + + fiftyHzNano = "20000000" +) + var pwmMockPaths = []string{ - "/sys/class/pwm/pwmchip0/export", - "/sys/class/pwm/pwmchip0/unexport", - "/sys/class/pwm/pwmchip0/pwm0/enable", - "/sys/class/pwm/pwmchip0/pwm0/period", - "/sys/class/pwm/pwmchip0/pwm0/duty_cycle", - "/sys/class/pwm/pwmchip0/pwm0/polarity", + pwmExportPath, + pwmUnexportPath, + pwmEnablePath, + pwmPeriodPath, + pwmDutyCyclePath, + pwmPolarityPath, } var gpioMockPaths = []string{ @@ -85,29 +97,31 @@ func TestDigitalIO(t *testing.T) { func TestPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) - fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" - fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" + fs.Files[pwmDutyCyclePath].Contents = "0" + fs.Files[pwmPeriodPath].Contents = "0" err := a.PwmWrite("32", 100) require.NoError(t, err) - assert.Equal(t, "0", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) - assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents) - assert.Equal(t, "3921568", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) - assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault - assert.Equal(t, "normal", fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents) + assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) + assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) + assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "10000000", fs.Files[pwmPeriodPath].Contents) // pwmPeriodDefault + assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) + // prepare 50Hz for servos + fs.Files[pwmPeriodPath].Contents = fiftyHzNano err = a.ServoWrite("32", 0) require.NoError(t, err) - assert.Equal(t, "500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) - assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) + assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, fiftyHzNano, fs.Files[pwmPeriodPath].Contents) err = a.ServoWrite("32", 180) require.NoError(t, err) - assert.Equal(t, "2000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) - assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) + assert.Equal(t, "2500000", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, fiftyHzNano, fs.Files[pwmPeriodPath].Contents) require.NoError(t, a.Finalize()) } @@ -125,8 +139,8 @@ func TestFinalizeErrorAfterGPIO(t *testing.T) { func TestFinalizeErrorAfterPWM(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) - fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" - fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" + fs.Files[pwmDutyCyclePath].Contents = "0" + fs.Files[pwmPeriodPath].Contents = "0" require.NoError(t, a.PwmWrite("32", 1)) diff --git a/system/pwmpin_sysfs.go b/system/pwmpin_sysfs.go index b31a9484a..859110498 100644 --- a/system/pwmpin_sysfs.go +++ b/system/pwmpin_sysfs.go @@ -133,7 +133,7 @@ func (p *pwmPinSysFs) SetPolarity(normal bool) error { return nil } -// Period returns the current period +// Period returns the current period in nanoseconds func (p *pwmPinSysFs) Period() (uint32, error) { val, err := p.sfa.readInteger(p.pwmPeriodPath()) if err != nil { From 8ae46677015120b945a10bebe3129816a3fc1225 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 5 Dec 2023 20:26:28 +0100 Subject: [PATCH 35/57] adaptors(pwm): introduce scale option for servo (#1046) --- examples/tinkerboard_servo.go | 16 +- platforms/adaptors/digitalpinsadaptor.go | 269 +++--------------- platforms/adaptors/digitalpinsadaptor_test.go | 108 ------- .../adaptors/digitalpinsadaptoroptions.go | 157 ++++++++++ .../digitalpinsadaptoroptions_test.go | 120 ++++++++ platforms/adaptors/options.go | 7 - platforms/adaptors/pwmpinsadaptor.go | 206 ++++++++------ platforms/adaptors/pwmpinsadaptor_test.go | 57 +--- platforms/adaptors/pwmpinsadaptoroptions.go | 118 ++++++++ .../adaptors/pwmpinsadaptoroptions_test.go | 148 ++++++++++ platforms/beaglebone/beaglebone_adaptor.go | 108 ++++--- .../beaglebone/beaglebone_adaptor_test.go | 134 ++++++--- platforms/beaglebone/pocketbeagle_adaptor.go | 9 +- platforms/chip/chip_adaptor.go | 77 +++-- platforms/chip/chip_adaptor_test.go | 46 +-- platforms/dragonboard/dragonboard_adaptor.go | 2 +- platforms/intel-iot/edison/edison_adaptor.go | 201 +++++++------ .../intel-iot/edison/edison_adaptor_test.go | 17 +- platforms/intel-iot/joule/joule_adaptor.go | 65 +++-- platforms/jetson/jetson_adaptor.go | 2 +- platforms/nanopi/nanopi_adaptor.go | 89 +++--- platforms/nanopi/nanopi_adaptor_test.go | 38 ++- platforms/raspi/raspi_adaptor.go | 2 +- platforms/rockpi/rockpi_adaptor.go | 2 +- platforms/tinkerboard/adaptor.go | 94 +++--- platforms/tinkerboard/adaptor_test.go | 80 ++++-- platforms/upboard/up2/adaptor.go | 86 +++--- platforms/upboard/up2/adaptor_test.go | 40 ++- 28 files changed, 1395 insertions(+), 903 deletions(-) create mode 100644 platforms/adaptors/digitalpinsadaptoroptions.go create mode 100644 platforms/adaptors/digitalpinsadaptoroptions_test.go delete mode 100644 platforms/adaptors/options.go create mode 100644 platforms/adaptors/pwmpinsadaptoroptions.go create mode 100644 platforms/adaptors/pwmpinsadaptoroptions_test.go diff --git a/examples/tinkerboard_servo.go b/examples/tinkerboard_servo.go index 5be3fce63..4e81503b7 100644 --- a/examples/tinkerboard_servo.go +++ b/examples/tinkerboard_servo.go @@ -12,6 +12,7 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/platforms/tinkerboard" ) @@ -25,15 +26,16 @@ func main() { fiftyHzNanos = 20 * 1000 * 1000 // 50Hz = 0.02 sec = 20 ms ) - adaptor := tinkerboard.NewAdaptor() + // usually a frequency of 50Hz is used for servos, most servos have 0.5 ms..2.5 ms for 0-180°, + // however the mapping can be changed with options: + adaptor := tinkerboard.NewAdaptor( + adaptors.WithPWMDefaultPeriodForPin(pwmPin, fiftyHzNanos), + adaptors.WithPWMServoDutyCycleRangeForPin(pwmPin, time.Millisecond, 2*time.Millisecond), + adaptors.WithPWMServoAngleRangeForPin(pwmPin, 0, 270), + ) servo := gpio.NewServoDriver(adaptor, pwmPin) work := func() { - // usually a frequency of 50Hz is used for servos - if err := adaptor.SetPeriod(pwmPin, fiftyHzNanos); err != nil { - log.Println(err) - } - fmt.Printf("first move to minimal position for %s...\n", wait) if err := servo.ToMin(); err != nil { log.Println(err) @@ -55,7 +57,7 @@ func main() { time.Sleep(wait) - fmt.Println("finally move 0-180° and back forever...") + fmt.Println("finally move 0-180° (or what your servo do for the new mapping) and back forever...") angle := 0 fadeAmount := 45 diff --git a/platforms/adaptors/digitalpinsadaptor.go b/platforms/adaptors/digitalpinsadaptor.go index e62d91c70..d60aa9be6 100644 --- a/platforms/adaptors/digitalpinsadaptor.go +++ b/platforms/adaptors/digitalpinsadaptor.go @@ -16,25 +16,6 @@ type ( digitalPinInitializer func(gobot.DigitalPinner) error ) -type digitalPinsOptioner interface { - setDigitalPinInitializer(initializer digitalPinInitializer) - setDigitalPinsForSystemGpiod() - setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string) - prepareDigitalPinsActiveLow(pin string, otherPins ...string) - prepareDigitalPinsPullDown(pin string, otherPins ...string) - prepareDigitalPinsPullUp(pin string, otherPins ...string) - prepareDigitalPinsOpenDrain(pin string, otherPins ...string) - prepareDigitalPinsOpenSource(pin string, otherPins ...string) - prepareDigitalPinDebounce(pin string, period time.Duration) - prepareDigitalPinEventOnFallingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, - detectedEdge string, seqno uint32, lseqno uint32)) - prepareDigitalPinEventOnRisingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, - detectedEdge string, seqno uint32, lseqno uint32)) - prepareDigitalPinEventOnBothEdges(pin string, handler func(lineOffset int, timestamp time.Duration, - detectedEdge string, seqno uint32, lseqno uint32)) - prepareDigitalPinPollForEdgeDetection(pin string, pollInterval time.Duration, pollQuitChan chan struct{}) -} - // DigitalPinsAdaptor is a adaptor for digital pins, normally used for composition in platforms. type DigitalPinsAdaptor struct { sys *system.Accesser @@ -53,7 +34,7 @@ type DigitalPinsAdaptor struct { func NewDigitalPinsAdaptor( sys *system.Accesser, t digitalPinTranslator, - options ...func(Optioner), + options ...func(DigitalPinsOptioner), ) *DigitalPinsAdaptor { a := &DigitalPinsAdaptor{ sys: sys, @@ -67,99 +48,72 @@ func NewDigitalPinsAdaptor( } // WithDigitalPinInitializer can be used to substitute the default initializer. -func WithDigitalPinInitializer(pc digitalPinInitializer) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.setDigitalPinInitializer(pc) - } +func WithDigitalPinInitializer(pc digitalPinInitializer) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.setDigitalPinInitializer(pc) } } // WithGpiodAccess can be used to change the default sysfs implementation to the character device Kernel ABI. // The access is provided by the gpiod package. -func WithGpiodAccess() func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.setDigitalPinsForSystemGpiod() - } +func WithGpiodAccess() func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.setDigitalPinsForSystemGpiod() } } // WithSpiGpioAccess can be used to switch the default SPI implementation to GPIO usage. -func WithSpiGpioAccess(sclkPin, nssPin, mosiPin, misoPin string) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin) - } +func WithSpiGpioAccess(sclkPin, nssPin, mosiPin, misoPin string) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin) } } // WithGpiosActiveLow prepares the given pins for inverse reaction on next initialize. // This is working for inputs and outputs. -func WithGpiosActiveLow(pin string, otherPins ...string) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinsActiveLow(pin, otherPins...) - } +func WithGpiosActiveLow(pin string, otherPins ...string) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinsActiveLow(pin, otherPins...) } } // WithGpiosPullDown prepares the given pins to be pulled down (high impedance to GND) on next initialize. // This is working for inputs and outputs since Kernel 5.5, but will be ignored with sysfs ABI. -func WithGpiosPullDown(pin string, otherPins ...string) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinsPullDown(pin, otherPins...) - } +func WithGpiosPullDown(pin string, otherPins ...string) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinsPullDown(pin, otherPins...) } } // WithGpiosPullUp prepares the given pins to be pulled up (high impedance to VDD) on next initialize. // This is working for inputs and outputs since Kernel 5.5, but will be ignored with sysfs ABI. -func WithGpiosPullUp(pin string, otherPins ...string) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinsPullUp(pin, otherPins...) - } +func WithGpiosPullUp(pin string, otherPins ...string) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinsPullUp(pin, otherPins...) } } // WithGpiosOpenDrain prepares the given output pins to be driven with open drain/collector on next initialize. // This will be ignored for inputs or with sysfs ABI. -func WithGpiosOpenDrain(pin string, otherPins ...string) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinsOpenDrain(pin, otherPins...) - } +func WithGpiosOpenDrain(pin string, otherPins ...string) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinsOpenDrain(pin, otherPins...) } } // WithGpiosOpenSource prepares the given output pins to be driven with open source/emitter on next initialize. // This will be ignored for inputs or with sysfs ABI. -func WithGpiosOpenSource(pin string, otherPins ...string) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinsOpenSource(pin, otherPins...) - } +func WithGpiosOpenSource(pin string, otherPins ...string) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinsOpenSource(pin, otherPins...) } } // WithGpioDebounce prepares the given input pin to be debounced on next initialize. // This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI. -func WithGpioDebounce(pin string, period time.Duration) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinDebounce(pin, period) - } +func WithGpioDebounce(pin string, period time.Duration) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinDebounce(pin, period) } } @@ -167,12 +121,9 @@ func WithGpioDebounce(pin string, period time.Duration) func(Optioner) { // This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI. func WithGpioEventOnFallingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, lseqno uint32), -) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinEventOnFallingEdge(pin, handler) - } +) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinEventOnFallingEdge(pin, handler) } } @@ -180,12 +131,9 @@ func WithGpioEventOnFallingEdge(pin string, handler func(lineOffset int, timesta // This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI. func WithGpioEventOnRisingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, lseqno uint32), -) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinEventOnRisingEdge(pin, handler) - } +) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinEventOnRisingEdge(pin, handler) } } @@ -193,23 +141,21 @@ func WithGpioEventOnRisingEdge(pin string, handler func(lineOffset int, timestam // This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI. func WithGpioEventOnBothEdges(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, lseqno uint32), -) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinEventOnBothEdges(pin, handler) - } +) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinEventOnBothEdges(pin, handler) } } // WithGpioPollForEdgeDetection prepares the given input pin to use a discrete input pin polling function together with // edge detection. -func WithGpioPollForEdgeDetection(pin string, pollInterval time.Duration, pollQuitChan chan struct{}) func(Optioner) { - return func(o Optioner) { - a, ok := o.(digitalPinsOptioner) - if ok { - a.prepareDigitalPinPollForEdgeDetection(pin, pollInterval, pollQuitChan) - } +func WithGpioPollForEdgeDetection( + pin string, + pollInterval time.Duration, + pollQuitChan chan struct{}, +) func(DigitalPinsOptioner) { + return func(o DigitalPinsOptioner) { + o.prepareDigitalPinPollForEdgeDetection(pin, pollInterval, pollQuitChan) } } @@ -273,133 +219,6 @@ func (a *DigitalPinsAdaptor) DigitalWrite(id string, val byte) error { return pin.Write(int(val)) } -func (a *DigitalPinsAdaptor) setDigitalPinInitializer(pinInit digitalPinInitializer) { - a.initialize = pinInit -} - -func (a *DigitalPinsAdaptor) setDigitalPinsForSystemGpiod() { - system.WithDigitalPinGpiodAccess()(a.sys) -} - -func (a *DigitalPinsAdaptor) setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string) { - system.WithSpiGpioAccess(a, sclkPin, nssPin, mosiPin, misoPin)(a.sys) -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinsActiveLow(id string, otherIDs ...string) { - ids := []string{id} - ids = append(ids, otherIDs...) - - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - for _, i := range ids { - a.pinOptions[i] = append(a.pinOptions[i], system.WithPinActiveLow()) - } -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinsPullDown(id string, otherIDs ...string) { - ids := []string{id} - ids = append(ids, otherIDs...) - - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - for _, i := range ids { - a.pinOptions[i] = append(a.pinOptions[i], system.WithPinPullDown()) - } -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinsPullUp(id string, otherIDs ...string) { - ids := []string{id} - ids = append(ids, otherIDs...) - - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - for _, i := range ids { - a.pinOptions[i] = append(a.pinOptions[i], system.WithPinPullUp()) - } -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinsOpenDrain(id string, otherIDs ...string) { - ids := []string{id} - ids = append(ids, otherIDs...) - - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - for _, i := range ids { - a.pinOptions[i] = append(a.pinOptions[i], system.WithPinOpenDrain()) - } -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinsOpenSource(id string, otherIDs ...string) { - ids := []string{id} - ids = append(ids, otherIDs...) - - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - for _, i := range ids { - a.pinOptions[i] = append(a.pinOptions[i], system.WithPinOpenSource()) - } -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinDebounce(id string, period time.Duration) { - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - a.pinOptions[id] = append(a.pinOptions[id], system.WithPinDebounce(period)) -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnFallingEdge(id string, handler func(int, time.Duration, string, - uint32, uint32), -) { - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnFallingEdge(handler)) -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnRisingEdge(id string, handler func(int, time.Duration, string, - uint32, uint32), -) { - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnRisingEdge(handler)) -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnBothEdges(id string, handler func(int, time.Duration, string, - uint32, uint32), -) { - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnBothEdges(handler)) -} - -func (a *DigitalPinsAdaptor) prepareDigitalPinPollForEdgeDetection( - id string, - pollInterval time.Duration, - pollQuitChan chan struct{}, -) { - if a.pinOptions == nil { - a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) - } - - a.pinOptions[id] = append(a.pinOptions[id], system.WithPinPollForEdgeDetection(pollInterval, pollQuitChan)) -} - func (a *DigitalPinsAdaptor) digitalPin( id string, opts ...func(gobot.DigitalPinOptioner) bool, diff --git a/platforms/adaptors/digitalpinsadaptor_test.go b/platforms/adaptors/digitalpinsadaptor_test.go index ae0785df8..55e16393b 100644 --- a/platforms/adaptors/digitalpinsadaptor_test.go +++ b/platforms/adaptors/digitalpinsadaptor_test.go @@ -7,7 +7,6 @@ import ( "strconv" "sync" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -43,18 +42,6 @@ func testDigitalPinTranslator(pin string) (string, int, error) { return "", line, err } -func TestDigitalPinsWithGpiosActiveLow(t *testing.T) { - // This is a general test, that options are applied in constructor. Further tests for options - // can also be done by call of "WithOption(val)(d)". - // arrange - translate := func(pin string) (chip string, line int, err error) { return } - sys := system.NewAccesser() - // act - a := NewDigitalPinsAdaptor(sys, translate, WithGpiosActiveLow("1", "12", "33")) - // assert - assert.Len(t, a.pinOptions, 3) -} - func TestDigitalPinsConnect(t *testing.T) { translate := func(pin string) (chip string, line int, err error) { return } sys := system.NewAccesser() @@ -170,96 +157,6 @@ func TestDigitalRead(t *testing.T) { require.ErrorContains(t, err, "write error") } -func TestDigitalReadWithGpiosActiveLow(t *testing.T) { - mockedPaths := []string{ - "/sys/class/gpio/export", - "/sys/class/gpio/unexport", - "/sys/class/gpio/gpio25/value", - "/sys/class/gpio/gpio25/direction", - "/sys/class/gpio/gpio25/active_low", - "/sys/class/gpio/gpio26/value", - "/sys/class/gpio/gpio26/direction", - } - a, fs := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) - fs.Files["/sys/class/gpio/gpio25/value"].Contents = "1" - fs.Files["/sys/class/gpio/gpio25/active_low"].Contents = "5" - fs.Files["/sys/class/gpio/gpio26/value"].Contents = "0" - WithGpiosActiveLow("14")(a) - // creates a new pin without inverted logic - if _, err := a.DigitalRead("15"); err != nil { - panic(err) - } - fs.Add("/sys/class/gpio/gpio26/active_low") - fs.Files["/sys/class/gpio/gpio26/active_low"].Contents = "6" - WithGpiosActiveLow("15")(a) - // act - got1, err1 := a.DigitalRead("14") // for a new pin - got2, err2 := a.DigitalRead("15") // for an existing pin (calls ApplyOptions()) - // assert - require.NoError(t, err1) - require.NoError(t, err2) - assert.Equal(t, 1, got1) // there is no mechanism to negate mocked values - assert.Equal(t, 0, got2) - assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio25/active_low"].Contents) - assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio26/active_low"].Contents) -} - -func TestDigitalWrite(t *testing.T) { - // arrange - mockedPaths := []string{ - "/sys/class/gpio/export", - "/sys/class/gpio/unexport", - "/sys/class/gpio/gpio18/value", - "/sys/class/gpio/gpio18/direction", - } - a, fs := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) - - // assert write correct value without error and just ignore unsupported options - WithGpiosPullUp("7")(a) - WithGpiosOpenDrain("7")(a) - WithGpioEventOnFallingEdge("7", gpioEventHandler)(a) - WithGpioPollForEdgeDetection("7", 0, nil)(a) - err := a.DigitalWrite("7", 1) - require.NoError(t, err) - assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio18/value"].Contents) - - // assert second write to same pin without error and just ignore unsupported options - WithGpiosPullDown("7")(a) - WithGpiosOpenSource("7")(a) - WithGpioDebounce("7", 2*time.Second)(a) - WithGpioEventOnRisingEdge("7", gpioEventHandler)(a) - err = a.DigitalWrite("7", 1) - require.NoError(t, err) - - // assert error on bad id - require.ErrorContains(t, a.DigitalWrite("notexist", 1), "not a valid pin") - - // assert error bubbling - fs.WithWriteError = true - err = a.DigitalWrite("7", 0) - require.ErrorContains(t, err, "write error") -} - -func TestDigitalWriteWithGpiosActiveLow(t *testing.T) { - // arrange - mockedPaths := []string{ - "/sys/class/gpio/export", - "/sys/class/gpio/unexport", - "/sys/class/gpio/gpio19/value", - "/sys/class/gpio/gpio19/direction", - "/sys/class/gpio/gpio19/active_low", - } - a, fs := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) - fs.Files["/sys/class/gpio/gpio19/active_low"].Contents = "5" - WithGpiosActiveLow("8")(a) - // act - err := a.DigitalWrite("8", 2) - // assert - require.NoError(t, err) - assert.Equal(t, "2", fs.Files["/sys/class/gpio/gpio19/value"].Contents) - assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio19/active_low"].Contents) -} - func TestDigitalPinConcurrency(t *testing.T) { oldProcs := runtime.GOMAXPROCS(0) runtime.GOMAXPROCS(8) @@ -286,8 +183,3 @@ func TestDigitalPinConcurrency(t *testing.T) { wg.Wait() } } - -func gpioEventHandler(o int, t time.Duration, et string, sn uint32, lsn uint32) { - // the handler should never execute, because used in outputs and not supported by sysfs - panic(fmt.Sprintf("event handler was called (%d, %d) unexpected for line %d with '%s' at %s!", sn, lsn, o, t, et)) -} diff --git a/platforms/adaptors/digitalpinsadaptoroptions.go b/platforms/adaptors/digitalpinsadaptoroptions.go new file mode 100644 index 000000000..6aefbf700 --- /dev/null +++ b/platforms/adaptors/digitalpinsadaptoroptions.go @@ -0,0 +1,157 @@ +package adaptors + +import ( + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/system" +) + +// DigitalPinsOptioner is the interface for digital adaptors options. This provides the possibility for change the +// platform behavior by the user when creating the platform, e.g. by "NewAdaptor()". +// TODO: change to applier-architecture, see options of pwmpinsadaptor.go +type DigitalPinsOptioner interface { + setDigitalPinInitializer(initializer digitalPinInitializer) + setDigitalPinsForSystemGpiod() + setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string) + prepareDigitalPinsActiveLow(pin string, otherPins ...string) + prepareDigitalPinsPullDown(pin string, otherPins ...string) + prepareDigitalPinsPullUp(pin string, otherPins ...string) + prepareDigitalPinsOpenDrain(pin string, otherPins ...string) + prepareDigitalPinsOpenSource(pin string, otherPins ...string) + prepareDigitalPinDebounce(pin string, period time.Duration) + prepareDigitalPinEventOnFallingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, + detectedEdge string, seqno uint32, lseqno uint32)) + prepareDigitalPinEventOnRisingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, + detectedEdge string, seqno uint32, lseqno uint32)) + prepareDigitalPinEventOnBothEdges(pin string, handler func(lineOffset int, timestamp time.Duration, + detectedEdge string, seqno uint32, lseqno uint32)) + prepareDigitalPinPollForEdgeDetection(pin string, pollInterval time.Duration, pollQuitChan chan struct{}) +} + +func (a *DigitalPinsAdaptor) setDigitalPinInitializer(pinInit digitalPinInitializer) { + a.initialize = pinInit +} + +func (a *DigitalPinsAdaptor) setDigitalPinsForSystemGpiod() { + system.WithDigitalPinGpiodAccess()(a.sys) +} + +func (a *DigitalPinsAdaptor) setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string) { + system.WithSpiGpioAccess(a, sclkPin, nssPin, mosiPin, misoPin)(a.sys) +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinsActiveLow(id string, otherIDs ...string) { + ids := []string{id} + ids = append(ids, otherIDs...) + + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + for _, i := range ids { + a.pinOptions[i] = append(a.pinOptions[i], system.WithPinActiveLow()) + } +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinsPullDown(id string, otherIDs ...string) { + ids := []string{id} + ids = append(ids, otherIDs...) + + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + for _, i := range ids { + a.pinOptions[i] = append(a.pinOptions[i], system.WithPinPullDown()) + } +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinsPullUp(id string, otherIDs ...string) { + ids := []string{id} + ids = append(ids, otherIDs...) + + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + for _, i := range ids { + a.pinOptions[i] = append(a.pinOptions[i], system.WithPinPullUp()) + } +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinsOpenDrain(id string, otherIDs ...string) { + ids := []string{id} + ids = append(ids, otherIDs...) + + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + for _, i := range ids { + a.pinOptions[i] = append(a.pinOptions[i], system.WithPinOpenDrain()) + } +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinsOpenSource(id string, otherIDs ...string) { + ids := []string{id} + ids = append(ids, otherIDs...) + + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + for _, i := range ids { + a.pinOptions[i] = append(a.pinOptions[i], system.WithPinOpenSource()) + } +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinDebounce(id string, period time.Duration) { + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + a.pinOptions[id] = append(a.pinOptions[id], system.WithPinDebounce(period)) +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnFallingEdge(id string, handler func(int, time.Duration, string, + uint32, uint32), +) { + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnFallingEdge(handler)) +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnRisingEdge(id string, handler func(int, time.Duration, string, + uint32, uint32), +) { + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnRisingEdge(handler)) +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnBothEdges(id string, handler func(int, time.Duration, string, + uint32, uint32), +) { + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnBothEdges(handler)) +} + +func (a *DigitalPinsAdaptor) prepareDigitalPinPollForEdgeDetection( + id string, + pollInterval time.Duration, + pollQuitChan chan struct{}, +) { + if a.pinOptions == nil { + a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool) + } + + a.pinOptions[id] = append(a.pinOptions[id], system.WithPinPollForEdgeDetection(pollInterval, pollQuitChan)) +} diff --git a/platforms/adaptors/digitalpinsadaptoroptions_test.go b/platforms/adaptors/digitalpinsadaptoroptions_test.go new file mode 100644 index 000000000..a458de37e --- /dev/null +++ b/platforms/adaptors/digitalpinsadaptoroptions_test.go @@ -0,0 +1,120 @@ +//nolint:nonamedreturns // ok for tests +package adaptors + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2/system" +) + +func TestDigitalPinsWithGpiosActiveLow(t *testing.T) { + // This is a general test, that options are applied in constructor. Further tests for options + // can also be done by call of "WithOption(val)(d)". + // arrange + translate := func(pin string) (chip string, line int, err error) { return } + sys := system.NewAccesser() + // act + a := NewDigitalPinsAdaptor(sys, translate, WithGpiosActiveLow("1", "12", "33")) + // assert + assert.Len(t, a.pinOptions, 3) +} + +func TestDigitalReadWithGpiosActiveLow(t *testing.T) { + mockedPaths := []string{ + "/sys/class/gpio/export", + "/sys/class/gpio/unexport", + "/sys/class/gpio/gpio25/value", + "/sys/class/gpio/gpio25/direction", + "/sys/class/gpio/gpio25/active_low", + "/sys/class/gpio/gpio26/value", + "/sys/class/gpio/gpio26/direction", + } + a, fs := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) + fs.Files["/sys/class/gpio/gpio25/value"].Contents = "1" + fs.Files["/sys/class/gpio/gpio25/active_low"].Contents = "5" + fs.Files["/sys/class/gpio/gpio26/value"].Contents = "0" + WithGpiosActiveLow("14")(a) + // creates a new pin without inverted logic + if _, err := a.DigitalRead("15"); err != nil { + panic(err) + } + fs.Add("/sys/class/gpio/gpio26/active_low") + fs.Files["/sys/class/gpio/gpio26/active_low"].Contents = "6" + WithGpiosActiveLow("15")(a) + // act + got1, err1 := a.DigitalRead("14") // for a new pin + got2, err2 := a.DigitalRead("15") // for an existing pin (calls ApplyOptions()) + // assert + require.NoError(t, err1) + require.NoError(t, err2) + assert.Equal(t, 1, got1) // there is no mechanism to negate mocked values + assert.Equal(t, 0, got2) + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio25/active_low"].Contents) + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio26/active_low"].Contents) +} + +func TestDigitalWriteWithOptions(t *testing.T) { + // arrange + mockedPaths := []string{ + "/sys/class/gpio/export", + "/sys/class/gpio/unexport", + "/sys/class/gpio/gpio18/value", + "/sys/class/gpio/gpio18/direction", + } + a, fs := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) + + // assert write correct value without error and just ignore unsupported options + WithGpiosPullUp("7")(a) + WithGpiosOpenDrain("7")(a) + WithGpioEventOnFallingEdge("7", gpioEventHandler)(a) + WithGpioPollForEdgeDetection("7", 0, nil)(a) + err := a.DigitalWrite("7", 1) + require.NoError(t, err) + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio18/value"].Contents) + + // assert second write to same pin without error and just ignore unsupported options + WithGpiosPullDown("7")(a) + WithGpiosOpenSource("7")(a) + WithGpioDebounce("7", 2*time.Second)(a) + WithGpioEventOnRisingEdge("7", gpioEventHandler)(a) + err = a.DigitalWrite("7", 1) + require.NoError(t, err) + + // assert error on bad id + require.ErrorContains(t, a.DigitalWrite("notexist", 1), "not a valid pin") + + // assert error bubbling + fs.WithWriteError = true + err = a.DigitalWrite("7", 0) + require.ErrorContains(t, err, "write error") +} + +func TestDigitalWriteWithGpiosActiveLow(t *testing.T) { + // arrange + mockedPaths := []string{ + "/sys/class/gpio/export", + "/sys/class/gpio/unexport", + "/sys/class/gpio/gpio19/value", + "/sys/class/gpio/gpio19/direction", + "/sys/class/gpio/gpio19/active_low", + } + a, fs := initTestDigitalPinsAdaptorWithMockedFilesystem(mockedPaths) + fs.Files["/sys/class/gpio/gpio19/active_low"].Contents = "5" + WithGpiosActiveLow("8")(a) + // act + err := a.DigitalWrite("8", 2) + // assert + require.NoError(t, err) + assert.Equal(t, "2", fs.Files["/sys/class/gpio/gpio19/value"].Contents) + assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio19/active_low"].Contents) +} + +func gpioEventHandler(o int, t time.Duration, et string, sn uint32, lsn uint32) { + // the handler should never execute, because used in outputs and not supported by sysfs + panic(fmt.Sprintf("event handler was called (%d, %d) unexpected for line %d with '%s' at %s!", sn, lsn, o, t, et)) +} diff --git a/platforms/adaptors/options.go b/platforms/adaptors/options.go deleted file mode 100644 index 11b48afa4..000000000 --- a/platforms/adaptors/options.go +++ /dev/null @@ -1,7 +0,0 @@ -package adaptors - -// Optioner is the interface for adaptors options. This provides the possibility for change the platform behavior -// by the user when creating the platform, e.g. by "NewAdaptor()". -type Optioner interface { - digitalPinsOptioner -} diff --git a/platforms/adaptors/pwmpinsadaptor.go b/platforms/adaptors/pwmpinsadaptor.go index 962c7dd4b..baa8bc0dd 100644 --- a/platforms/adaptors/pwmpinsadaptor.go +++ b/platforms/adaptors/pwmpinsadaptor.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "sync" + "time" multierror "github.com/hashicorp/go-multierror" @@ -17,69 +18,112 @@ import ( // 100ns = 10MHz, 10ns = 100MHz, 1ns = 1GHz const pwmPeriodDefault = 10000000 // 10 ms = 100 Hz +// 50Hz = 0.02 sec = 20 ms +const fiftyHzNanos = 20 * 1000 * 1000 + type ( pwmPinTranslator func(pin string) (path string, channel int, err error) - pwmPinInitializer func(gobot.PWMPinner) error + pwmPinInitializer func(id string, pin gobot.PWMPinner) error ) -type pwmPinsOption interface { - setInitializer(initializer pwmPinInitializer) - setDefaultPeriod(period uint32) - setPolarityInvertedIdentifier(id string) +type pwmPinServoScale struct { + minDegree, maxDegree float64 + minDuty, maxDuty time.Duration } -// PWMPinsAdaptor is a adaptor for PWM pins, normally used for composition in platforms. -type PWMPinsAdaptor struct { - sys *system.Accesser - translate pwmPinTranslator +// pwmPinConfiguration contains all changeable attributes of the adaptor. +type pwmPinsConfiguration struct { initialize pwmPinInitializer periodDefault uint32 polarityNormalIdentifier string polarityInvertedIdentifier string adjustDutyOnSetPeriod bool - pins map[string]gobot.PWMPinner - mutex sync.Mutex + pinsDefaultPeriod map[string]uint32 // the key is the pin id + pinsServoScale map[string]pwmPinServoScale // the key is the pin id +} + +// PWMPinsAdaptor is a adaptor for PWM pins, normally used for composition in platforms. +type PWMPinsAdaptor struct { + sys *system.Accesser + translate pwmPinTranslator + pwmPinsCfg *pwmPinsConfiguration + pins map[string]gobot.PWMPinner + mutex sync.Mutex } // NewPWMPinsAdaptor provides the access to PWM pins of the board. It uses sysfs system drivers. The translator is used // to adapt the pin header naming, which is given by user, to the internal file name nomenclature. This varies by each // platform. If for some reasons the default initializer is not suitable, it can be given by the option // "WithPWMPinInitializer()". -func NewPWMPinsAdaptor(sys *system.Accesser, t pwmPinTranslator, options ...func(pwmPinsOption)) *PWMPinsAdaptor { +// +// Further options: +// +// "WithPWMDefaultPeriod" +// "WithPWMPolarityInvertedIdentifier" +// "WithPWMNoDutyCycleAdjustment" +// "WithPWMDefaultPeriodForPin" +// "WithPWMServoDutyCycleRangeForPin" +// "WithPWMServoAngleRangeForPin" +func NewPWMPinsAdaptor(sys *system.Accesser, t pwmPinTranslator, opts ...PwmPinsOptionApplier) *PWMPinsAdaptor { a := &PWMPinsAdaptor{ - sys: sys, - translate: t, - periodDefault: pwmPeriodDefault, - polarityNormalIdentifier: "normal", - polarityInvertedIdentifier: "inverted", - adjustDutyOnSetPeriod: true, + sys: sys, + translate: t, + pwmPinsCfg: &pwmPinsConfiguration{ + periodDefault: pwmPeriodDefault, + pinsDefaultPeriod: make(map[string]uint32), + pinsServoScale: make(map[string]pwmPinServoScale), + polarityNormalIdentifier: "normal", + polarityInvertedIdentifier: "inverted", + adjustDutyOnSetPeriod: true, + }, } - a.initialize = a.getDefaultInitializer() - for _, option := range options { - option(a) + a.pwmPinsCfg.initialize = a.getDefaultInitializer() + + for _, o := range opts { + o.apply(a.pwmPinsCfg) } + return a } // WithPWMPinInitializer substitute the default initializer. -func WithPWMPinInitializer(pc pwmPinInitializer) func(pwmPinsOption) { - return func(a pwmPinsOption) { - a.setInitializer(pc) - } +func WithPWMPinInitializer(pc pwmPinInitializer) pwmPinsInitializeOption { + return pwmPinsInitializeOption(pc) } -// WithPWMPinDefaultPeriod substitute the default period of 10 ms (100 Hz) for all created pins. -func WithPWMPinDefaultPeriod(periodNanoSec uint32) func(pwmPinsOption) { - return func(a pwmPinsOption) { - a.setDefaultPeriod(periodNanoSec) - } +// WithPWMDefaultPeriod substitute the default period of 10 ms (100 Hz) for all created pins. +func WithPWMDefaultPeriod(periodNanoSec uint32) pwmPinsPeriodDefaultOption { + return pwmPinsPeriodDefaultOption(periodNanoSec) } -// WithPolarityInvertedIdentifier use the given identifier, which will replace the default "inverted". -func WithPolarityInvertedIdentifier(identifier string) func(pwmPinsOption) { - return func(a pwmPinsOption) { - a.setPolarityInvertedIdentifier(identifier) - } +// WithPWMPolarityInvertedIdentifier use the given identifier, which will replace the default "inverted". +func WithPWMPolarityInvertedIdentifier(identifier string) pwmPinsPolarityInvertedIdentifierOption { + return pwmPinsPolarityInvertedIdentifierOption(identifier) +} + +// WithPWMNoDutyCycleAdjustment switch off the automatic adjustment of duty cycle on setting the period. +func WithPWMNoDutyCycleAdjustment() pwmPinsAdjustDutyOnSetPeriodOption { + return pwmPinsAdjustDutyOnSetPeriodOption(false) +} + +// WithPWMDefaultPeriodForPin substitute the default period of 10 ms (100 Hz) for the given pin. +// This option also overrides a default period given by the WithPWMDefaultPeriod() option. +// This is often needed for servo applications, where the default period is 50Hz (20.000.000 ns). +func WithPWMDefaultPeriodForPin(pin string, periodNanoSec uint32) pwmPinsDefaultPeriodForPinOption { + o := pwmPinsDefaultPeriodForPinOption{id: pin, period: periodNanoSec} + return o +} + +// WithPWMServoDutyCycleRangeForPin set new values for range of duty cycle for servo calls, which replaces the default +// 0.5-2.5 ms range. The given duration values will be internally converted to nanoseconds. +func WithPWMServoDutyCycleRangeForPin(pin string, min, max time.Duration) pwmPinsServoDutyScaleForPinOption { + return pwmPinsServoDutyScaleForPinOption{id: pin, min: min, max: max} +} + +// WithPWMServoAngleRangeForPin set new values for range of angle for servo calls, which replaces +// the default 0.0-180.0° range. +func WithPWMServoAngleRangeForPin(pin string, min, max float64) pwmPinsServoAngleScaleForPinOption { + return pwmPinsServoAngleScaleForPinOption{id: pin, minDegree: min, maxDegree: max} } // Connect prepare new connection to PWM pins. @@ -142,40 +186,19 @@ func (a *PWMPinsAdaptor) ServoWrite(id string, angle byte) error { return err } - // 50Hz = 0.02 sec = 20 ms - const fiftyHzNanos = 20 * 1000 * 1000 - if period != fiftyHzNanos { log.Printf("WARNING: the PWM acts with a period of %d, but should use %d (50Hz) for servos\n", period, fiftyHzNanos) } - // TODO: implement an option to give another min-max range - // TODO: allow usage of adaptors.WithPWMPinDefaultPeriod() from main.go - // - // for some older servos, this can happen - // 0.5 ms => -90 (1/40 part of period at 50Hz) - // 1.5 ms => 0 - // 2.0 ms => 90 (1/10 part of period at 50Hz) - - // some servos have profiles below/above the 0-180° value - // SG90: 1/90: after position a small smooth movement is done - // SG90: >1/100: endless movement clock wise - // SG90: <1/8: endless movement counter clock wise - - // usually for the most servos (at 50Hz) for 90° - // 1.0 ms => 0 (1/20 part of period at 50Hz) - // 1.5 ms => 45 - // 2.0 ms => 90 (1/10 part of period at 50Hz) - - // usually for the most servos (at 50Hz) for 180° (SG90, AD002) - // 0.5 ms => 0 (1/40 part of period at 50Hz) - // 1.5 ms => 90 - // 2.5 ms => 180 (1/8 part of period at 50Hz) - - minDuty := float64(period) / 40 - maxDuty := float64(period) / 8 - duty := uint32(gobot.ToScale(gobot.FromScale(float64(angle), 0, 180), minDuty, maxDuty)) - return pin.SetDutyCycle(duty) + scale, ok := a.pwmPinsCfg.pinsServoScale[id] + if !ok { + return fmt.Errorf("no scaler found for servo pin '%s'", id) + } + + duty := gobot.ToScale(gobot.FromScale(float64(angle), + scale.minDegree, scale.maxDegree), + float64(scale.minDuty), float64(scale.maxDuty)) + return pin.SetDutyCycle(uint32(duty)) } // SetPeriod adjusts the period of the specified PWM pin immediately. @@ -188,7 +211,7 @@ func (a *PWMPinsAdaptor) SetPeriod(id string, period uint32) error { if err != nil { return err } - return setPeriod(pin, period, a.adjustDutyOnSetPeriod) + return setPeriod(pin, period, a.pwmPinsCfg.adjustDutyOnSetPeriod) } // PWMPin initializes the pin for PWM and returns matched pwmPin for specified pin number. @@ -200,20 +223,8 @@ func (a *PWMPinsAdaptor) PWMPin(id string) (gobot.PWMPinner, error) { return a.pwmPin(id) } -func (a *PWMPinsAdaptor) setInitializer(pinInit pwmPinInitializer) { - a.initialize = pinInit -} - -func (a *PWMPinsAdaptor) setDefaultPeriod(periodNanoSec uint32) { - a.periodDefault = periodNanoSec -} - -func (a *PWMPinsAdaptor) setPolarityInvertedIdentifier(identifier string) { - a.polarityInvertedIdentifier = identifier -} - -func (a *PWMPinsAdaptor) getDefaultInitializer() func(gobot.PWMPinner) error { - return func(pin gobot.PWMPinner) error { +func (a *PWMPinsAdaptor) getDefaultInitializer() func(string, gobot.PWMPinner) error { + return func(id string, pin gobot.PWMPinner) error { if err := pin.Export(); err != nil { return err } @@ -223,9 +234,38 @@ func (a *PWMPinsAdaptor) getDefaultInitializer() func(gobot.PWMPinner) error { return err } } - if err := setPeriod(pin, a.periodDefault, a.adjustDutyOnSetPeriod); err != nil { + + // looking for a pin specific period + defaultPeriod, ok := a.pwmPinsCfg.pinsDefaultPeriod[id] + if !ok { + defaultPeriod = a.pwmPinsCfg.periodDefault + } + + if err := setPeriod(pin, defaultPeriod, a.pwmPinsCfg.adjustDutyOnSetPeriod); err != nil { return err } + + // ensure servo scaler is present + // + // usually for the most servos (at 50Hz) for 180° (SG90, AD002) + // 0.5 ms => 0 (1/40 part of period at 50Hz) + // 1.5 ms => 90 + // 2.5 ms => 180 (1/8 part of period at 50Hz) + scale, ok := a.pwmPinsCfg.pinsServoScale[id] + if !ok { + scale = pwmPinServoScale{ + minDegree: 0, + maxDegree: 180, + } + } + if scale.minDuty == 0 { + scale.minDuty = time.Duration(defaultPeriod / 40) + } + if scale.maxDuty == 0 { + scale.maxDuty = time.Duration(defaultPeriod / 8) + } + a.pwmPinsCfg.pinsServoScale[id] = scale + // period needs to be set >1 before all next statements if err := pin.SetPolarity(true); err != nil { return err @@ -246,8 +286,8 @@ func (a *PWMPinsAdaptor) pwmPin(id string) (gobot.PWMPinner, error) { if err != nil { return nil, err } - pin = a.sys.NewPWMPin(path, channel, a.polarityNormalIdentifier, a.polarityInvertedIdentifier) - if err := a.initialize(pin); err != nil { + pin = a.sys.NewPWMPin(path, channel, a.pwmPinsCfg.polarityNormalIdentifier, a.pwmPinsCfg.polarityInvertedIdentifier) + if err := a.pwmPinsCfg.initialize(id, pin); err != nil { return nil, err } a.pins[id] = pin diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index ad0397be5..4635c90fb 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -50,7 +50,7 @@ func initTestPWMPinsAdaptorWithMockedFilesystem(mockPaths []string) (*PWMPinsAda fs.Files[pwmEnablePath].Contents = "0" fs.Files[pwmPeriodPath].Contents = "0" fs.Files[pwmDutyCyclePath].Contents = "0" - fs.Files[pwmPolarityPath].Contents = a.polarityInvertedIdentifier + fs.Files[pwmPolarityPath].Contents = a.pwmPinsCfg.polarityInvertedIdentifier if err := a.Connect(); err != nil { panic(err) } @@ -72,44 +72,10 @@ func TestNewPWMPinsAdaptor(t *testing.T) { // act a := NewPWMPinsAdaptor(system.NewAccesser(), translate) // assert - assert.Equal(t, uint32(pwmPeriodDefault), a.periodDefault) - assert.Equal(t, "normal", a.polarityNormalIdentifier) - assert.Equal(t, "inverted", a.polarityInvertedIdentifier) - assert.True(t, a.adjustDutyOnSetPeriod) -} - -func TestWithPWMPinInitializer(t *testing.T) { - // This is a general test, that options are applied by using the WithPWMPinInitializer() option. - // All other configuration options can also be tested by With..(val)(a). - // arrange - wantErr := fmt.Errorf("new_initializer") - newInitializer := func(gobot.PWMPinner) error { return wantErr } - // act - a := NewPWMPinsAdaptor(system.NewAccesser(), func(pin string) (c string, l int, e error) { return }, - WithPWMPinInitializer(newInitializer)) - // assert - err := a.initialize(nil) - assert.Equal(t, wantErr, err) -} - -func TestWithPWMPinDefaultPeriod(t *testing.T) { - // arrange - const newPeriod = uint32(10) - a := NewPWMPinsAdaptor(system.NewAccesser(), func(string) (c string, l int, e error) { return }) - // act - WithPWMPinDefaultPeriod(newPeriod)(a) - // assert - assert.Equal(t, newPeriod, a.periodDefault) -} - -func TestWithPolarityInvertedIdentifier(t *testing.T) { - // arrange - const newPolarityIdent = "pwm_invers" - a := NewPWMPinsAdaptor(system.NewAccesser(), func(pin string) (c string, l int, e error) { return }) - // act - WithPolarityInvertedIdentifier(newPolarityIdent)(a) - // assert - assert.Equal(t, newPolarityIdent, a.polarityInvertedIdentifier) + assert.Equal(t, uint32(pwmPeriodDefault), a.pwmPinsCfg.periodDefault) + assert.Equal(t, "normal", a.pwmPinsCfg.polarityNormalIdentifier) + assert.Equal(t, "inverted", a.pwmPinsCfg.polarityInvertedIdentifier) + assert.True(t, a.pwmPinsCfg.adjustDutyOnSetPeriod) } func TestPWMPinsConnect(t *testing.T) { @@ -182,7 +148,8 @@ func TestPwmWrite(t *testing.T) { assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", a.periodDefault), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here + //nolint:perfsprint // ok here + assert.Equal(t, fmt.Sprintf("%d", a.pwmPinsCfg.periodDefault), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) @@ -203,12 +170,13 @@ func TestServoWrite(t *testing.T) { a, fs := initTestPWMPinsAdaptorWithMockedFilesystem(pwmMockPaths) err := a.ServoWrite("33", 0) + require.NoError(t, err) assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", a.periodDefault), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here + //nolint:perfsprint // ok here + assert.Equal(t, fmt.Sprintf("%d", a.pwmPinsCfg.periodDefault), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "250000", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) - require.NoError(t, err) err = a.ServoWrite("33", 180) require.NoError(t, err) @@ -225,6 +193,11 @@ func TestServoWrite(t *testing.T) { fs.WithReadError = true err = a.ServoWrite("33", 100) require.ErrorContains(t, err, "read error") + fs.WithReadError = false + + delete(a.pwmPinsCfg.pinsServoScale, "33") + err = a.ServoWrite("33", 42) + require.EqualError(t, err, "no scaler found for servo pin '33'") } func TestSetPeriod(t *testing.T) { diff --git a/platforms/adaptors/pwmpinsadaptoroptions.go b/platforms/adaptors/pwmpinsadaptoroptions.go new file mode 100644 index 000000000..c6b336d92 --- /dev/null +++ b/platforms/adaptors/pwmpinsadaptoroptions.go @@ -0,0 +1,118 @@ +package adaptors + +import "time" + +// pwmPinOptionApplier needs to be implemented by each configurable option type +type PwmPinsOptionApplier interface { + apply(cfg *pwmPinsConfiguration) +} + +// pwmPinInitializeOption is the type for applying another than the default initializer. +type pwmPinsInitializeOption pwmPinInitializer + +// pwmPinPeriodDefaultOption is the type for applying another than the default period of 10 ms (100 Hz) for all +// created pins. +type pwmPinsPeriodDefaultOption uint32 + +// pwmPinPolarityInvertedIdentifierOption is the type for applying another identifier, which will replace the default +// "inverted". +type pwmPinsPolarityInvertedIdentifierOption string + +// pwmPinsAdjustDutyOnSetPeriodOption is the type for applying the automatic adjustment of duty cycle on setting +// the period to on/off. +type pwmPinsAdjustDutyOnSetPeriodOption bool + +// pwmPinsDefaultPeriodForPinOption is the type for applying another than the default period of 10 ms (100 Hz) only for +// the given pin id. +type pwmPinsDefaultPeriodForPinOption struct { + id string + period uint32 +} + +// pwmPinsServoDutyScaleForPinOption is the type for applying another than the default 0.5-2.5 ms range of duty cycle +// for servo calls on the specified pin id. +type pwmPinsServoDutyScaleForPinOption struct { + id string + min time.Duration + max time.Duration +} + +// pwmPinsServoAngleScaleForPinOption is the type for applying another than the default 0.0-180.0° range of angle for +// servo calls on the specified pin id. +type pwmPinsServoAngleScaleForPinOption struct { + id string + minDegree float64 + maxDegree float64 +} + +func (o pwmPinsInitializeOption) String() string { + return "pin initializer option for PWM's" +} + +func (o pwmPinsPeriodDefaultOption) String() string { + return "default period option for PWM's" +} + +func (o pwmPinsPolarityInvertedIdentifierOption) String() string { + return "inverted identifier option for PWM's" +} + +func (o pwmPinsAdjustDutyOnSetPeriodOption) String() string { + return "adjust duty cycle on set period option for PWM's" +} + +func (o pwmPinsDefaultPeriodForPinOption) String() string { + return "default period for the pin option for PWM's" +} + +func (o pwmPinsServoDutyScaleForPinOption) String() string { + return "duty cycle min-max range for a servo pin option for PWM's" +} + +func (o pwmPinsServoAngleScaleForPinOption) String() string { + return "angle min-max range for a servo pin option for PWM's" +} + +func (o pwmPinsInitializeOption) apply(cfg *pwmPinsConfiguration) { + cfg.initialize = pwmPinInitializer(o) +} + +func (o pwmPinsPeriodDefaultOption) apply(cfg *pwmPinsConfiguration) { + cfg.periodDefault = uint32(o) +} + +func (o pwmPinsPolarityInvertedIdentifierOption) apply(cfg *pwmPinsConfiguration) { + cfg.polarityInvertedIdentifier = string(o) +} + +func (o pwmPinsAdjustDutyOnSetPeriodOption) apply(cfg *pwmPinsConfiguration) { + cfg.adjustDutyOnSetPeriod = bool(o) +} + +func (o pwmPinsDefaultPeriodForPinOption) apply(cfg *pwmPinsConfiguration) { + cfg.pinsDefaultPeriod[o.id] = o.period +} + +func (o pwmPinsServoDutyScaleForPinOption) apply(cfg *pwmPinsConfiguration) { + scale, ok := cfg.pinsServoScale[o.id] + if !ok { + scale = pwmPinServoScale{minDegree: 0, maxDegree: 180} + } + + scale.minDuty = o.min + scale.maxDuty = o.max + + cfg.pinsServoScale[o.id] = scale +} + +func (o pwmPinsServoAngleScaleForPinOption) apply(cfg *pwmPinsConfiguration) { + scale, ok := cfg.pinsServoScale[o.id] + if !ok { + scale = pwmPinServoScale{} // default values for duty cycle will be set on initialize, if zero + } + + scale.minDegree = o.minDegree + scale.maxDegree = o.maxDegree + + cfg.pinsServoScale[o.id] = scale +} diff --git a/platforms/adaptors/pwmpinsadaptoroptions_test.go b/platforms/adaptors/pwmpinsadaptoroptions_test.go new file mode 100644 index 000000000..64341272d --- /dev/null +++ b/platforms/adaptors/pwmpinsadaptoroptions_test.go @@ -0,0 +1,148 @@ +//nolint:nonamedreturns // ok for tests +package adaptors + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/system" +) + +func TestWithPWMPinInitializer(t *testing.T) { + // This is a general test, that options are applied by using the WithPWMPinInitializer() option. + // All other configuration options can also be tested by With..(val).apply(cfg). + // arrange + wantErr := fmt.Errorf("new_initializer") + newInitializer := func(string, gobot.PWMPinner) error { return wantErr } + // act + a := NewPWMPinsAdaptor(system.NewAccesser(), func(pin string) (c string, l int, e error) { return }, + WithPWMPinInitializer(newInitializer)) + // assert + err := a.pwmPinsCfg.initialize("1", nil) + assert.Equal(t, wantErr, err) +} + +func TestWithPWMDefaultPeriod(t *testing.T) { + // arrange + const newPeriod = uint32(10) + cfg := &pwmPinsConfiguration{periodDefault: 123} + // act + WithPWMDefaultPeriod(newPeriod).apply(cfg) + // assert + assert.Equal(t, newPeriod, cfg.periodDefault) +} + +func TestWithPWMPolarityInvertedIdentifier(t *testing.T) { + // arrange + const newPolarityIdent = "pwm_invers" + cfg := &pwmPinsConfiguration{polarityInvertedIdentifier: "old_inverted"} + // act + WithPWMPolarityInvertedIdentifier(newPolarityIdent).apply(cfg) + // assert + assert.Equal(t, newPolarityIdent, cfg.polarityInvertedIdentifier) +} + +func TestWithPWMNoDutyCycleAdjustment(t *testing.T) { + // arrange + cfg := &pwmPinsConfiguration{adjustDutyOnSetPeriod: true} + // act + WithPWMNoDutyCycleAdjustment().apply(cfg) + // assert + assert.False(t, cfg.adjustDutyOnSetPeriod) +} + +func TestWithPWMDefaultPeriodForPin(t *testing.T) { + // arrange + const ( + pin = "pin4test" + newPeriod = 123456 + ) + cfg := &pwmPinsConfiguration{pinsDefaultPeriod: map[string]uint32{pin: 54321}} + // act + WithPWMDefaultPeriodForPin(pin, newPeriod).apply(cfg) + // assert + assert.Equal(t, uint32(newPeriod), cfg.pinsDefaultPeriod[pin]) +} + +func TestWithPWMServoDutyCycleRangeForPin(t *testing.T) { + const ( + pin = "pin4test" + newMin = 19 + newMax = 99 + ) + + tests := map[string]struct { + scaleMap map[string]pwmPinServoScale + wantScaleMap map[string]pwmPinServoScale + }{ + "empty_scale_map": { + scaleMap: make(map[string]pwmPinServoScale), + wantScaleMap: map[string]pwmPinServoScale{ + pin: {minDuty: newMin, maxDuty: newMax, minDegree: 0, maxDegree: 180}, + }, + }, + "scale_exists_for_set_pin": { + scaleMap: map[string]pwmPinServoScale{ + "other": {minDuty: 123, maxDuty: 234, minDegree: 11, maxDegree: 22}, + pin: {minDuty: newMin - 2, maxDuty: newMax + 2, minDegree: 1, maxDegree: 2}, + }, + wantScaleMap: map[string]pwmPinServoScale{ + "other": {minDuty: 123, maxDuty: 234, minDegree: 11, maxDegree: 22}, + pin: {minDuty: newMin, maxDuty: newMax, minDegree: 1, maxDegree: 2}, + }, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + cfg := &pwmPinsConfiguration{pinsServoScale: tc.scaleMap} + // act + WithPWMServoDutyCycleRangeForPin(pin, newMin, newMax).apply(cfg) + // assert + assert.Equal(t, tc.wantScaleMap, cfg.pinsServoScale) + }) + } +} + +func TestWithPWMServoAngleRangeForPin(t *testing.T) { + const ( + pin = "pin4test" + newMin = 30 + newMax = 90 + ) + + tests := map[string]struct { + scaleMap map[string]pwmPinServoScale + wantScaleMap map[string]pwmPinServoScale + }{ + "empty_scale_map": { + scaleMap: make(map[string]pwmPinServoScale), + wantScaleMap: map[string]pwmPinServoScale{ + pin: {minDuty: 0.0, maxDuty: 0.0, minDegree: newMin, maxDegree: newMax}, + }, + }, + "scale_exists_for_set_pin": { + scaleMap: map[string]pwmPinServoScale{ + "other": {minDuty: 123, maxDuty: 234, minDegree: 11, maxDegree: 22}, + pin: {minDuty: 4, maxDuty: 5, minDegree: newMin - 2, maxDegree: newMax + 2}, + }, + wantScaleMap: map[string]pwmPinServoScale{ + "other": {minDuty: 123, maxDuty: 234, minDegree: 11, maxDegree: 22}, + pin: {minDuty: 4, maxDuty: 5, minDegree: newMin, maxDegree: newMax}, + }, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + cfg := &pwmPinsConfiguration{pinsServoScale: tc.scaleMap} + // act + WithPWMServoAngleRangeForPin(pin, newMin, newMax).apply(cfg) + // assert + assert.Equal(t, tc.wantScaleMap, cfg.pinsServoScale) + }) + } +} diff --git a/platforms/beaglebone/beaglebone_adaptor.go b/platforms/beaglebone/beaglebone_adaptor.go index 87269eae4..3355497e4 100644 --- a/platforms/beaglebone/beaglebone_adaptor.go +++ b/platforms/beaglebone/beaglebone_adaptor.go @@ -43,7 +43,7 @@ const ( type Adaptor struct { name string sys *system.Accesser - mutex sync.Mutex + mutex *sync.Mutex *adaptors.AnalogPinsAdaptor *adaptors.DigitalPinsAdaptor *adaptors.PWMPinsAdaptor @@ -61,75 +61,91 @@ type Adaptor struct { // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +// +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +func NewAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser() - c := &Adaptor{ + a := &Adaptor{ name: gobot.DefaultName("BeagleboneBlack"), sys: sys, + mutex: &sync.Mutex{}, pinMap: bbbPinMap, pwmPinMap: bbbPwmPinMap, analogPinMap: bbbAnalogPinMap, usrLed: "/sys/class/leds/beaglebone:green:", } - c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) - c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateAndMuxDigitalPin, opts...) - c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translateAndMuxPWMPin, - adaptors.WithPWMPinDefaultPeriod(pwmPeriodDefault)) - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber) - c.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, c.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, + + var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) + pwmPinsOpts := []adaptors.PwmPinsOptionApplier{adaptors.WithPWMDefaultPeriod(pwmPeriodDefault)} + for _, opt := range opts { + switch o := opt.(type) { + case func(adaptors.DigitalPinsOptioner): + digitalPinsOpts = append(digitalPinsOpts, o) + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } + } + + a.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, a.translateAnalogPin) + a.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, a.translateAndMuxDigitalPin, digitalPinsOpts...) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.translateAndMuxPWMPin, pwmPinsOpts...) + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateI2cBusNumber, defaultI2cBusNumber) + a.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, a.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, defaultSpiMode, defaultSpiBitsNumber, defaultSpiMaxSpeed) - return c + return a } // Name returns the Adaptor name -func (c *Adaptor) Name() string { return c.name } +func (a *Adaptor) Name() string { return a.name } // SetName sets the Adaptor name -func (c *Adaptor) SetName(n string) { c.name = n } +func (a *Adaptor) SetName(n string) { a.name = n } // Connect create new connection to board and pins. -func (c *Adaptor) Connect() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() - if err := c.SpiBusAdaptor.Connect(); err != nil { + if err := a.SpiBusAdaptor.Connect(); err != nil { return err } - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - if err := c.AnalogPinsAdaptor.Connect(); err != nil { + if err := a.AnalogPinsAdaptor.Connect(); err != nil { return err } - if err := c.PWMPinsAdaptor.Connect(); err != nil { + if err := a.PWMPinsAdaptor.Connect(); err != nil { return err } - return c.DigitalPinsAdaptor.Connect() + return a.DigitalPinsAdaptor.Connect() } // Finalize releases all i2c devices and exported analog, digital, pwm pins. -func (c *Adaptor) Finalize() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() - err := c.DigitalPinsAdaptor.Finalize() + err := a.DigitalPinsAdaptor.Finalize() - if e := c.PWMPinsAdaptor.Finalize(); e != nil { + if e := a.PWMPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + if e := a.AnalogPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.SpiBusAdaptor.Finalize(); e != nil { + if e := a.SpiBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } return err @@ -137,12 +153,12 @@ func (c *Adaptor) Finalize() error { // DigitalWrite writes a digital value to specified pin. // valid usr pin values are usr0, usr1, usr2 and usr3 -func (c *Adaptor) DigitalWrite(id string, val byte) error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) DigitalWrite(id string, val byte) error { + a.mutex.Lock() + defer a.mutex.Unlock() if strings.Contains(id, "usr") { - fi, e := c.sys.OpenFile(c.usrLed+id+"/brightness", os.O_WRONLY|os.O_APPEND, 0o666) + fi, e := a.sys.OpenFile(a.usrLed+id+"/brightness", os.O_WRONLY|os.O_APPEND, 0o666) defer fi.Close() //nolint:staticcheck // for historical reasons if e != nil { return e @@ -151,10 +167,10 @@ func (c *Adaptor) DigitalWrite(id string, val byte) error { return err } - return c.DigitalPinsAdaptor.DigitalWrite(id, val) + return a.DigitalPinsAdaptor.DigitalWrite(id, val) } -func (c *Adaptor) validateSpiBusNumber(busNr int) error { +func (a *Adaptor) validateSpiBusNumber(busNr int) error { // Valid bus numbers are [0,1] which corresponds to /dev/spidev0.x through /dev/spidev1.x. // x is the chip number <255 if (busNr < 0) || (busNr > 1) { @@ -163,7 +179,7 @@ func (c *Adaptor) validateSpiBusNumber(busNr int) error { return nil } -func (c *Adaptor) validateI2cBusNumber(busNr int) error { +func (a *Adaptor) validateI2cBusNumber(busNr int) error { // Valid bus number is either 0 or 2 which corresponds to /dev/i2c-0 or /dev/i2c-2. if (busNr != 0) && (busNr != 2) { return fmt.Errorf("Bus number %d out of range", busNr) @@ -172,8 +188,8 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { } // translateAnalogPin converts analog pin name to pin position -func (c *Adaptor) translateAnalogPin(pin string) (string, bool, bool, uint16, error) { - pinInfo, ok := c.analogPinMap[pin] +func (a *Adaptor) translateAnalogPin(pin string) (string, bool, bool, uint16, error) { + pinInfo, ok := a.analogPinMap[pin] if !ok { return "", false, false, 0, fmt.Errorf("Not a valid analog pin") } @@ -182,30 +198,30 @@ func (c *Adaptor) translateAnalogPin(pin string) (string, bool, bool, uint16, er } // translatePin converts digital pin name to pin position -func (c *Adaptor) translateAndMuxDigitalPin(id string) (string, int, error) { - line, ok := c.pinMap[id] +func (a *Adaptor) translateAndMuxDigitalPin(id string) (string, int, error) { + line, ok := a.pinMap[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id) } // mux is done by id, not by line - if err := c.muxPin(id, "gpio"); err != nil { + if err := a.muxPin(id, "gpio"); err != nil { return "", -1, err } return "", line, nil } -func (c *Adaptor) translateAndMuxPWMPin(id string) (string, int, error) { - pinInfo, ok := c.pwmPinMap[id] +func (a *Adaptor) translateAndMuxPWMPin(id string) (string, int, error) { + pinInfo, ok := a.pwmPinMap[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a PWM pin", id) } - path, err := pinInfo.findPWMDir(c.sys) + path, err := pinInfo.findPWMDir(a.sys) if err != nil { return "", -1, err } - if err := c.muxPin(id, "pwm"); err != nil { + if err := a.muxPin(id, "pwm"); err != nil { return "", -1, err } @@ -230,9 +246,9 @@ func (p pwmPinDefinition) findPWMDir(sys *system.Accesser) (string, error) { return dir, nil } -func (c *Adaptor) muxPin(pin, cmd string) error { +func (a *Adaptor) muxPin(pin, cmd string) error { path := fmt.Sprintf("/sys/devices/platform/ocp/ocp:%s_pinmux/state", pin) - fi, e := c.sys.OpenFile(path, os.O_WRONLY, 0o666) + fi, e := a.sys.OpenFile(path, os.O_WRONLY, 0o666) defer fi.Close() //nolint:staticcheck // for historical reasons if e != nil { return e diff --git a/platforms/beaglebone/beaglebone_adaptor_test.go b/platforms/beaglebone/beaglebone_adaptor_test.go index 879999e3b..e94de6971 100644 --- a/platforms/beaglebone/beaglebone_adaptor_test.go +++ b/platforms/beaglebone/beaglebone_adaptor_test.go @@ -2,6 +2,7 @@ package beaglebone import ( "fmt" + "strconv" "strings" "testing" @@ -13,6 +14,7 @@ import ( "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/drivers/spi" + "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" ) @@ -45,47 +47,115 @@ const ( pwmChip0ExportPath = pwmChip0Dir + "export" pwmChip0UnexportPath = pwmChip0Dir + "unexport" pwmChip0Pwm0Dir = pwmChip0Dir + "pwm0/" - pwm0EnablePath = pwmChip0Pwm0Dir + "enable" - pwm0PeriodPath = pwmChip0Pwm0Dir + "period" - pwm0DutyCyclePath = pwmChip0Pwm0Dir + "duty_cycle" - pwm0PolarityPath = pwmChip0Pwm0Dir + "polarity" + pwmChip0Pwm1Dir = pwmChip0Dir + "pwm1/" + + pwm0EnablePath = pwmChip0Pwm0Dir + "enable" + pwm0PeriodPath = pwmChip0Pwm0Dir + "period" + pwm0DutyCyclePath = pwmChip0Pwm0Dir + "duty_cycle" + pwm0PolarityPath = pwmChip0Pwm0Dir + "polarity" - pwmChip0Pwm1Dir = pwmChip0Dir + "pwm1/" pwm1EnablePath = pwmChip0Pwm1Dir + "enable" pwm1PeriodPath = pwmChip0Pwm1Dir + "period" pwm1DutyCyclePath = pwmChip0Pwm1Dir + "duty_cycle" pwm1PolarityPath = pwmChip0Pwm1Dir + "polarity" ) -func TestPWM(t *testing.T) { - mockPaths := []string{ - "/sys/devices/platform/ocp/ocp:P9_22_pinmux/state", - "/sys/devices/platform/ocp/ocp:P9_21_pinmux/state", - "/sys/bus/iio/devices/iio:device0/in_voltage1_raw", - pwmChip0ExportPath, - pwmChip0UnexportPath, - pwm0EnablePath, - pwm0PeriodPath, - pwm0DutyCyclePath, - pwm0PolarityPath, - pwm1EnablePath, - pwm1PeriodPath, - pwm1DutyCyclePath, - pwm1PolarityPath, - } +var pwmMockPaths = []string{ + "/sys/devices/platform/ocp/ocp:P9_22_pinmux/state", + "/sys/devices/platform/ocp/ocp:P9_21_pinmux/state", + "/sys/bus/iio/devices/iio:device0/in_voltage1_raw", + pwmChip0ExportPath, + pwmChip0UnexportPath, + pwm0EnablePath, + pwm0PeriodPath, + pwm0DutyCyclePath, + pwm0PolarityPath, + pwm1EnablePath, + pwm1PeriodPath, + pwm1DutyCyclePath, + pwm1PolarityPath, +} - a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) +func TestNewAdaptor(t *testing.T) { + // arrange & act + a := NewAdaptor() + // assert + assert.IsType(t, &Adaptor{}, a) + assert.True(t, strings.HasPrefix(a.Name(), "Beaglebone")) + assert.NotNil(t, a.sys) + assert.NotNil(t, a.mutex) + assert.NotNil(t, a.AnalogPinsAdaptor) + assert.NotNil(t, a.DigitalPinsAdaptor) + assert.NotNil(t, a.PWMPinsAdaptor) + assert.NotNil(t, a.I2cBusAdaptor) + assert.NotNil(t, a.SpiBusAdaptor) + assert.Equal(t, bbbPinMap, a.pinMap) + assert.Equal(t, bbbPwmPinMap, a.pwmPinMap) + assert.Equal(t, bbbAnalogPinMap, a.analogPinMap) + assert.Equal(t, "/sys/class/leds/beaglebone:green:", a.usrLed) + // act & assert + a.SetName("NewName") + assert.Equal(t, "NewName", a.Name()) +} + +func TestNewPocketBeagleAdaptor(t *testing.T) { + // arrange & act + a := NewPocketBeagleAdaptor() + // assert + assert.IsType(t, &PocketBeagleAdaptor{}, a) + assert.True(t, strings.HasPrefix(a.Name(), "PocketBeagle")) + assert.NotNil(t, a.sys) + assert.Equal(t, pocketBeaglePinMap, a.pinMap) + assert.Equal(t, pocketBeaglePwmPinMap, a.pwmPinMap) + assert.Equal(t, pocketBeagleAnalogPinMap, a.analogPinMap) + assert.Equal(t, "/sys/class/leds/beaglebone:green:", a.usrLed) +} + +func TestNewPocketBeagleAdaptorWithOption(t *testing.T) { + // arrange & act + a := NewPocketBeagleAdaptor(adaptors.WithGpiodAccess()) + // assert + require.NoError(t, a.Connect()) +} + +func TestPWMWrite(t *testing.T) { + // arrange + a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) fs.Files[pwm1DutyCyclePath].Contents = "0" fs.Files[pwm1PeriodPath].Contents = "0" - + // act & assert wrong pin require.ErrorContains(t, a.PwmWrite("P9_99", 175), "'P9_99' is not a valid id for a PWM pin") + + // act & assert values _ = a.PwmWrite("P9_21", 175) assert.Equal(t, "500000", fs.Files[pwm1PeriodPath].Contents) assert.Equal(t, "343137", fs.Files[pwm1DutyCyclePath].Contents) - _ = a.ServoWrite("P9_21", 100) - assert.Equal(t, "500000", fs.Files[pwm1PeriodPath].Contents) - assert.Equal(t, "40277", fs.Files[pwm1DutyCyclePath].Contents) + require.NoError(t, a.Finalize()) +} + +func TestServoWrite(t *testing.T) { + // arrange: prepare 50Hz for servos + const ( + pin = "P9_21" + fiftyHzNano = 20000000 + ) + a := NewAdaptor(adaptors.WithPWMDefaultPeriodForPin(pin, fiftyHzNano)) + fs := a.sys.UseMockFilesystem(pwmMockPaths) + require.NoError(t, a.Connect()) + // act & assert for 0° (min default value) + err := a.ServoWrite(pin, 0) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwm1PeriodPath].Contents) + assert.Equal(t, "500000", fs.Files[pwm1DutyCyclePath].Contents) + // act & assert for 180° (max default value) + err = a.ServoWrite(pin, 180) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwm1PeriodPath].Contents) + assert.Equal(t, "2500000", fs.Files[pwm1DutyCyclePath].Contents) + // act & assert invalid pins + err = a.ServoWrite("3", 120) + require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") require.NoError(t, a.Finalize()) } @@ -160,13 +230,6 @@ func TestDigitalIO(t *testing.T) { require.NoError(t, a.Finalize()) } -func TestName(t *testing.T) { - a := NewAdaptor() - assert.True(t, strings.HasPrefix(a.Name(), "Beaglebone")) - a.SetName("NewName") - assert.Equal(t, "NewName", a.Name()) -} - func TestAnalogReadFileError(t *testing.T) { mockPaths := []string{ "/sys/devices/platform/whatever", @@ -212,11 +275,6 @@ func TestDigitalPinFinalizeFileError(t *testing.T) { require.ErrorContains(t, err, "/sys/class/gpio/unexport: no such file") } -func TestPocketName(t *testing.T) { - a := NewPocketBeagleAdaptor() - assert.True(t, strings.HasPrefix(a.Name(), "PocketBeagle")) -} - func TestSpiDefaultValues(t *testing.T) { a := NewAdaptor() diff --git a/platforms/beaglebone/pocketbeagle_adaptor.go b/platforms/beaglebone/pocketbeagle_adaptor.go index 68c6db49e..5ef366970 100644 --- a/platforms/beaglebone/pocketbeagle_adaptor.go +++ b/platforms/beaglebone/pocketbeagle_adaptor.go @@ -2,7 +2,6 @@ package beaglebone import ( "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/adaptors" ) // PocketBeagleAdaptor is the Gobot Adaptor for the PocketBeagle @@ -14,7 +13,13 @@ type PocketBeagleAdaptor struct { } // NewPocketBeagleAdaptor creates a new Adaptor for the PocketBeagle -func NewPocketBeagleAdaptor(opts ...func(adaptors.Optioner)) *PocketBeagleAdaptor { +// Optional parameters: +// +// adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs +// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +func NewPocketBeagleAdaptor(opts ...interface{}) *PocketBeagleAdaptor { a := NewAdaptor(opts...) a.SetName(gobot.DefaultName("PocketBeagle")) a.pinMap = pocketBeaglePinMap diff --git a/platforms/chip/chip_adaptor.go b/platforms/chip/chip_adaptor.go index c7dd3a21a..7f9d999ce 100644 --- a/platforms/chip/chip_adaptor.go +++ b/platforms/chip/chip_adaptor.go @@ -42,67 +42,82 @@ type Adaptor struct { // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +// +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +func NewAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser() - c := &Adaptor{ + a := &Adaptor{ name: gobot.DefaultName("CHIP"), sys: sys, } - c.pinmap = chipPins + a.pinmap = chipPins baseAddr, _ := getXIOBase() for i := 0; i < 8; i++ { pin := fmt.Sprintf("XIO-P%d", i) - c.pinmap[pin] = sysfsPin{pin: baseAddr + i, pwmPin: -1} + a.pinmap[pin] = sysfsPin{pin: baseAddr + i, pwmPin: -1} + } + + var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) + var pwmPinsOpts []adaptors.PwmPinsOptionApplier + for _, opt := range opts { + switch o := opt.(type) { + case func(adaptors.DigitalPinsOptioner): + digitalPinsOpts = append(digitalPinsOpts, o) + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } } - c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) - c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin) - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber) - return c + a.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, a.translateDigitalPin, digitalPinsOpts...) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.translatePWMPin, pwmPinsOpts...) + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateI2cBusNumber, defaultI2cBusNumber) + return a } // NewProAdaptor creates a C.H.I.P. Pro Adaptor func NewProAdaptor() *Adaptor { - c := NewAdaptor() - c.name = gobot.DefaultName("CHIP Pro") - c.pinmap = chipProPins - return c + a := NewAdaptor() + a.name = gobot.DefaultName("CHIP Pro") + a.pinmap = chipProPins + return a } // Name returns the name of the Adaptor -func (c *Adaptor) Name() string { return c.name } +func (a *Adaptor) Name() string { return a.name } // SetName sets the name of the Adaptor -func (c *Adaptor) SetName(n string) { c.name = n } +func (a *Adaptor) SetName(n string) { a.name = n } // Connect create new connection to board and pins. -func (c *Adaptor) Connect() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - if err := c.PWMPinsAdaptor.Connect(); err != nil { + if err := a.PWMPinsAdaptor.Connect(); err != nil { return err } - return c.DigitalPinsAdaptor.Connect() + return a.DigitalPinsAdaptor.Connect() } // Finalize closes connection to board and pins -func (c *Adaptor) Finalize() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() - err := c.DigitalPinsAdaptor.Finalize() + err := a.DigitalPinsAdaptor.Finalize() - if e := c.PWMPinsAdaptor.Finalize(); e != nil { + if e := a.PWMPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } @@ -139,7 +154,7 @@ func getXIOBase() (int, error) { return baseAddr, nil } -func (c *Adaptor) validateI2cBusNumber(busNr int) error { +func (a *Adaptor) validateI2cBusNumber(busNr int) error { // Valid bus number is [0..2] which corresponds to /dev/i2c-0 through /dev/i2c-2. if (busNr < 0) || (busNr > 2) { return fmt.Errorf("Bus number %d out of range", busNr) @@ -147,15 +162,15 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } -func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { - if val, ok := c.pinmap[id]; ok { +func (a *Adaptor) translateDigitalPin(id string) (string, int, error) { + if val, ok := a.pinmap[id]; ok { return "", val.pin, nil } return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id) } -func (c *Adaptor) translatePWMPin(id string) (string, int, error) { - sysPin, ok := c.pinmap[id] +func (a *Adaptor) translatePWMPin(id string) (string, int, error) { + sysPin, ok := a.pinmap[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a pin", id) } diff --git a/platforms/chip/chip_adaptor_test.go b/platforms/chip/chip_adaptor_test.go index 0a3d275ad..61aad0c58 100644 --- a/platforms/chip/chip_adaptor_test.go +++ b/platforms/chip/chip_adaptor_test.go @@ -2,6 +2,7 @@ package chip import ( "fmt" + "strconv" "strings" "testing" @@ -11,6 +12,7 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" + "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" ) @@ -73,7 +75,6 @@ func TestNewProAdaptor(t *testing.T) { func TestFinalizeErrorAfterGPIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() - require.NoError(t, a.Connect()) require.NoError(t, a.DigitalWrite("CSID7", 1)) fs.WithWriteError = true @@ -87,7 +88,6 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" - require.NoError(t, a.Connect()) require.NoError(t, a.PwmWrite("PWM0", 100)) fs.WithWriteError = true @@ -98,9 +98,8 @@ func TestFinalizeErrorAfterPWM(t *testing.T) { func TestDigitalIO(t *testing.T) { a, fs := initTestAdaptorWithMockedFilesystem() - _ = a.Connect() - _ = a.DigitalWrite("CSID7", 1) + require.NoError(t, a.DigitalWrite("CSID7", 1)) assert.Equal(t, "1", fs.Files["/sys/class/gpio/gpio139/value"].Contents) fs.Files["/sys/class/gpio/gpio50/value"].Contents = "1" @@ -126,36 +125,45 @@ func TestProDigitalIO(t *testing.T) { require.NoError(t, a.Finalize()) } -func TestPWM(t *testing.T) { +func TestPWMWrite(t *testing.T) { + // arrange a, fs := initTestAdaptorWithMockedFilesystem() fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" - - _ = a.Connect() - + // act err := a.PwmWrite("PWM0", 100) + // assert require.NoError(t, err) - assert.Equal(t, "0", fs.Files["/sys/class/pwm/pwmchip0/export"].Contents) assert.Equal(t, "1", fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents) assert.Equal(t, "3921568", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) assert.Equal(t, "10000000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault assert.Equal(t, "normal", fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents) - // prepare 50Hz for servos - const fiftyHzNano = "20000000" - fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = fiftyHzNano - err = a.ServoWrite("PWM0", 0) - require.NoError(t, err) + require.NoError(t, a.Finalize()) +} +func TestServoWrite(t *testing.T) { + // arrange: prepare 50Hz for servos + const ( + pin = "PWM0" + fiftyHzNano = 20000000 + ) + a := NewAdaptor(adaptors.WithPWMDefaultPeriodForPin(pin, fiftyHzNano)) + fs := a.sys.UseMockFilesystem(mockPaths) + require.NoError(t, a.Connect()) + fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents = "0" + fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "0" + // act & assert for 0° (min default value) + err := a.ServoWrite(pin, 0) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) assert.Equal(t, "500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) - assert.Equal(t, fiftyHzNano, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) - - err = a.ServoWrite("PWM0", 180) + // act & assert for 180° (max default value) + err = a.ServoWrite(pin, 180) require.NoError(t, err) - + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) assert.Equal(t, "2500000", fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents) - assert.Equal(t, fiftyHzNano, fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents) // pwmPeriodDefault require.NoError(t, a.Finalize()) } diff --git a/platforms/dragonboard/dragonboard_adaptor.go b/platforms/dragonboard/dragonboard_adaptor.go index 0f75eac41..5941b995f 100644 --- a/platforms/dragonboard/dragonboard_adaptor.go +++ b/platforms/dragonboard/dragonboard_adaptor.go @@ -50,7 +50,7 @@ var fixedPins = map[string]int{ // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { sys := system.NewAccesser() c := &Adaptor{ name: gobot.DefaultName("DragonBoard"), diff --git a/platforms/intel-iot/edison/edison_adaptor.go b/platforms/intel-iot/edison/edison_adaptor.go index 07a1ca76c..87c2c33c2 100644 --- a/platforms/intel-iot/edison/edison_adaptor.go +++ b/platforms/intel-iot/edison/edison_adaptor.go @@ -48,108 +48,121 @@ type Adaptor struct { // NewAdaptor returns a new Edison Adaptor of the given type. // Supported types are: "arduino", "miniboard", "sparkfun", an empty string defaults to "arduino" -func NewAdaptor(boardType ...string) *Adaptor { +// +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +func NewAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser() - c := &Adaptor{ + a := &Adaptor{ name: gobot.DefaultName("Edison"), board: "arduino", sys: sys, pinmap: arduinoPinMap, } - if len(boardType) > 0 && boardType[0] != "" { - c.board = boardType[0] + + pwmPinsOpts := []adaptors.PwmPinsOptionApplier{adaptors.WithPWMPinInitializer(pwmPinInitializer)} + for _, opt := range opts { + switch o := opt.(type) { + case string: + if o != "" { + a.board = o + } + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } } - c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) - c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translateAndMuxPWMPin, - adaptors.WithPWMPinInitializer(pwmPinInitializer)) + + a.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, a.translateAnalogPin) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.translateAndMuxPWMPin, pwmPinsOpts...) defI2cBusNr := defaultI2cBusNumber - if c.board != "arduino" { + if a.board != "arduino" { defI2cBusNr = defaultI2cBusNumberOther } - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateAndSetupI2cBusNumber, defI2cBusNr) - return c + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateAndSetupI2cBusNumber, defI2cBusNr) + return a } // Name returns the Adaptors name -func (c *Adaptor) Name() string { return c.name } +func (a *Adaptor) Name() string { return a.name } // SetName sets the Adaptors name -func (c *Adaptor) SetName(n string) { c.name = n } +func (a *Adaptor) SetName(n string) { a.name = n } // Connect initializes the Edison for use with the Arduino breakout board -func (c *Adaptor) Connect() error { - c.digitalPins = make(map[int]gobot.DigitalPinner) +func (a *Adaptor) Connect() error { + a.digitalPins = make(map[int]gobot.DigitalPinner) - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - if err := c.AnalogPinsAdaptor.Connect(); err != nil { + if err := a.AnalogPinsAdaptor.Connect(); err != nil { return err } - if err := c.PWMPinsAdaptor.Connect(); err != nil { + if err := a.PWMPinsAdaptor.Connect(); err != nil { return err } - switch c.board { + switch a.board { case "sparkfun": - c.pinmap = sparkfunPinMap + a.pinmap = sparkfunPinMap case "arduino": - c.board = "arduino" - c.pinmap = arduinoPinMap - if err := c.arduinoSetup(); err != nil { + a.board = "arduino" + a.pinmap = arduinoPinMap + if err := a.arduinoSetup(); err != nil { return err } case "miniboard": - c.pinmap = miniboardPinMap + a.pinmap = miniboardPinMap default: - return fmt.Errorf("Unknown board type: %s", c.board) + return fmt.Errorf("Unknown board type: %s", a.board) } return nil } // Finalize releases all i2c devices and exported analog, digital, pwm pins. -func (c *Adaptor) Finalize() error { +func (a *Adaptor) Finalize() error { var err error - if c.tristate != nil { - if errs := c.tristate.Unexport(); errs != nil { + if a.tristate != nil { + if errs := a.tristate.Unexport(); errs != nil { err = multierror.Append(err, errs) } } - c.tristate = nil + a.tristate = nil - for _, pin := range c.digitalPins { + for _, pin := range a.digitalPins { if pin != nil { if errs := pin.Unexport(); errs != nil { err = multierror.Append(err, errs) } } } - c.digitalPins = nil + a.digitalPins = nil - if e := c.PWMPinsAdaptor.Finalize(); e != nil { + if e := a.PWMPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + if e := a.AnalogPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - c.arduinoI2cInitialized = false + a.arduinoI2cInitialized = false return err } // DigitalRead reads digital value from pin -func (c *Adaptor) DigitalRead(pin string) (int, error) { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) DigitalRead(pin string) (int, error) { + a.mutex.Lock() + defer a.mutex.Unlock() - sysPin, err := c.digitalPin(pin, system.WithPinDirectionInput()) + sysPin, err := a.digitalPin(pin, system.WithPinDirectionInput()) if err != nil { return 0, err } @@ -157,25 +170,25 @@ func (c *Adaptor) DigitalRead(pin string) (int, error) { } // DigitalWrite writes a value to the pin. Acceptable values are 1 or 0. -func (c *Adaptor) DigitalWrite(pin string, val byte) error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) DigitalWrite(pin string, val byte) error { + a.mutex.Lock() + defer a.mutex.Unlock() - return c.digitalWrite(pin, val) + return a.digitalWrite(pin, val) } // DigitalPin returns a digital pin. If the pin is initially acquired, it is an input. // Pin direction and other options can be changed afterwards by pin.ApplyOptions() at any time. -func (c *Adaptor) DigitalPin(id string) (gobot.DigitalPinner, error) { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) DigitalPin(id string) (gobot.DigitalPinner, error) { + a.mutex.Lock() + defer a.mutex.Unlock() - return c.digitalPin(id) + return a.digitalPin(id) } // AnalogRead returns value from analog reading of specified pin -func (c *Adaptor) AnalogRead(pin string) (int, error) { - rawRead, err := c.AnalogPinsAdaptor.AnalogRead(pin) +func (a *Adaptor) AnalogRead(pin string) (int, error) { + rawRead, err := a.AnalogPinsAdaptor.AnalogRead(pin) if err != nil { return 0, err } @@ -183,20 +196,20 @@ func (c *Adaptor) AnalogRead(pin string) (int, error) { return rawRead / 4, err } -func (c *Adaptor) validateAndSetupI2cBusNumber(busNr int) error { +func (a *Adaptor) validateAndSetupI2cBusNumber(busNr int) error { // Valid bus number is 6 for "arduino", otherwise 1. - if busNr == 6 && c.board == "arduino" { - if !c.arduinoI2cInitialized { - if err := c.arduinoI2CSetup(); err != nil { + if busNr == 6 && a.board == "arduino" { + if !a.arduinoI2cInitialized { + if err := a.arduinoI2CSetup(); err != nil { return err } - c.arduinoI2cInitialized = true + a.arduinoI2cInitialized = true return nil } return nil } - if busNr == 1 && c.board != "arduino" { + if busNr == 1 && a.board != "arduino" { return nil } @@ -204,81 +217,81 @@ func (c *Adaptor) validateAndSetupI2cBusNumber(busNr int) error { } // arduinoSetup does needed setup for the Arduino compatible breakout board -func (c *Adaptor) arduinoSetup() error { +func (a *Adaptor) arduinoSetup() error { // TODO: also check to see if device labels for // /sys/class/gpio/gpiochip{200,216,232,248}/label == "pcal9555a" - tpin, err := c.newExportedDigitalPin(214, system.WithPinDirectionOutput(system.LOW)) + tpin, err := a.newExportedDigitalPin(214, system.WithPinDirectionOutput(system.LOW)) if err != nil { return err } - c.tristate = tpin + a.tristate = tpin for _, i := range []int{263, 262} { - if err := c.newUnexportedDigitalPin(i, system.WithPinDirectionOutput(system.HIGH)); err != nil { + if err := a.newUnexportedDigitalPin(i, system.WithPinDirectionOutput(system.HIGH)); err != nil { return err } } for _, i := range []int{240, 241, 242, 243} { - if err := c.newUnexportedDigitalPin(i, system.WithPinDirectionOutput(system.LOW)); err != nil { + if err := a.newUnexportedDigitalPin(i, system.WithPinDirectionOutput(system.LOW)); err != nil { return err } } for _, i := range []string{"111", "115", "114", "109"} { - if err := c.changePinMode(i, "1"); err != nil { + if err := a.changePinMode(i, "1"); err != nil { return err } } for _, i := range []string{"131", "129", "40"} { - if err := c.changePinMode(i, "0"); err != nil { + if err := a.changePinMode(i, "0"); err != nil { return err } } - return c.tristate.Write(system.HIGH) + return a.tristate.Write(system.HIGH) } -func (c *Adaptor) arduinoI2CSetup() error { - if c.tristate == nil { +func (a *Adaptor) arduinoI2CSetup() error { + if a.tristate == nil { return fmt.Errorf("not connected") } - if err := c.tristate.Write(system.LOW); err != nil { + if err := a.tristate.Write(system.LOW); err != nil { return err } for _, i := range []int{14, 165, 212, 213} { - if err := c.newUnexportedDigitalPin(i, system.WithPinDirectionInput()); err != nil { + if err := a.newUnexportedDigitalPin(i, system.WithPinDirectionInput()); err != nil { return err } } for _, i := range []int{236, 237, 204, 205} { - if err := c.newUnexportedDigitalPin(i, system.WithPinDirectionOutput(system.LOW)); err != nil { + if err := a.newUnexportedDigitalPin(i, system.WithPinDirectionOutput(system.LOW)); err != nil { return err } } for _, i := range []string{"28", "27"} { - if err := c.changePinMode(i, "1"); err != nil { + if err := a.changePinMode(i, "1"); err != nil { return err } } - return c.tristate.Write(system.HIGH) + return a.tristate.Write(system.HIGH) } -func (c *Adaptor) digitalPin(id string, o ...func(gobot.DigitalPinOptioner) bool) (gobot.DigitalPinner, error) { - i := c.pinmap[id] +func (a *Adaptor) digitalPin(id string, o ...func(gobot.DigitalPinOptioner) bool) (gobot.DigitalPinner, error) { + i := a.pinmap[id] - err := c.ensureDigitalPin(i.pin, o...) + err := a.ensureDigitalPin(i.pin, o...) if err != nil { return nil, err } - pin := c.digitalPins[i.pin] + pin := a.digitalPins[i.pin] vpin, ok := pin.(gobot.DigitalPinValuer) if !ok { return nil, fmt.Errorf("can not determine the direction behavior") @@ -289,7 +302,7 @@ func (c *Adaptor) digitalPin(id string, o ...func(gobot.DigitalPinOptioner) bool if dir == system.OUT { rop = system.WithPinDirectionInput() } - if err := c.ensureDigitalPin(i.resistor, rop); err != nil { + if err := a.ensureDigitalPin(i.resistor, rop); err != nil { return nil, err } } @@ -299,14 +312,14 @@ func (c *Adaptor) digitalPin(id string, o ...func(gobot.DigitalPinOptioner) bool if dir == system.OUT { lop = system.WithPinDirectionOutput(system.HIGH) } - if err := c.ensureDigitalPin(i.levelShifter, lop); err != nil { + if err := a.ensureDigitalPin(i.levelShifter, lop); err != nil { return nil, err } } if len(i.mux) > 0 { for _, mux := range i.mux { - if err := c.ensureDigitalPin(mux.pin, system.WithPinDirectionOutput(mux.value)); err != nil { + if err := a.ensureDigitalPin(mux.pin, system.WithPinDirectionOutput(mux.value)); err != nil { return nil, err } } @@ -315,15 +328,15 @@ func (c *Adaptor) digitalPin(id string, o ...func(gobot.DigitalPinOptioner) bool return pin, nil } -func (c *Adaptor) ensureDigitalPin(idx int, o ...func(gobot.DigitalPinOptioner) bool) error { - pin := c.digitalPins[idx] +func (a *Adaptor) ensureDigitalPin(idx int, o ...func(gobot.DigitalPinOptioner) bool) error { + pin := a.digitalPins[idx] var err error if pin == nil { - pin, err = c.newExportedDigitalPin(idx, o...) + pin, err = a.newExportedDigitalPin(idx, o...) if err != nil { return err } - c.digitalPins[idx] = pin + a.digitalPins[idx] = pin } else { if err := pin.ApplyOptions(o...); err != nil { return err @@ -332,14 +345,14 @@ func (c *Adaptor) ensureDigitalPin(idx int, o ...func(gobot.DigitalPinOptioner) return nil } -func pwmPinInitializer(pin gobot.PWMPinner) error { +func pwmPinInitializer(_ string, pin gobot.PWMPinner) error { if err := pin.Export(); err != nil { return err } return pin.SetEnabled(true) } -func (c *Adaptor) translateAnalogPin(pin string) (string, bool, bool, uint16, error) { +func (a *Adaptor) translateAnalogPin(pin string) (string, bool, bool, uint16, error) { path := fmt.Sprintf("/sys/bus/iio/devices/iio:device1/in_voltage%s_raw", pin) const ( read = true @@ -349,43 +362,43 @@ func (c *Adaptor) translateAnalogPin(pin string) (string, bool, bool, uint16, er return path, read, write, readBufLen, nil } -func (c *Adaptor) translateAndMuxPWMPin(id string) (string, int, error) { - sysPin, ok := c.pinmap[id] +func (a *Adaptor) translateAndMuxPWMPin(id string) (string, int, error) { + sysPin, ok := a.pinmap[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a pin", id) } if sysPin.pwmPin == -1 { return "", -1, fmt.Errorf("'%s' is not a valid id for a PWM pin", id) } - if err := c.digitalWrite(id, 1); err != nil { + if err := a.digitalWrite(id, 1); err != nil { return "", -1, err } - if err := c.changePinMode(strconv.Itoa(sysPin.pin), "1"); err != nil { + if err := a.changePinMode(strconv.Itoa(sysPin.pin), "1"); err != nil { return "", -1, err } return "/sys/class/pwm/pwmchip0", sysPin.pwmPin, nil } -func (c *Adaptor) newUnexportedDigitalPin(i int, o ...func(gobot.DigitalPinOptioner) bool) error { - io := c.sys.NewDigitalPin("", i, o...) +func (a *Adaptor) newUnexportedDigitalPin(i int, o ...func(gobot.DigitalPinOptioner) bool) error { + io := a.sys.NewDigitalPin("", i, o...) if err := io.Export(); err != nil { return err } return io.Unexport() } -func (c *Adaptor) newExportedDigitalPin( +func (a *Adaptor) newExportedDigitalPin( pin int, o ...func(gobot.DigitalPinOptioner) bool, ) (gobot.DigitalPinner, error) { - sysPin := c.sys.NewDigitalPin("", pin, o...) + sysPin := a.sys.NewDigitalPin("", pin, o...) err := sysPin.Export() return sysPin, err } // changePinMode writes pin mode to current_pinmux file -func (c *Adaptor) changePinMode(pin, mode string) error { - file, err := c.sys.OpenFile("/sys/kernel/debug/gpio_debug/gpio"+pin+"/current_pinmux", os.O_WRONLY, 0o644) +func (a *Adaptor) changePinMode(pin, mode string) error { + file, err := a.sys.OpenFile("/sys/kernel/debug/gpio_debug/gpio"+pin+"/current_pinmux", os.O_WRONLY, 0o644) defer file.Close() //nolint:staticcheck // for historical reasons if err != nil { return err @@ -394,8 +407,8 @@ func (c *Adaptor) changePinMode(pin, mode string) error { return err } -func (c *Adaptor) digitalWrite(pin string, val byte) error { - sysPin, err := c.digitalPin(pin, system.WithPinDirectionOutput(int(val))) +func (a *Adaptor) digitalWrite(pin string, val byte) error { + sysPin, err := a.digitalPin(pin, system.WithPinDirectionOutput(int(val))) if err != nil { return err } diff --git a/platforms/intel-iot/edison/edison_adaptor_test.go b/platforms/intel-iot/edison/edison_adaptor_test.go index 8451d949e..05bb4bad9 100644 --- a/platforms/intel-iot/edison/edison_adaptor_test.go +++ b/platforms/intel-iot/edison/edison_adaptor_test.go @@ -1,7 +1,6 @@ package edison import ( - "fmt" "strings" "testing" @@ -579,15 +578,15 @@ func Test_validateI2cBusNumber(t *testing.T) { tests := map[string]struct { board string busNr int - wantErr error + wantErr string }{ "arduino_number_negative_error": { busNr: -1, - wantErr: fmt.Errorf("Unsupported I2C bus '-1'"), + wantErr: "Unsupported I2C bus '-1'", }, "arduino_number_1_error": { busNr: 1, - wantErr: fmt.Errorf("Unsupported I2C bus '1'"), + wantErr: "Unsupported I2C bus '1'", }, "arduino_number_6_ok": { busNr: 6, @@ -595,7 +594,7 @@ func Test_validateI2cBusNumber(t *testing.T) { "sparkfun_number_negative_error": { board: "sparkfun", busNr: -1, - wantErr: fmt.Errorf("Unsupported I2C bus '-1'"), + wantErr: "Unsupported I2C bus '-1'", }, "sparkfun_number_1_ok": { board: "sparkfun", @@ -604,7 +603,7 @@ func Test_validateI2cBusNumber(t *testing.T) { "miniboard_number_6_error": { board: "miniboard", busNr: 6, - wantErr: fmt.Errorf("Unsupported I2C bus '6'"), + wantErr: "Unsupported I2C bus '6'", }, } for name, tc := range tests { @@ -616,7 +615,11 @@ func Test_validateI2cBusNumber(t *testing.T) { // act err := a.validateAndSetupI2cBusNumber(tc.busNr) // assert - assert.Equal(t, tc.wantErr, err) + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + } else { + require.NoError(t, err) + } }) } } diff --git a/platforms/intel-iot/joule/joule_adaptor.go b/platforms/intel-iot/joule/joule_adaptor.go index 0afdc83d5..5706ac233 100644 --- a/platforms/intel-iot/joule/joule_adaptor.go +++ b/platforms/intel-iot/joule/joule_adaptor.go @@ -34,59 +34,74 @@ type Adaptor struct { // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +// +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +func NewAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser() - c := &Adaptor{ + a := &Adaptor{ name: gobot.DefaultName("Joule"), sys: sys, } - c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) - c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin, - adaptors.WithPWMPinInitializer(pwmPinInitializer)) - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber) - return c + + var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) + pwmPinsOpts := []adaptors.PwmPinsOptionApplier{adaptors.WithPWMPinInitializer(pwmPinInitializer)} + for _, opt := range opts { + switch o := opt.(type) { + case func(adaptors.DigitalPinsOptioner): + digitalPinsOpts = append(digitalPinsOpts, o) + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } + } + + a.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, a.translateDigitalPin, digitalPinsOpts...) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.translatePWMPin, pwmPinsOpts...) + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateI2cBusNumber, defaultI2cBusNumber) + return a } // Name returns the Adaptors name -func (c *Adaptor) Name() string { return c.name } +func (a *Adaptor) Name() string { return a.name } // SetName sets the Adaptors name -func (c *Adaptor) SetName(n string) { c.name = n } +func (a *Adaptor) SetName(n string) { a.name = n } // Connect create new connection to board and pins. -func (c *Adaptor) Connect() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - if err := c.PWMPinsAdaptor.Connect(); err != nil { + if err := a.PWMPinsAdaptor.Connect(); err != nil { return err } - return c.DigitalPinsAdaptor.Connect() + return a.DigitalPinsAdaptor.Connect() } // Finalize releases all i2c devices and exported digital and pwm pins. -func (c *Adaptor) Finalize() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() - err := c.DigitalPinsAdaptor.Finalize() + err := a.DigitalPinsAdaptor.Finalize() - if e := c.PWMPinsAdaptor.Finalize(); e != nil { + if e := a.PWMPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } return err } -func (c *Adaptor) validateI2cBusNumber(busNr int) error { +func (a *Adaptor) validateI2cBusNumber(busNr int) error { // Valid bus number is [0..2] which corresponds to /dev/i2c-0 through /dev/i2c-2. if (busNr < 0) || (busNr > 2) { return fmt.Errorf("Bus number %d out of range", busNr) @@ -94,14 +109,14 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } -func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { +func (a *Adaptor) translateDigitalPin(id string) (string, int, error) { if val, ok := sysfsPinMap[id]; ok { return "", val.pin, nil } return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id) } -func (c *Adaptor) translatePWMPin(id string) (string, int, error) { +func (a *Adaptor) translatePWMPin(id string) (string, int, error) { sysPin, ok := sysfsPinMap[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a pin", id) @@ -112,7 +127,7 @@ func (c *Adaptor) translatePWMPin(id string) (string, int, error) { return "/sys/class/pwm/pwmchip0", sysPin.pwmPin, nil } -func pwmPinInitializer(pin gobot.PWMPinner) error { +func pwmPinInitializer(_ string, pin gobot.PWMPinner) error { if err := pin.Export(); err != nil { return err } diff --git a/platforms/jetson/jetson_adaptor.go b/platforms/jetson/jetson_adaptor.go index ce336ed34..dacd9ede4 100644 --- a/platforms/jetson/jetson_adaptor.go +++ b/platforms/jetson/jetson_adaptor.go @@ -41,7 +41,7 @@ type Adaptor struct { // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { sys := system.NewAccesser() c := &Adaptor{ name: gobot.DefaultName("JetsonNano"), diff --git a/platforms/nanopi/nanopi_adaptor.go b/platforms/nanopi/nanopi_adaptor.go index 0ef45cffb..ab78758d8 100644 --- a/platforms/nanopi/nanopi_adaptor.go +++ b/platforms/nanopi/nanopi_adaptor.go @@ -71,79 +71,94 @@ type Adaptor struct { // adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior // adaptors.WithGpioDebounce(pin, period): sets the input debouncer // adaptors.WithGpioEventOnFallingEdge/RaisingEdge/BothEdges(pin, handler): activate edge detection -func NewNeoAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +// +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +func NewNeoAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser(system.WithDigitalPinGpiodAccess()) - c := &Adaptor{ + a := &Adaptor{ name: gobot.DefaultName("NanoPi NEO Board"), sys: sys, gpioPinMap: neoGpioPins, pwmPinMap: neoPwmPins, } - c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) - c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) - c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin, - adaptors.WithPolarityInvertedIdentifier(pwmInvertedIdentifier)) - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber) - c.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, c.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, + + var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) + pwmPinsOpts := []adaptors.PwmPinsOptionApplier{adaptors.WithPWMPolarityInvertedIdentifier(pwmInvertedIdentifier)} + for _, opt := range opts { + switch o := opt.(type) { + case func(adaptors.DigitalPinsOptioner): + digitalPinsOpts = append(digitalPinsOpts, o) + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } + } + + a.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, a.translateAnalogPin) + a.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, a.translateDigitalPin, digitalPinsOpts...) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.translatePWMPin, pwmPinsOpts...) + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateI2cBusNumber, defaultI2cBusNumber) + a.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, a.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, defaultSpiMode, defaultSpiBitsNumber, defaultSpiMaxSpeed) - return c + return a } // Name returns the name of the Adaptor -func (c *Adaptor) Name() string { return c.name } +func (a *Adaptor) Name() string { return a.name } // SetName sets the name of the Adaptor -func (c *Adaptor) SetName(n string) { c.name = n } +func (a *Adaptor) SetName(n string) { a.name = n } // Connect create new connection to board and pins. -func (c *Adaptor) Connect() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() - if err := c.SpiBusAdaptor.Connect(); err != nil { + if err := a.SpiBusAdaptor.Connect(); err != nil { return err } - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - if err := c.AnalogPinsAdaptor.Connect(); err != nil { + if err := a.AnalogPinsAdaptor.Connect(); err != nil { return err } - if err := c.PWMPinsAdaptor.Connect(); err != nil { + if err := a.PWMPinsAdaptor.Connect(); err != nil { return err } - return c.DigitalPinsAdaptor.Connect() + return a.DigitalPinsAdaptor.Connect() } // Finalize closes connection to board, pins and bus -func (c *Adaptor) Finalize() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() - err := c.DigitalPinsAdaptor.Finalize() + err := a.DigitalPinsAdaptor.Finalize() - if e := c.PWMPinsAdaptor.Finalize(); e != nil { + if e := a.PWMPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + if e := a.AnalogPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.SpiBusAdaptor.Finalize(); e != nil { + if e := a.SpiBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } return err } -func (c *Adaptor) validateSpiBusNumber(busNr int) error { +func (a *Adaptor) validateSpiBusNumber(busNr int) error { // Valid bus numbers are [0] which corresponds to /dev/spidev0.x // x is the chip number <255 if busNr != 0 { @@ -152,7 +167,7 @@ func (c *Adaptor) validateSpiBusNumber(busNr int) error { return nil } -func (c *Adaptor) validateI2cBusNumber(busNr int) error { +func (a *Adaptor) validateI2cBusNumber(busNr int) error { // Valid bus number is [0..2] which corresponds to /dev/i2c-0 through /dev/i2c-2. if (busNr < 0) || (busNr > 2) { return fmt.Errorf("Bus number %d out of range", busNr) @@ -160,14 +175,14 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } -func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { +func (a *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { pinInfo, ok := analogPinDefinitions[id] if !ok { return "", false, false, 0, fmt.Errorf("'%s' is not a valid id for a analog pin", id) } path := pinInfo.path - info, err := c.sys.Stat(path) + info, err := a.sys.Stat(path) if err != nil { return "", false, false, 0, fmt.Errorf("Error (%v) on access '%s'", err, path) } @@ -178,12 +193,12 @@ func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, err return path, pinInfo.r, pinInfo.w, pinInfo.bufLen, nil } -func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { - pindef, ok := c.gpioPinMap[id] +func (a *Adaptor) translateDigitalPin(id string) (string, int, error) { + pindef, ok := a.gpioPinMap[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id) } - if c.sys.IsSysfsDigitalPinAccess() { + if a.sys.IsSysfsDigitalPinAccess() { return "", pindef.sysfs, nil } chip := fmt.Sprintf("gpiochip%d", pindef.cdev.chip) @@ -191,12 +206,12 @@ func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { return chip, line, nil } -func (c *Adaptor) translatePWMPin(id string) (string, int, error) { - pinInfo, ok := c.pwmPinMap[id] +func (a *Adaptor) translatePWMPin(id string) (string, int, error) { + pinInfo, ok := a.pwmPinMap[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a PWM pin", id) } - path, err := pinInfo.findPWMDir(c.sys) + path, err := pinInfo.findPWMDir(a.sys) if err != nil { return "", -1, err } diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index 8c44ce240..5410323bc 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -13,6 +13,7 @@ import ( "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" + "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" ) @@ -30,8 +31,6 @@ const ( pwmPeriodPath = pwmPwmDir + "period" pwmDutyCyclePath = pwmPwmDir + "duty_cycle" pwmPolarityPath = pwmPwmDir + "polarity" - - fiftyHzNano = "20000000" ) var pwmMockPaths = []string{ @@ -144,29 +143,46 @@ func TestInvalidPWMPin(t *testing.T) { } func TestPwmWrite(t *testing.T) { + // arrange a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) - + // act err := a.PwmWrite("PWM", 100) + // assert require.NoError(t, err) - assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) assert.Equal(t, strconv.Itoa(10000000), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) - // prepare 50Hz for servos - fs.Files[pwmPeriodPath].Contents = fiftyHzNano - err = a.ServoWrite("PWM", 0) - require.NoError(t, err) + require.NoError(t, a.Finalize()) +} +func TestServoWrite(t *testing.T) { + // arrange: prepare 50Hz for servos + const ( + pin = "PWM" + fiftyHzNano = 20000000 + ) + a := NewNeoAdaptor(adaptors.WithPWMDefaultPeriodForPin(pin, fiftyHzNano)) + fs := a.sys.UseMockFilesystem(pwmMockPaths) + preparePwmFs(fs) + require.NoError(t, a.Connect()) + // act & assert for 0° (min default value) + err := a.ServoWrite(pin, 0) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) - - err = a.ServoWrite("PWM", 180) + // act & assert for 180° (max default value) + err = a.ServoWrite(pin, 180) require.NoError(t, err) - + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "2500000", fs.Files[pwmDutyCyclePath].Contents) + // act & assert invalid pins + err = a.ServoWrite("3", 120) + require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") + require.NoError(t, a.Finalize()) } diff --git a/platforms/raspi/raspi_adaptor.go b/platforms/raspi/raspi_adaptor.go index 75e3fe5e0..a98ff9fe1 100644 --- a/platforms/raspi/raspi_adaptor.go +++ b/platforms/raspi/raspi_adaptor.go @@ -56,7 +56,7 @@ type Adaptor struct { // adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior // adaptors.WithGpioDebounce(pin, period): sets the input debouncer // adaptors.WithGpioEventOnFallingEdge/RaisingEdge/BothEdges(pin, handler): activate edge detection -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { sys := system.NewAccesser(system.WithDigitalPinGpiodAccess()) c := &Adaptor{ name: gobot.DefaultName("RaspberryPi"), diff --git a/platforms/rockpi/rockpi_adaptor.go b/platforms/rockpi/rockpi_adaptor.go index 13418f86c..cf159a716 100644 --- a/platforms/rockpi/rockpi_adaptor.go +++ b/platforms/rockpi/rockpi_adaptor.go @@ -44,7 +44,7 @@ type Adaptor struct { // adaptors.WithGpiodAccess(): use character device gpiod driver instead of the default sysfs (NOT work on RockPi4C+!) // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# // adaptors.WithGpiosActiveLow(pin's): invert the pin behavior -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { sys := system.NewAccesser() c := &Adaptor{ name: gobot.DefaultName("RockPi"), diff --git a/platforms/tinkerboard/adaptor.go b/platforms/tinkerboard/adaptor.go index f63ce80c7..01f926660 100644 --- a/platforms/tinkerboard/adaptor.go +++ b/platforms/tinkerboard/adaptor.go @@ -50,7 +50,7 @@ type pwmPinDefinition struct { type Adaptor struct { name string sys *system.Accesser - mutex sync.Mutex + mutex *sync.Mutex *adaptors.AnalogPinsAdaptor *adaptors.DigitalPinsAdaptor *adaptors.PWMPinsAdaptor @@ -67,79 +67,95 @@ type Adaptor struct { // adaptors.WithGpiosActiveLow(pin's): invert the pin behavior // adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor // +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +// // note from RK3288 datasheet: "The pull direction (pullup or pulldown) for all of GPIOs are software-programmable", but // the latter is not working for any pin (armbian 22.08.7) -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +func NewAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser(system.WithDigitalPinGpiodAccess()) - c := &Adaptor{ - name: gobot.DefaultName("Tinker Board"), - sys: sys, - } - c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) - c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) - c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin, - adaptors.WithPolarityInvertedIdentifier(pwmInvertedIdentifier)) - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber) - c.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, c.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, + a := &Adaptor{ + name: gobot.DefaultName("Tinker Board"), + sys: sys, + mutex: &sync.Mutex{}, + } + + var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) + pwmPinsOpts := []adaptors.PwmPinsOptionApplier{adaptors.WithPWMPolarityInvertedIdentifier(pwmInvertedIdentifier)} + for _, opt := range opts { + switch o := opt.(type) { + case func(adaptors.DigitalPinsOptioner): + digitalPinsOpts = append(digitalPinsOpts, o) + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } + } + + a.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, a.translateAnalogPin) + a.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, a.translateDigitalPin, digitalPinsOpts...) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.translatePWMPin, pwmPinsOpts...) + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateI2cBusNumber, defaultI2cBusNumber) + a.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, a.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, defaultSpiMode, defaultSpiBitsNumber, defaultSpiMaxSpeed) - return c + return a } // Name returns the name of the Adaptor -func (c *Adaptor) Name() string { return c.name } +func (a *Adaptor) Name() string { return a.name } // SetName sets the name of the Adaptor -func (c *Adaptor) SetName(n string) { c.name = n } +func (a *Adaptor) SetName(n string) { a.name = n } // Connect create new connection to board and pins. -func (c *Adaptor) Connect() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() - if err := c.SpiBusAdaptor.Connect(); err != nil { + if err := a.SpiBusAdaptor.Connect(); err != nil { return err } - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - if err := c.AnalogPinsAdaptor.Connect(); err != nil { + if err := a.AnalogPinsAdaptor.Connect(); err != nil { return err } - if err := c.PWMPinsAdaptor.Connect(); err != nil { + if err := a.PWMPinsAdaptor.Connect(); err != nil { return err } - return c.DigitalPinsAdaptor.Connect() + return a.DigitalPinsAdaptor.Connect() } // Finalize closes connection to board, pins and bus -func (c *Adaptor) Finalize() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() - err := c.DigitalPinsAdaptor.Finalize() + err := a.DigitalPinsAdaptor.Finalize() - if e := c.PWMPinsAdaptor.Finalize(); e != nil { + if e := a.PWMPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + if e := a.AnalogPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.SpiBusAdaptor.Finalize(); e != nil { + if e := a.SpiBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } return err } -func (c *Adaptor) validateSpiBusNumber(busNr int) error { +func (a *Adaptor) validateSpiBusNumber(busNr int) error { // Valid bus numbers are [0,2] which corresponds to /dev/spidev0.x, /dev/spidev2.x // x is the chip number <255 if (busNr != 0) && (busNr != 2) { @@ -148,7 +164,7 @@ func (c *Adaptor) validateSpiBusNumber(busNr int) error { return nil } -func (c *Adaptor) validateI2cBusNumber(busNr int) error { +func (a *Adaptor) validateI2cBusNumber(busNr int) error { // Valid bus number is [0..4] which corresponds to /dev/i2c-0 through /dev/i2c-4. // We don't support "/dev/i2c-6 DesignWare HDMI". if (busNr < 0) || (busNr > 4) { @@ -157,14 +173,14 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } -func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { +func (a *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { pinInfo, ok := analogPinDefinitions[id] if !ok { return "", false, false, 0, fmt.Errorf("'%s' is not a valid id for a analog pin", id) } path := pinInfo.path - info, err := c.sys.Stat(path) + info, err := a.sys.Stat(path) if err != nil { return "", false, false, 0, fmt.Errorf("Error (%v) on access '%s'", err, path) } @@ -175,12 +191,12 @@ func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, err return path, pinInfo.r, pinInfo.w, pinInfo.bufLen, nil } -func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { +func (a *Adaptor) translateDigitalPin(id string) (string, int, error) { pindef, ok := gpioPinDefinitions[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id) } - if c.sys.IsSysfsDigitalPinAccess() { + if a.sys.IsSysfsDigitalPinAccess() { return "", pindef.sysfs, nil } chip := fmt.Sprintf("gpiochip%d", pindef.cdev.chip) @@ -188,12 +204,12 @@ func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { return chip, line, nil } -func (c *Adaptor) translatePWMPin(id string) (string, int, error) { +func (a *Adaptor) translatePWMPin(id string) (string, int, error) { pinInfo, ok := pwmPinDefinitions[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a PWM pin", id) } - path, err := pinInfo.findPWMDir(c.sys) + path, err := pinInfo.findPWMDir(a.sys) if err != nil { return "", -1, err } diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 71b95b39d..0b6a5fe6d 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -13,6 +13,7 @@ import ( "gobot.io/x/gobot/v2/drivers/aio" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" + "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" ) @@ -79,13 +80,31 @@ func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system. return a, fs } -func TestName(t *testing.T) { +func TestNewAdaptor(t *testing.T) { + // arrange & act a := NewAdaptor() + // assert + assert.IsType(t, &Adaptor{}, a) assert.True(t, strings.HasPrefix(a.Name(), "Tinker Board")) + assert.NotNil(t, a.sys) + assert.NotNil(t, a.mutex) + assert.NotNil(t, a.AnalogPinsAdaptor) + assert.NotNil(t, a.DigitalPinsAdaptor) + assert.NotNil(t, a.PWMPinsAdaptor) + assert.NotNil(t, a.I2cBusAdaptor) + assert.NotNil(t, a.SpiBusAdaptor) + // act & assert a.SetName("NewName") assert.Equal(t, "NewName", a.Name()) } +func TestNewAdaptorWithOption(t *testing.T) { + // arrange & act + a := NewAdaptor(adaptors.WithGpiosActiveLow("1")) + // assert + require.NoError(t, a.Connect()) +} + func TestDigitalIO(t *testing.T) { // only basic tests needed, further tests are done in "digitalpinsadaptor.go" a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) @@ -101,7 +120,7 @@ func TestDigitalIO(t *testing.T) { require.NoError(t, a.Finalize()) } -func TestAnalog(t *testing.T) { +func TestAnalogRead(t *testing.T) { mockPaths := []string{ "/sys/class/thermal/thermal_zone0/temp", } @@ -124,47 +143,50 @@ func TestAnalog(t *testing.T) { require.NoError(t, a.Finalize()) } -func TestInvalidPWMPin(t *testing.T) { - a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) - preparePwmFs(fs) - - err := a.PwmWrite("666", 42) - require.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") - - err = a.ServoWrite("666", 120) - require.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") - - err = a.PwmWrite("3", 42) - require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") - - err = a.ServoWrite("3", 120) - require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") -} - func TestPwmWrite(t *testing.T) { + // arrange a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) preparePwmFs(fs) - + // act err := a.PwmWrite("33", 100) + // assert require.NoError(t, err) - assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, strconv.Itoa(10000000), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, "10000000", fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) + // act & assert invalid pin + err = a.PwmWrite("666", 42) + require.ErrorContains(t, err, "'666' is not a valid id for a PWM pin") - // prepare 50Hz for servos - fs.Files[pwmPeriodPath].Contents = strconv.Itoa(20000000) - err = a.ServoWrite("33", 0) - require.NoError(t, err) + require.NoError(t, a.Finalize()) +} +func TestServoWrite(t *testing.T) { + // arrange: prepare 50Hz for servos + const ( + pin = "33" + fiftyHzNano = 20000000 + ) + a := NewAdaptor(adaptors.WithPWMDefaultPeriodForPin(pin, fiftyHzNano)) + fs := a.sys.UseMockFilesystem(pwmMockPaths) + preparePwmFs(fs) + require.NoError(t, a.Connect()) + // act & assert for 0° (min default value) + err := a.ServoWrite(pin, 0) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) - - err = a.ServoWrite("33", 180) + // act & assert for 180° (max default value) + err = a.ServoWrite(pin, 180) require.NoError(t, err) - + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "2500000", fs.Files[pwmDutyCyclePath].Contents) + // act & assert invalid pins + err = a.ServoWrite("3", 120) + require.ErrorContains(t, err, "'3' is not a valid id for a PWM pin") + require.NoError(t, a.Finalize()) } diff --git a/platforms/upboard/up2/adaptor.go b/platforms/upboard/up2/adaptor.go index d4a80660c..b58d1258d 100644 --- a/platforms/upboard/up2/adaptor.go +++ b/platforms/upboard/up2/adaptor.go @@ -56,77 +56,93 @@ type Adaptor struct { // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor { +// +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +func NewAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser() - c := &Adaptor{ + a := &Adaptor{ name: gobot.DefaultName("UP2"), sys: sys, ledPath: "/sys/class/leds/upboard:%s:/brightness", pinmap: fixedPins, } - c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) - c.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, c.translatePWMPin) - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber) - c.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, c.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, + + var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) + var pwmPinsOpts []adaptors.PwmPinsOptionApplier + for _, opt := range opts { + switch o := opt.(type) { + case func(adaptors.DigitalPinsOptioner): + digitalPinsOpts = append(digitalPinsOpts, o) + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } + } + + a.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, a.translateDigitalPin, digitalPinsOpts...) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.translatePWMPin, pwmPinsOpts...) + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateI2cBusNumber, defaultI2cBusNumber) + a.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, a.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, defaultSpiMode, defaultSpiBitsNumber, defaultSpiMaxSpeed) - return c + return a } // Name returns the name of the Adaptor -func (c *Adaptor) Name() string { return c.name } +func (a *Adaptor) Name() string { return a.name } // SetName sets the name of the Adaptor -func (c *Adaptor) SetName(n string) { c.name = n } +func (a *Adaptor) SetName(n string) { a.name = n } // Connect create new connection to board and pins. -func (c *Adaptor) Connect() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() - if err := c.SpiBusAdaptor.Connect(); err != nil { + if err := a.SpiBusAdaptor.Connect(); err != nil { return err } - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - if err := c.PWMPinsAdaptor.Connect(); err != nil { + if err := a.PWMPinsAdaptor.Connect(); err != nil { return err } - return c.DigitalPinsAdaptor.Connect() + return a.DigitalPinsAdaptor.Connect() } // Finalize closes connection to board and pins -func (c *Adaptor) Finalize() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() - err := c.DigitalPinsAdaptor.Finalize() + err := a.DigitalPinsAdaptor.Finalize() - if e := c.PWMPinsAdaptor.Finalize(); e != nil { + if e := a.PWMPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.SpiBusAdaptor.Finalize(); e != nil { + if e := a.SpiBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } return err } // DigitalWrite writes digital value to the specified pin. -func (c *Adaptor) DigitalWrite(id string, val byte) error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) DigitalWrite(id string, val byte) error { + a.mutex.Lock() + defer a.mutex.Unlock() // is it one of the built-in LEDs? if id == LEDRed || id == LEDBlue || id == LEDGreen || id == LEDYellow { - pinPath := fmt.Sprintf(c.ledPath, id) - fi, err := c.sys.OpenFile(pinPath, os.O_WRONLY|os.O_APPEND, 0o666) + pinPath := fmt.Sprintf(a.ledPath, id) + fi, err := a.sys.OpenFile(pinPath, os.O_WRONLY|os.O_APPEND, 0o666) defer fi.Close() //nolint:staticcheck // for historical reasons if err != nil { return err @@ -135,10 +151,10 @@ func (c *Adaptor) DigitalWrite(id string, val byte) error { return err } - return c.DigitalPinsAdaptor.DigitalWrite(id, val) + return a.DigitalPinsAdaptor.DigitalWrite(id, val) } -func (c *Adaptor) validateSpiBusNumber(busNr int) error { +func (a *Adaptor) validateSpiBusNumber(busNr int) error { // Valid bus numbers are [0,1] which corresponds to /dev/spidev0.x through /dev/spidev1.x. // x is the chip number <255 if (busNr < 0) || (busNr > 1) { @@ -147,7 +163,7 @@ func (c *Adaptor) validateSpiBusNumber(busNr int) error { return nil } -func (c *Adaptor) validateI2cBusNumber(busNr int) error { +func (a *Adaptor) validateI2cBusNumber(busNr int) error { // Valid bus number is [5..6] which corresponds to /dev/i2c-5 through /dev/i2c-6. if (busNr < 5) || (busNr > 6) { return fmt.Errorf("Bus number %d out of range", busNr) @@ -155,15 +171,15 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } -func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { - if val, ok := c.pinmap[id]; ok { +func (a *Adaptor) translateDigitalPin(id string) (string, int, error) { + if val, ok := a.pinmap[id]; ok { return "", val.pin, nil } return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id) } -func (c *Adaptor) translatePWMPin(id string) (string, int, error) { - sysPin, ok := c.pinmap[id] +func (a *Adaptor) translatePWMPin(id string) (string, int, error) { + sysPin, ok := a.pinmap[id] if !ok { return "", -1, fmt.Errorf("'%s' is not a valid id for a pin", id) } diff --git a/platforms/upboard/up2/adaptor_test.go b/platforms/upboard/up2/adaptor_test.go index 610af5b2c..6993bb5b1 100644 --- a/platforms/upboard/up2/adaptor_test.go +++ b/platforms/upboard/up2/adaptor_test.go @@ -2,6 +2,7 @@ package up2 import ( "fmt" + "strconv" "strings" "testing" @@ -12,6 +13,7 @@ import ( "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/drivers/spi" + "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" ) @@ -36,8 +38,6 @@ const ( pwmDutyCyclePath = pwmDir + "pwm0/duty_cycle" pwmPeriodPath = pwmDir + "pwm0/period" pwmPolarityPath = pwmDir + "pwm0/polarity" - - fiftyHzNano = "20000000" ) var pwmMockPaths = []string{ @@ -95,33 +95,45 @@ func TestDigitalIO(t *testing.T) { require.NoError(t, a.Finalize()) } -func TestPWM(t *testing.T) { +func TestPWMWrite(t *testing.T) { + // arrange a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) fs.Files[pwmDutyCyclePath].Contents = "0" fs.Files[pwmPeriodPath].Contents = "0" - + // act err := a.PwmWrite("32", 100) + // assert require.NoError(t, err) - assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) assert.Equal(t, "10000000", fs.Files[pwmPeriodPath].Contents) // pwmPeriodDefault assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) - // prepare 50Hz for servos - fs.Files[pwmPeriodPath].Contents = fiftyHzNano - err = a.ServoWrite("32", 0) - require.NoError(t, err) + require.NoError(t, a.Finalize()) +} +func TestServoWrite(t *testing.T) { + // arrange: prepare 50Hz for servos + const ( + pin = "32" + fiftyHzNano = 20000000 + ) + a := NewAdaptor(adaptors.WithPWMDefaultPeriodForPin(pin, fiftyHzNano)) + fs := a.sys.UseMockFilesystem(pwmMockPaths) + require.NoError(t, a.Connect()) + fs.Files[pwmDutyCyclePath].Contents = "0" + fs.Files[pwmPeriodPath].Contents = "0" + // act & assert for 0° (min default value) + err := a.ServoWrite(pin, 0) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) - assert.Equal(t, fiftyHzNano, fs.Files[pwmPeriodPath].Contents) - - err = a.ServoWrite("32", 180) + // act & assert for 180° (max default value) + err = a.ServoWrite(pin, 180) require.NoError(t, err) - + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwmPeriodPath].Contents) assert.Equal(t, "2500000", fs.Files[pwmDutyCyclePath].Contents) - assert.Equal(t, fiftyHzNano, fs.Files[pwmPeriodPath].Contents) require.NoError(t, a.Finalize()) } From a2690d2b151c18aaf84f2c2a065729abea9427e7 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Fri, 8 Dec 2023 18:09:58 +0100 Subject: [PATCH 36/57] build(deps): module update (#1047) --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 74e58fe23..8ab13ac89 100644 --- a/go.mod +++ b/go.mod @@ -18,8 +18,8 @@ require ( github.com/warthog618/gpiod v0.8.2 go.bug.st/serial v1.6.1 gocv.io/x/gocv v0.35.0 - golang.org/x/net v0.17.0 - golang.org/x/sys v0.13.0 + golang.org/x/net v0.19.0 + golang.org/x/sys v0.15.0 periph.io/x/conn/v3 v3.7.0 periph.io/x/host/v3 v3.8.2 tinygo.org/x/bluetooth v0.8.0 @@ -31,18 +31,18 @@ require ( github.com/fatih/structs v1.1.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.1 // indirect + github.com/klauspost/compress v1.17.4 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 // indirect - github.com/nats-io/nkeys v0.4.5 // indirect + github.com/nats-io/nkeys v0.4.6 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/saltosystems/winrt-go v0.0.0-20231011131235-9071442c0c84 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/tinygo-org/cbgo v0.0.4 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/sync v0.4.0 // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/sync v0.5.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 1b2be75a9..aa4cf3f7c 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -32,8 +32,8 @@ github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 h1:7of6LJZ4 github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78/go.mod h1:YllNbhGM1UEcySxCv1BWK5lre7QLmJJ+O0ADUOo2nbc= github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e h1:xCcwD5FOXul+j1dn8xD16nbrhJkkum/Cn+jTd/u1LhY= github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM805MRKrioHYuU7iKLUyFPVKqVV6um5DAvCkUtXs= -github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g= -github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -45,8 +45,8 @@ github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 h1:BuVRHr4HHJbk1 github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= -github.com/nats-io/nkeys v0.4.5 h1:Zdz2BUlFm4fJlierwvGK+yl20IAKUm7eV6AAZXEhkPk= -github.com/nats-io/nkeys v0.4.5/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= +github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= +github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -87,18 +87,18 @@ gocv.io/x/gocv v0.35.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -106,8 +106,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= From 915d0c89b8327f3c4960c180e09c1b6ab5fe5fe7 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Mon, 11 Dec 2023 19:09:00 +0100 Subject: [PATCH 37/57] raspi(pwm): add support for sysfs and fix pi-blaster (#1048) --- examples/raspi_led_brightness.go | 2 +- examples/raspi_servo.go | 92 +++++++ examples/tinkerboard_servo.go | 2 +- platforms/adaptors/piblasterpwm_pin.go | 118 ++++++++ platforms/adaptors/piblasterpwm_pin_test.go | 79 ++++++ platforms/adaptors/pwmpinsadaptor.go | 86 +++++- platforms/adaptors/pwmpinsadaptor_test.go | 237 ++++++++++++---- platforms/adaptors/pwmpinsadaptoroptions.go | 38 ++- .../adaptors/pwmpinsadaptoroptions_test.go | 42 +++ platforms/jetson/jetson_adaptor.go | 183 +++++------- platforms/jetson/jetson_adaptor_test.go | 39 ++- platforms/jetson/jetson_pin_map.go | 7 +- platforms/jetson/pwm_pin.go | 148 ---------- platforms/jetson/pwm_pin_test.go | 79 ------ platforms/nanopi/nanopi_adaptor.go | 4 +- platforms/nanopi/nanopi_adaptor_test.go | 2 + platforms/raspi/README.md | 51 +++- platforms/raspi/pwm_pin.go | 119 -------- platforms/raspi/pwm_pin_test.go | 55 ---- platforms/raspi/raspi_adaptor.go | 202 ++++++-------- platforms/raspi/raspi_adaptor_test.go | 260 +++++++++++++----- platforms/raspi/raspi_pin_map.go | 6 + platforms/tinkerboard/adaptor.go | 4 +- platforms/tinkerboard/adaptor_test.go | 2 + system/pwmpin_sysfs_test.go | 2 +- 25 files changed, 1054 insertions(+), 805 deletions(-) create mode 100644 examples/raspi_servo.go create mode 100644 platforms/adaptors/piblasterpwm_pin.go create mode 100644 platforms/adaptors/piblasterpwm_pin_test.go delete mode 100644 platforms/jetson/pwm_pin.go delete mode 100644 platforms/jetson/pwm_pin_test.go delete mode 100644 platforms/raspi/pwm_pin.go delete mode 100644 platforms/raspi/pwm_pin_test.go diff --git a/examples/raspi_led_brightness.go b/examples/raspi_led_brightness.go index ae3da2c21..1ae9a6dc9 100644 --- a/examples/raspi_led_brightness.go +++ b/examples/raspi_led_brightness.go @@ -16,7 +16,7 @@ import ( func main() { r := raspi.NewAdaptor() - led := gpio.NewLedDriver(r, "11") + led := gpio.NewLedDriver(r, "pwm0") work := func() { brightness := uint8(0) diff --git a/examples/raspi_servo.go b/examples/raspi_servo.go new file mode 100644 index 000000000..d1f88ff65 --- /dev/null +++ b/examples/raspi_servo.go @@ -0,0 +1,92 @@ +//go:build example +// +build example + +// Do not build by default. + +package main + +import ( + "fmt" + "log" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/gpio" + "gobot.io/x/gobot/v2/platforms/adaptors" + "gobot.io/x/gobot/v2/platforms/raspi" +) + +// Wiring +// PWM Raspi: header pin 12 (GPIO18-PWM0), please refer to the README.md, located in the folder of raspi platform, on +// how to activate the pwm support. +// Servo: orange (PWM), black (GND), red (VCC) 4-6V (please read the manual of your device) +func main() { + const ( + pwmPin = "pwm0" + wait = 3 * time.Second + + fiftyHzNanos = 20 * 1000 * 1000 // 50Hz = 0.02 sec = 20 ms + ) + // usually a frequency of 50Hz is used for servos, most servos have 0.5 ms..2.5 ms for 0-180°, however the mapping + // can be changed with options... + // + // for usage of pi-blaster driver just add the option "adaptors.WithPWMUsePiBlaster()" and use your pin number + // instead of "pwm0" + adaptor := raspi.NewAdaptor(adaptors.WithPWMDefaultPeriodForPin(pwmPin, fiftyHzNanos)) + servo := gpio.NewServoDriver(adaptor, pwmPin) + + work := func() { + fmt.Printf("first move to minimal position for %s...\n", wait) + if err := servo.ToMin(); err != nil { + log.Println(err) + } + + time.Sleep(wait) + + fmt.Printf("second move to center position for %s...\n", wait) + if err := servo.ToCenter(); err != nil { + log.Println(err) + } + + time.Sleep(wait) + + fmt.Printf("third move to maximal position for %s...\n", wait) + if err := servo.ToMax(); err != nil { + log.Println(err) + } + + time.Sleep(wait) + + fmt.Println("finally move 0-180° (or what your servo do for the new mapping) and back forever...") + angle := 0 + fadeAmount := 45 + + gobot.Every(time.Second, func() { + if err := servo.Move(byte(angle)); err != nil { + log.Println(err) + } + angle = angle + fadeAmount + if angle < 0 || angle > 180 { + if angle < 0 { + angle = 0 + } + if angle > 180 { + angle = 180 + } + // change direction and recalculate + fadeAmount = -fadeAmount + angle = angle + fadeAmount + } + }) + } + + robot := gobot.NewRobot("motorBot", + []gobot.Connection{adaptor}, + []gobot.Device{servo}, + work, + ) + + if err := robot.Start(); err != nil { + panic(err) + } +} diff --git a/examples/tinkerboard_servo.go b/examples/tinkerboard_servo.go index 4e81503b7..3c26b52b7 100644 --- a/examples/tinkerboard_servo.go +++ b/examples/tinkerboard_servo.go @@ -17,7 +17,7 @@ import ( ) // Wiring -// PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) +// PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) // PWM Tinkerboard: header pin 33 (PWM2) or pin 32 (PWM3) func main() { const ( diff --git a/platforms/adaptors/piblasterpwm_pin.go b/platforms/adaptors/piblasterpwm_pin.go new file mode 100644 index 000000000..15f4b65c1 --- /dev/null +++ b/platforms/adaptors/piblasterpwm_pin.go @@ -0,0 +1,118 @@ +package adaptors + +import ( + "fmt" + "os" + "strconv" + + "gobot.io/x/gobot/v2/system" +) + +const ( + piBlasterPath = "/dev/pi-blaster" + piBlasterMinDutyNano = 10000 // 10 us +) + +// piBlasterPWMPin is the Raspberry Pi implementation of the PWMPinner interface. +// It uses Pi Blaster. +type piBlasterPWMPin struct { + sys *system.Accesser + pin string + dc uint32 + period uint32 +} + +// newPiBlasterPWMPin returns a new PWM pin for pi-blaster access. +func newPiBlasterPWMPin(sys *system.Accesser, pinNo int) *piBlasterPWMPin { + return &piBlasterPWMPin{ + sys: sys, + pin: strconv.Itoa(pinNo), + } +} + +// Export exports the pin for use by the Raspberry Pi +func (p *piBlasterPWMPin) Export() error { + return nil +} + +// Unexport releases the pin from the operating system +func (p *piBlasterPWMPin) Unexport() error { + return p.writeValue(fmt.Sprintf("release %v\n", p.pin)) +} + +// Enabled returns always true for "enabled" +func (p *piBlasterPWMPin) Enabled() (bool, error) { + return true, nil +} + +// SetEnabled do nothing for PiBlaster +func (p *piBlasterPWMPin) SetEnabled(e bool) error { + return nil +} + +// Polarity returns always true for "normal" +func (p *piBlasterPWMPin) Polarity() (bool, error) { + return true, nil +} + +// SetPolarity does not do anything when using PiBlaster +func (p *piBlasterPWMPin) SetPolarity(bool) error { + return nil +} + +// Period returns the cached PWM period for pin +func (p *piBlasterPWMPin) Period() (uint32, error) { + return p.period, nil +} + +// SetPeriod uses PiBlaster setting and cannot be changed. We allow setting once here to define a base period for +// ServoWrite(). see https://github.com/sarfata/pi-blaster#how-to-adjust-the-frequency-and-the-resolution-of-the-pwm +func (p *piBlasterPWMPin) SetPeriod(period uint32) error { + if p.period != 0 { + return fmt.Errorf("the period of PWM pins needs to be set to '%d' in pi-blaster source code", period) + } + p.period = period + return nil +} + +// DutyCycle returns the duty cycle for the pin +func (p *piBlasterPWMPin) DutyCycle() (uint32, error) { + return p.dc, nil +} + +// SetDutyCycle writes the duty cycle to the pin +func (p *piBlasterPWMPin) SetDutyCycle(dutyNanos uint32) error { + if p.period == 0 { + return fmt.Errorf("pi-blaster PWM pin period not set while try to set duty cycle to '%d'", dutyNanos) + } + + if dutyNanos > p.period { + return fmt.Errorf("the duty cycle (%d) exceeds period (%d) for pi-blaster", dutyNanos, p.period) + } + + // never go below minimum allowed duty for pi blaster unless the duty equals to 0 + if dutyNanos < piBlasterMinDutyNano && dutyNanos != 0 { + dutyNanos = piBlasterMinDutyNano + fmt.Printf("duty cycle value limited to '%d' ns for pi-blaster", dutyNanos) + } + + duty := float64(dutyNanos) / float64(p.period) + if err := p.writeValue(fmt.Sprintf("%v=%v\n", p.pin, duty)); err != nil { + return err + } + + p.dc = dutyNanos + return nil +} + +func (p *piBlasterPWMPin) writeValue(data string) error { + fi, err := p.sys.OpenFile(piBlasterPath, os.O_WRONLY|os.O_APPEND, 0o644) + defer fi.Close() //nolint:staticcheck // for historical reasons + + if err != nil { + return err + } + + _, err = fi.WriteString(data) + return err +} diff --git a/platforms/adaptors/piblasterpwm_pin_test.go b/platforms/adaptors/piblasterpwm_pin_test.go new file mode 100644 index 000000000..bd4c48210 --- /dev/null +++ b/platforms/adaptors/piblasterpwm_pin_test.go @@ -0,0 +1,79 @@ +package adaptors + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/system" +) + +var _ gobot.PWMPinner = (*piBlasterPWMPin)(nil) + +func TestPiBlasterPWMPin(t *testing.T) { + // arrange + const path = "/dev/pi-blaster" + a := system.NewAccesser() + a.UseMockFilesystem([]string{path}) + pin := newPiBlasterPWMPin(a, 1) + // act & assert: activate pin for usage + require.NoError(t, pin.Export()) + require.NoError(t, pin.SetEnabled(true)) + // act & assert: get and set polarity + val, err := pin.Polarity() + require.NoError(t, err) + assert.True(t, val) + require.NoError(t, pin.SetPolarity(false)) + polarity, err := pin.Polarity() + assert.True(t, polarity) + require.NoError(t, err) + // act & assert: get and set period + period, err := pin.Period() + require.NoError(t, err) + assert.Equal(t, uint32(0), period) + require.NoError(t, pin.SetPeriod(20000000)) + period, err = pin.Period() + require.NoError(t, err) + assert.Equal(t, uint32(20000000), period) + err = pin.SetPeriod(10000000) + require.EqualError(t, err, "the period of PWM pins needs to be set to '10000000' in pi-blaster source code") + // act & assert: cleanup + require.NoError(t, pin.Unexport()) +} + +func TestPiBlasterPWMPin_DutyCycle(t *testing.T) { + // arrange + const path = "/dev/pi-blaster" + a := system.NewAccesser() + a.UseMockFilesystem([]string{path}) + pin := newPiBlasterPWMPin(a, 1) + // act & assert: activate pin for usage + require.NoError(t, pin.Export()) + require.NoError(t, pin.SetEnabled(true)) + // act & assert zero + dc, err := pin.DutyCycle() + require.NoError(t, err) + assert.Equal(t, uint32(0), dc) + // act & assert error without period set, the value remains zero + err = pin.SetDutyCycle(10000) + require.EqualError(t, err, "pi-blaster PWM pin period not set while try to set duty cycle to '10000'") + dc, err = pin.DutyCycle() + require.NoError(t, err) + assert.Equal(t, uint32(0), dc) + // arrange, act & assert a value + pin.period = 20000000 + require.NoError(t, pin.SetDutyCycle(10000)) + dc, err = pin.DutyCycle() + require.NoError(t, err) + assert.Equal(t, uint32(10000), dc) + // act & assert error on over limit, the value remains + err = pin.SetDutyCycle(20000001) + require.EqualError(t, err, "the duty cycle (20000001) exceeds period (20000000) for pi-blaster") + dc, err = pin.DutyCycle() + require.NoError(t, err) + assert.Equal(t, uint32(10000), dc) + // act & assert: cleanup + require.NoError(t, pin.Unexport()) +} diff --git a/platforms/adaptors/pwmpinsadaptor.go b/platforms/adaptors/pwmpinsadaptor.go index baa8bc0dd..16388bba2 100644 --- a/platforms/adaptors/pwmpinsadaptor.go +++ b/platforms/adaptors/pwmpinsadaptor.go @@ -34,7 +34,10 @@ type pwmPinServoScale struct { // pwmPinConfiguration contains all changeable attributes of the adaptor. type pwmPinsConfiguration struct { initialize pwmPinInitializer + usePiBlasterPin bool periodDefault uint32 + periodMinimum uint32 + dutyRateMinimum float64 // is the minimal relation of duty/period (except 0.0) polarityNormalIdentifier string polarityInvertedIdentifier string adjustDutyOnSetPeriod bool @@ -73,7 +76,7 @@ func NewPWMPinsAdaptor(sys *system.Accesser, t pwmPinTranslator, opts ...PwmPins pinsDefaultPeriod: make(map[string]uint32), pinsServoScale: make(map[string]pwmPinServoScale), polarityNormalIdentifier: "normal", - polarityInvertedIdentifier: "inverted", + polarityInvertedIdentifier: "inversed", adjustDutyOnSetPeriod: true, }, } @@ -91,12 +94,28 @@ func WithPWMPinInitializer(pc pwmPinInitializer) pwmPinsInitializeOption { return pwmPinsInitializeOption(pc) } +// WithPWMUsePiBlaster substitute the default sysfs-implementation for PWM-pins by the implementation for pi-blaster. +func WithPWMUsePiBlaster() pwmPinsUsePiBlasterPinOption { + return pwmPinsUsePiBlasterPinOption(true) +} + // WithPWMDefaultPeriod substitute the default period of 10 ms (100 Hz) for all created pins. func WithPWMDefaultPeriod(periodNanoSec uint32) pwmPinsPeriodDefaultOption { return pwmPinsPeriodDefaultOption(periodNanoSec) } -// WithPWMPolarityInvertedIdentifier use the given identifier, which will replace the default "inverted". +// WithPWMMinimumPeriod substitute the default minimum period limit of 0 nanoseconds. +func WithPWMMinimumPeriod(periodNanoSec uint32) pwmPinsPeriodMinimumOption { + return pwmPinsPeriodMinimumOption(periodNanoSec) +} + +// WithPWMMinimumDutyRate substitute the default minimum duty rate of 1/period. The given limit only come into effect, +// if the rate is > 0, because a rate of 0.0 is always allowed. +func WithPWMMinimumDutyRate(dutyRate float64) pwmPinsDutyRateMinimumOption { + return pwmPinsDutyRateMinimumOption(dutyRate) +} + +// WithPWMPolarityInvertedIdentifier use the given identifier, which will replace the default "inversed". func WithPWMPolarityInvertedIdentifier(identifier string) pwmPinsPolarityInvertedIdentifierOption { return pwmPinsPolarityInvertedIdentifierOption(identifier) } @@ -132,6 +151,11 @@ func (a *PWMPinsAdaptor) Connect() error { defer a.mutex.Unlock() a.pins = make(map[string]gobot.PWMPinner) + + if a.pwmPinsCfg.dutyRateMinimum == 0 && a.pwmPinsCfg.periodDefault > 0 { + a.pwmPinsCfg.dutyRateMinimum = 1 / float64(a.pwmPinsCfg.periodDefault) + } + return nil } @@ -164,12 +188,18 @@ func (a *PWMPinsAdaptor) PwmWrite(id string, val byte) error { if err != nil { return err } - period, err := pin.Period() + periodNanos, err := pin.Period() if err != nil { return err } - duty := gobot.FromScale(float64(val), 0, 255.0) - return pin.SetDutyCycle(uint32(float64(period) * duty)) + + dutyNanos := float64(periodNanos) * gobot.FromScale(float64(val), 0, 255.0) + + if err := a.validateDutyCycle(id, dutyNanos, float64(periodNanos)); err != nil { + return err + } + + return pin.SetDutyCycle(uint32(dutyNanos)) } // ServoWrite writes a servo signal to the specified pin. The given angle is between 0 and 180°. @@ -181,13 +211,14 @@ func (a *PWMPinsAdaptor) ServoWrite(id string, angle byte) error { if err != nil { return err } - period, err := pin.Period() // nanoseconds + periodNanos, err := pin.Period() if err != nil { return err } - if period != fiftyHzNanos { - log.Printf("WARNING: the PWM acts with a period of %d, but should use %d (50Hz) for servos\n", period, fiftyHzNanos) + if periodNanos != fiftyHzNanos { + log.Printf("WARNING: the PWM acts with a period of %d, but should use %d (50Hz) for servos\n", + periodNanos, fiftyHzNanos) } scale, ok := a.pwmPinsCfg.pinsServoScale[id] @@ -195,10 +226,15 @@ func (a *PWMPinsAdaptor) ServoWrite(id string, angle byte) error { return fmt.Errorf("no scaler found for servo pin '%s'", id) } - duty := gobot.ToScale(gobot.FromScale(float64(angle), + dutyNanos := gobot.ToScale(gobot.FromScale(float64(angle), scale.minDegree, scale.maxDegree), float64(scale.minDuty), float64(scale.maxDuty)) - return pin.SetDutyCycle(uint32(duty)) + + if err := a.validateDutyCycle(id, dutyNanos, float64(periodNanos)); err != nil { + return err + } + + return pin.SetDutyCycle(uint32(dutyNanos)) } // SetPeriod adjusts the period of the specified PWM pin immediately. @@ -286,7 +322,13 @@ func (a *PWMPinsAdaptor) pwmPin(id string) (gobot.PWMPinner, error) { if err != nil { return nil, err } - pin = a.sys.NewPWMPin(path, channel, a.pwmPinsCfg.polarityNormalIdentifier, a.pwmPinsCfg.polarityInvertedIdentifier) + + if a.pwmPinsCfg.usePiBlasterPin { + pin = newPiBlasterPWMPin(a.sys, channel) + } else { + pin = a.sys.NewPWMPin(path, channel, a.pwmPinsCfg.polarityNormalIdentifier, + a.pwmPinsCfg.polarityInvertedIdentifier) + } if err := a.pwmPinsCfg.initialize(id, pin); err != nil { return nil, err } @@ -296,6 +338,28 @@ func (a *PWMPinsAdaptor) pwmPin(id string) (gobot.PWMPinner, error) { return pin, nil } +func (a *PWMPinsAdaptor) validateDutyCycle(id string, dutyNanos, periodNanos float64) error { + if periodNanos == 0 { + return nil + } + + if dutyNanos > periodNanos { + return fmt.Errorf("duty cycle (%d) exceeds period (%d) for PWM pin id '%s'", + uint32(dutyNanos), uint32(periodNanos), id) + } + + if dutyNanos == 0 { + return nil + } + + rate := dutyNanos / periodNanos + if rate < a.pwmPinsCfg.dutyRateMinimum { + return fmt.Errorf("duty rate (%.8f) is lower than allowed (%.8f) for PWM pin id '%s'", + rate, a.pwmPinsCfg.dutyRateMinimum, id) + } + return nil +} + // setPeriod adjusts the PWM period of the given pin. If duty cycle is already set and this feature is not suppressed, // also this value will be adjusted in the same ratio. The order of writing the values must be observed, otherwise an // error occur "write error: Invalid argument". diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index 4635c90fb..3dfc595fe 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -17,23 +17,32 @@ import ( ) const ( - pwmDir = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/" //nolint:gosec // false positive - pwmPwm0Dir = pwmDir + "pwm44/" - pwmExportPath = pwmDir + "export" - pwmUnexportPath = pwmDir + "unexport" - pwmEnablePath = pwmPwm0Dir + "enable" - pwmPeriodPath = pwmPwm0Dir + "period" - pwmDutyCyclePath = pwmPwm0Dir + "duty_cycle" - pwmPolarityPath = pwmPwm0Dir + "polarity" + pwmDir = "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/" //nolint:gosec // false positive + pwmPwm44Dir = pwmDir + "pwm44/" + pwmPwm47Dir = pwmDir + "pwm47/" + pwmExportPath = pwmDir + "export" + pwmUnexportPath = pwmDir + "unexport" + pwm44EnablePath = pwmPwm44Dir + "enable" + pwm44PeriodPath = pwmPwm44Dir + "period" + pwm44DutyCyclePath = pwmPwm44Dir + "duty_cycle" + pwm44PolarityPath = pwmPwm44Dir + "polarity" + pwm47EnablePath = pwmPwm47Dir + "enable" + pwm47PeriodPath = pwmPwm47Dir + "period" + pwm47DutyCyclePath = pwmPwm47Dir + "duty_cycle" + pwm47PolarityPath = pwmPwm47Dir + "polarity" ) var pwmMockPaths = []string{ pwmExportPath, pwmUnexportPath, - pwmEnablePath, - pwmPeriodPath, - pwmDutyCyclePath, - pwmPolarityPath, + pwm44EnablePath, + pwm44PeriodPath, + pwm44DutyCyclePath, + pwm44PolarityPath, + pwm47EnablePath, + pwm47PeriodPath, + pwm47DutyCyclePath, + pwm47PolarityPath, } // make sure that this PWMPinsAdaptor fulfills all the required interfaces @@ -47,10 +56,10 @@ func initTestPWMPinsAdaptorWithMockedFilesystem(mockPaths []string) (*PWMPinsAda sys := system.NewAccesser() fs := sys.UseMockFilesystem(mockPaths) a := NewPWMPinsAdaptor(sys, testPWMPinTranslator) - fs.Files[pwmEnablePath].Contents = "0" - fs.Files[pwmPeriodPath].Contents = "0" - fs.Files[pwmDutyCyclePath].Contents = "0" - fs.Files[pwmPolarityPath].Contents = a.pwmPinsCfg.polarityInvertedIdentifier + fs.Files[pwm44EnablePath].Contents = "0" + fs.Files[pwm44PeriodPath].Contents = "0" + fs.Files[pwm44DutyCyclePath].Contents = "0" + fs.Files[pwm44PolarityPath].Contents = a.pwmPinsCfg.polarityInvertedIdentifier if err := a.Connect(); err != nil { panic(err) } @@ -62,7 +71,7 @@ func testPWMPinTranslator(id string) (string, int, error) { if err != nil { return "", -1, fmt.Errorf("'%s' is not a valid id of a PWM pin", id) } - channel = channel + 11 // just for tests + channel = channel + 11 // just for tests, 33=>pwm0, 36=>pwm3 return pwmDir, channel, err } @@ -74,7 +83,7 @@ func TestNewPWMPinsAdaptor(t *testing.T) { // assert assert.Equal(t, uint32(pwmPeriodDefault), a.pwmPinsCfg.periodDefault) assert.Equal(t, "normal", a.pwmPinsCfg.polarityNormalIdentifier) - assert.Equal(t, "inverted", a.pwmPinsCfg.polarityInvertedIdentifier) + assert.Equal(t, "inversed", a.pwmPinsCfg.polarityInvertedIdentifier) assert.True(t, a.pwmPinsCfg.adjustDutyOnSetPeriod) } @@ -97,8 +106,8 @@ func TestPWMPinsFinalize(t *testing.T) { sys := system.NewAccesser() fs := sys.UseMockFilesystem(pwmMockPaths) a := NewPWMPinsAdaptor(sys, testPWMPinTranslator) - fs.Files[pwmPeriodPath].Contents = "0" - fs.Files[pwmDutyCyclePath].Contents = "0" + fs.Files[pwm44PeriodPath].Contents = "0" + fs.Files[pwm44DutyCyclePath].Contents = "0" // assert that finalize before connect is working require.NoError(t, a.Finalize()) // arrange @@ -140,30 +149,136 @@ func TestPWMPinsReConnect(t *testing.T) { assert.Empty(t, a.pins) } -func TestPwmWrite(t *testing.T) { - a, fs := initTestPWMPinsAdaptorWithMockedFilesystem(pwmMockPaths) - - err := a.PwmWrite("33", 100) +func TestPWMPinsCache(t *testing.T) { + // arrange + a, _ := initTestPWMPinsAdaptorWithMockedFilesystem(pwmMockPaths) + // act + firstSysPin, err := a.PWMPin("33") require.NoError(t, err) + secondSysPin, err := a.PWMPin("33") + require.NoError(t, err) + otherSysPin, err := a.PWMPin("36") + require.NoError(t, err) + // assert + assert.Equal(t, secondSysPin, firstSysPin) + assert.NotEqual(t, otherSysPin, firstSysPin) +} - assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) - assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - //nolint:perfsprint // ok here - assert.Equal(t, fmt.Sprintf("%d", a.pwmPinsCfg.periodDefault), fs.Files[pwmPeriodPath].Contents) - assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) - assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) - - err = a.PwmWrite("notexist", 42) - require.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") - - fs.WithWriteError = true - err = a.PwmWrite("33", 100) - require.ErrorContains(t, err, "write error") - fs.WithWriteError = false - - fs.WithReadError = true - err = a.PwmWrite("33", 100) - require.ErrorContains(t, err, "read error") +func TestPwmWrite(t *testing.T) { + tests := map[string]struct { + pin string + value byte + minimumRate float64 + simulateWriteErr bool + simulateReadErr bool + wantExport string + wantEnable string + wantPeriod string + wantDutyCycle string + wantErr string + }{ + "write_max": { + pin: "33", + value: 255, + wantExport: "44", + wantEnable: "1", + wantPeriod: "10000000", + wantDutyCycle: "10000000", + }, + "write_nearmax": { + pin: "33", + value: 254, + wantExport: "44", + wantEnable: "1", + wantPeriod: "10000000", + wantDutyCycle: "9960784", + }, + "write_mid": { + pin: "33", + value: 100, + wantExport: "44", + wantEnable: "1", + wantPeriod: "10000000", + wantDutyCycle: "3921568", + }, + "write_near min": { + pin: "33", + value: 1, + wantExport: "44", + wantEnable: "1", + wantPeriod: "10000000", + wantDutyCycle: "39215", + }, + "write_min": { + pin: "33", + value: 0, + minimumRate: 0.05, + wantExport: "44", + wantEnable: "1", + wantPeriod: "10000000", + wantDutyCycle: "0", + }, + "error_min_rate": { + pin: "33", + value: 1, + minimumRate: 0.05, + wantExport: "44", + wantEnable: "1", + wantPeriod: "10000000", + wantDutyCycle: "0", + wantErr: "is lower than allowed (0.05", + }, + "error_non_existent_pin": { + pin: "notexist", + wantEnable: "0", + wantPeriod: "0", + wantDutyCycle: "0", + wantErr: "'notexist' is not a valid id of a PWM pin", + }, + "error_write_error": { + pin: "33", + value: 10, + simulateWriteErr: true, + wantEnable: "0", + wantPeriod: "0", + wantDutyCycle: "0", + wantErr: "write error", + }, + "error_read_error": { + pin: "33", + value: 11, + simulateReadErr: true, + wantExport: "44", + wantEnable: "0", + wantPeriod: "0", + wantDutyCycle: "0", + wantErr: "read error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a, fs := initTestPWMPinsAdaptorWithMockedFilesystem(pwmMockPaths) + if tc.minimumRate > 0 { + a.pwmPinsCfg.dutyRateMinimum = tc.minimumRate + } + fs.WithWriteError = tc.simulateWriteErr + fs.WithReadError = tc.simulateReadErr + // act + err := a.PwmWrite(tc.pin, tc.value) + // assert + assert.Equal(t, tc.wantExport, fs.Files[pwmExportPath].Contents) + assert.Equal(t, tc.wantEnable, fs.Files[pwm44EnablePath].Contents) + assert.Equal(t, tc.wantPeriod, fs.Files[pwm44PeriodPath].Contents) + assert.Equal(t, tc.wantDutyCycle, fs.Files[pwm44DutyCyclePath].Contents) + if tc.wantErr != "" { + require.ErrorContains(t, err, tc.wantErr) + } else { + require.NoError(t, err) + assert.Equal(t, "normal", fs.Files[pwm44PolarityPath].Contents) + } + }) + } } func TestServoWrite(t *testing.T) { @@ -172,15 +287,15 @@ func TestServoWrite(t *testing.T) { err := a.ServoWrite("33", 0) require.NoError(t, err) assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) - assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) + assert.Equal(t, "1", fs.Files[pwm44EnablePath].Contents) //nolint:perfsprint // ok here - assert.Equal(t, fmt.Sprintf("%d", a.pwmPinsCfg.periodDefault), fs.Files[pwmPeriodPath].Contents) - assert.Equal(t, "250000", fs.Files[pwmDutyCyclePath].Contents) - assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) + assert.Equal(t, fmt.Sprintf("%d", a.pwmPinsCfg.periodDefault), fs.Files[pwm44PeriodPath].Contents) + assert.Equal(t, "250000", fs.Files[pwm44DutyCyclePath].Contents) + assert.Equal(t, "normal", fs.Files[pwm44PolarityPath].Contents) err = a.ServoWrite("33", 180) require.NoError(t, err) - assert.Equal(t, "1250000", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "1250000", fs.Files[pwm44DutyCyclePath].Contents) err = a.ServoWrite("notexist", 42) require.ErrorContains(t, err, "'notexist' is not a valid id of a PWM pin") @@ -209,15 +324,15 @@ func TestSetPeriod(t *testing.T) { // assert require.NoError(t, err) assert.Equal(t, "44", fs.Files[pwmExportPath].Contents) - assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) - assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwmPeriodPath].Contents) //nolint:perfsprint // ok here - assert.Equal(t, "0", fs.Files[pwmDutyCyclePath].Contents) - assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) + assert.Equal(t, "1", fs.Files[pwm44EnablePath].Contents) + assert.Equal(t, fmt.Sprintf("%d", newPeriod), fs.Files[pwm44PeriodPath].Contents) //nolint:perfsprint // ok here + assert.Equal(t, "0", fs.Files[pwm44DutyCyclePath].Contents) + assert.Equal(t, "normal", fs.Files[pwm44PolarityPath].Contents) // arrange test for automatic adjustment of duty cycle to lower value err = a.PwmWrite("33", 127) // 127 is a little bit smaller than 50% of period require.NoError(t, err) - assert.Equal(t, strconv.Itoa(1270000), fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, strconv.Itoa(1270000), fs.Files[pwm44DutyCyclePath].Contents) newPeriod = newPeriod / 10 // act @@ -225,7 +340,7 @@ func TestSetPeriod(t *testing.T) { // assert require.NoError(t, err) - assert.Equal(t, strconv.Itoa(127000), fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, strconv.Itoa(127000), fs.Files[pwm44DutyCyclePath].Contents) // arrange test for automatic adjustment of duty cycle to higher value newPeriod = newPeriod * 20 @@ -235,7 +350,7 @@ func TestSetPeriod(t *testing.T) { // assert require.NoError(t, err) - assert.Equal(t, strconv.Itoa(2540000), fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, strconv.Itoa(2540000), fs.Files[pwm44DutyCyclePath].Contents) // act err = a.SetPeriod("not_exist", newPeriod) @@ -255,7 +370,7 @@ func Test_PWMPin(t *testing.T) { wantErr string }{ "pin_ok": { - mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmDutyCyclePath, pwmPolarityPath}, + mockPaths: []string{pwmExportPath, pwm44EnablePath, pwm44PeriodPath, pwm44DutyCyclePath, pwm44PolarityPath}, period: "0", dutyCycle: "0", translate: translator, @@ -269,7 +384,7 @@ func Test_PWMPin(t *testing.T) { "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/export: no such file", }, "init_setenabled_error": { - mockPaths: []string{pwmExportPath, pwmPeriodPath}, + mockPaths: []string{pwmExportPath, pwm44PeriodPath}, period: "1000", translate: translator, pin: "33", @@ -277,14 +392,14 @@ func Test_PWMPin(t *testing.T) { "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/enable: no such file", }, "init_setperiod_dutycycle_no_error": { - mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmDutyCyclePath, pwmPolarityPath}, + mockPaths: []string{pwmExportPath, pwm44EnablePath, pwm44PeriodPath, pwm44DutyCyclePath, pwm44PolarityPath}, period: "0", dutyCycle: "0", translate: translator, pin: "33", }, "init_setperiod_error": { - mockPaths: []string{pwmExportPath, pwmEnablePath, pwmDutyCyclePath}, + mockPaths: []string{pwmExportPath, pwm44EnablePath, pwm44DutyCyclePath}, dutyCycle: "0", translate: translator, pin: "33", @@ -292,7 +407,7 @@ func Test_PWMPin(t *testing.T) { "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/period: no such file", }, "init_setpolarity_error": { - mockPaths: []string{pwmExportPath, pwmEnablePath, pwmPeriodPath, pwmDutyCyclePath}, + mockPaths: []string{pwmExportPath, pwm44EnablePath, pwm44PeriodPath, pwm44DutyCyclePath}, period: "0", dutyCycle: "0", translate: translator, @@ -311,10 +426,10 @@ func Test_PWMPin(t *testing.T) { sys := system.NewAccesser() fs := sys.UseMockFilesystem(tc.mockPaths) if tc.period != "" { - fs.Files[pwmPeriodPath].Contents = tc.period + fs.Files[pwm44PeriodPath].Contents = tc.period } if tc.dutyCycle != "" { - fs.Files[pwmDutyCyclePath].Contents = tc.dutyCycle + fs.Files[pwm44DutyCyclePath].Contents = tc.dutyCycle } a := NewPWMPinsAdaptor(sys, tc.translate) if err := a.Connect(); err != nil { diff --git a/platforms/adaptors/pwmpinsadaptoroptions.go b/platforms/adaptors/pwmpinsadaptoroptions.go index c6b336d92..168840470 100644 --- a/platforms/adaptors/pwmpinsadaptoroptions.go +++ b/platforms/adaptors/pwmpinsadaptoroptions.go @@ -10,12 +10,22 @@ type PwmPinsOptionApplier interface { // pwmPinInitializeOption is the type for applying another than the default initializer. type pwmPinsInitializeOption pwmPinInitializer +// pwmPinsUsePiBlasterPinOption is the type for applying the usage of the pi-blaster PWM pin implementation, which will +// replace the default sysfs-implementation for PWM-pins. +type pwmPinsUsePiBlasterPinOption bool + // pwmPinPeriodDefaultOption is the type for applying another than the default period of 10 ms (100 Hz) for all // created pins. type pwmPinsPeriodDefaultOption uint32 +// pwmPinsPeriodMinimumOption is the type for applying another than the default minimum period of "0". +type pwmPinsPeriodMinimumOption uint32 + +// pwmPinsDutyRateMinimumOption is the type for applying another than the default minimum rate of 1/period. +type pwmPinsDutyRateMinimumOption float64 + // pwmPinPolarityInvertedIdentifierOption is the type for applying another identifier, which will replace the default -// "inverted". +// "inversed". type pwmPinsPolarityInvertedIdentifierOption string // pwmPinsAdjustDutyOnSetPeriodOption is the type for applying the automatic adjustment of duty cycle on setting @@ -49,12 +59,24 @@ func (o pwmPinsInitializeOption) String() string { return "pin initializer option for PWM's" } +func (o pwmPinsUsePiBlasterPinOption) String() string { + return "pi-blaster pin implementation option for PWM's" +} + func (o pwmPinsPeriodDefaultOption) String() string { return "default period option for PWM's" } +func (o pwmPinsPeriodMinimumOption) String() string { + return "minimum period option for PWM's" +} + +func (o pwmPinsDutyRateMinimumOption) String() string { + return "minimum duty rate option for PWM's" +} + func (o pwmPinsPolarityInvertedIdentifierOption) String() string { - return "inverted identifier option for PWM's" + return "identifier for 'inversed' option for PWM's" } func (o pwmPinsAdjustDutyOnSetPeriodOption) String() string { @@ -77,10 +99,22 @@ func (o pwmPinsInitializeOption) apply(cfg *pwmPinsConfiguration) { cfg.initialize = pwmPinInitializer(o) } +func (o pwmPinsUsePiBlasterPinOption) apply(cfg *pwmPinsConfiguration) { + cfg.usePiBlasterPin = bool(o) +} + func (o pwmPinsPeriodDefaultOption) apply(cfg *pwmPinsConfiguration) { cfg.periodDefault = uint32(o) } +func (o pwmPinsPeriodMinimumOption) apply(cfg *pwmPinsConfiguration) { + cfg.periodMinimum = uint32(o) +} + +func (o pwmPinsDutyRateMinimumOption) apply(cfg *pwmPinsConfiguration) { + cfg.dutyRateMinimum = float64(o) +} + func (o pwmPinsPolarityInvertedIdentifierOption) apply(cfg *pwmPinsConfiguration) { cfg.polarityInvertedIdentifier = string(o) } diff --git a/platforms/adaptors/pwmpinsadaptoroptions_test.go b/platforms/adaptors/pwmpinsadaptoroptions_test.go index 64341272d..cf0175cb4 100644 --- a/platforms/adaptors/pwmpinsadaptoroptions_test.go +++ b/platforms/adaptors/pwmpinsadaptoroptions_test.go @@ -25,6 +25,15 @@ func TestWithPWMPinInitializer(t *testing.T) { assert.Equal(t, wantErr, err) } +func TestWithPWMUsePiBlaster(t *testing.T) { + // arrange + cfg := &pwmPinsConfiguration{usePiBlasterPin: false} + // act + WithPWMUsePiBlaster().apply(cfg) + // assert + assert.True(t, cfg.usePiBlasterPin) +} + func TestWithPWMDefaultPeriod(t *testing.T) { // arrange const newPeriod = uint32(10) @@ -35,6 +44,26 @@ func TestWithPWMDefaultPeriod(t *testing.T) { assert.Equal(t, newPeriod, cfg.periodDefault) } +func TestWithPWMMinimumPeriod(t *testing.T) { + // arrange + const newMinPeriod = uint32(10) + cfg := &pwmPinsConfiguration{periodMinimum: 23} + // act + WithPWMMinimumPeriod(newMinPeriod).apply(cfg) + // assert + assert.Equal(t, newMinPeriod, cfg.periodMinimum) +} + +func TestWithPWMMinimumDutyRate(t *testing.T) { + // arrange + const newRate = 11.0 + cfg := &pwmPinsConfiguration{dutyRateMinimum: 33} + // act + WithPWMMinimumDutyRate(newRate).apply(cfg) + // assert + assert.InDelta(t, newRate, cfg.dutyRateMinimum, 0.0) +} + func TestWithPWMPolarityInvertedIdentifier(t *testing.T) { // arrange const newPolarityIdent = "pwm_invers" @@ -146,3 +175,16 @@ func TestWithPWMServoAngleRangeForPin(t *testing.T) { }) } } + +func TestStringer(t *testing.T) { + assert.NotEmpty(t, pwmPinsInitializeOption(nil).String()) + assert.NotEmpty(t, pwmPinsUsePiBlasterPinOption(true).String()) + assert.NotEmpty(t, pwmPinsPeriodDefaultOption(1).String()) + assert.NotEmpty(t, pwmPinsPeriodMinimumOption(1).String()) + assert.NotEmpty(t, pwmPinsDutyRateMinimumOption(1).String()) + assert.NotEmpty(t, pwmPinsPolarityInvertedIdentifierOption("1").String()) + assert.NotEmpty(t, pwmPinsAdjustDutyOnSetPeriodOption(true).String()) + assert.NotEmpty(t, pwmPinsDefaultPeriodForPinOption{}.String()) + assert.NotEmpty(t, pwmPinsServoDutyScaleForPinOption{}.String()) + assert.NotEmpty(t, pwmPinsServoAngleScaleForPinOption{}.String()) +} diff --git a/platforms/jetson/jetson_adaptor.go b/platforms/jetson/jetson_adaptor.go index dacd9ede4..6ef35239a 100644 --- a/platforms/jetson/jetson_adaptor.go +++ b/platforms/jetson/jetson_adaptor.go @@ -1,7 +1,6 @@ package jetson import ( - "errors" "fmt" "sync" @@ -13,7 +12,9 @@ import ( ) const ( - pwmPeriodDefault = 3000000 // 3 ms = 333 Hz + pwmPeriodDefault = 3000000 // 3 ms = 333 Hz + pwmPeriodMinimum = 5334 + pwmDutyRateMinimum = 0.0005 // minimum duty of 1500 for default period, ~3 for minimum period defaultI2cBusNumber = 1 @@ -26,11 +27,11 @@ const ( // Adaptor is the Gobot adaptor for the Jetson Nano type Adaptor struct { - name string - sys *system.Accesser - mutex sync.Mutex - pwmPins map[string]gobot.PWMPinner + name string + sys *system.Accesser + mutex *sync.Mutex *adaptors.DigitalPinsAdaptor + *adaptors.PWMPinsAdaptor *adaptors.I2cBusAdaptor *adaptors.SpiBusAdaptor } @@ -41,143 +42,99 @@ type Adaptor struct { // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs // adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# -func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { +// +// Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] +func NewAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser() - c := &Adaptor{ - name: gobot.DefaultName("JetsonNano"), - sys: sys, + a := &Adaptor{ + name: gobot.DefaultName("JetsonNano"), + sys: sys, + mutex: &sync.Mutex{}, + } + + var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) + pwmPinsOpts := []adaptors.PwmPinsOptionApplier{ + adaptors.WithPWMDefaultPeriod(pwmPeriodDefault), + adaptors.WithPWMMinimumPeriod(pwmPeriodMinimum), + adaptors.WithPWMMinimumDutyRate(pwmDutyRateMinimum), + } + for _, opt := range opts { + switch o := opt.(type) { + case func(adaptors.DigitalPinsOptioner): + digitalPinsOpts = append(digitalPinsOpts, o) + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } } - c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...) - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber) - c.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, c.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, + + a.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, a.translateDigitalPin, digitalPinsOpts...) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.translatePWMPin, pwmPinsOpts...) + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateI2cBusNumber, defaultI2cBusNumber) + a.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, a.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, defaultSpiMode, defaultSpiBitsNumber, defaultSpiMaxSpeed) - return c + return a } // Name returns the Adaptor's name -func (c *Adaptor) Name() string { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Name() string { + a.mutex.Lock() + defer a.mutex.Unlock() - return c.name + return a.name } // SetName sets the Adaptor's name -func (c *Adaptor) SetName(n string) { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) SetName(n string) { + a.mutex.Lock() + defer a.mutex.Unlock() - c.name = n + a.name = n } // Connect create new connection to board and pins. -func (c *Adaptor) Connect() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() - if err := c.SpiBusAdaptor.Connect(); err != nil { + if err := a.SpiBusAdaptor.Connect(); err != nil { return err } - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - c.pwmPins = make(map[string]gobot.PWMPinner) - return c.DigitalPinsAdaptor.Connect() + if err := a.PWMPinsAdaptor.Connect(); err != nil { + return err + } + + return a.DigitalPinsAdaptor.Connect() } // Finalize closes connection to board and pins -func (c *Adaptor) Finalize() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() - err := c.DigitalPinsAdaptor.Finalize() + err := a.DigitalPinsAdaptor.Finalize() - for _, pin := range c.pwmPins { - if pin != nil { - if perr := pin.Unexport(); err != nil { - err = multierror.Append(err, perr) - } - } + if e := a.PWMPinsAdaptor.Finalize(); e != nil { + err = multierror.Append(err, e) } - c.pwmPins = nil - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.SpiBusAdaptor.Finalize(); e != nil { + if e := a.SpiBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } return err } -// PWMPin returns a Jetson Nano. PWMPin which provides the gobot.PWMPinner interface -func (c *Adaptor) PWMPin(pin string) (gobot.PWMPinner, error) { - c.mutex.Lock() - defer c.mutex.Unlock() - - return c.pwmPin(pin) -} - -// PwmWrite writes a PWM signal to the specified pin -func (c *Adaptor) PwmWrite(pin string, val byte) error { - c.mutex.Lock() - defer c.mutex.Unlock() - - sysPin, err := c.pwmPin(pin) - if err != nil { - return err - } - - duty := uint32(gobot.FromScale(float64(val), 0, 255) * float64(pwmPeriodDefault)) - return sysPin.SetDutyCycle(duty) -} - -// ServoWrite writes a servo signal to the specified pin -func (c *Adaptor) ServoWrite(pin string, angle byte) error { - c.mutex.Lock() - defer c.mutex.Unlock() - - sysPin, err := c.pwmPin(pin) - if err != nil { - return err - } - - duty := uint32(gobot.FromScale(float64(angle), 0, 180) * float64(pwmPeriodDefault)) - return sysPin.SetDutyCycle(duty) -} - -func (c *Adaptor) pwmPin(pin string) (gobot.PWMPinner, error) { - if c.pwmPins == nil { - return nil, fmt.Errorf("not connected") - } - - if c.pwmPins[pin] != nil { - return c.pwmPins[pin], nil - } - - fn, err := c.translatePwmPin(pin) - if err != nil { - return nil, err - } - - c.pwmPins[pin] = NewPWMPin(c.sys, "/sys/class/pwm/pwmchip0", fn) - if err := c.pwmPins[pin].Export(); err != nil { - return nil, err - } - if err := c.pwmPins[pin].SetPeriod(pwmPeriodDefault); err != nil { - return nil, err - } - if err := c.pwmPins[pin].SetEnabled(true); err != nil { - return nil, err - } - - return c.pwmPins[pin], nil -} - -func (c *Adaptor) validateSpiBusNumber(busNr int) error { +func (a *Adaptor) validateSpiBusNumber(busNr int) error { // Valid bus numbers are [0,1] which corresponds to /dev/spidev0.x through /dev/spidev1.x. // x is the chip number <255 if (busNr < 0) || (busNr > 1) { @@ -186,7 +143,7 @@ func (c *Adaptor) validateSpiBusNumber(busNr int) error { return nil } -func (c *Adaptor) validateI2cBusNumber(busNr int) error { +func (a *Adaptor) validateI2cBusNumber(busNr int) error { // Valid bus number is [0..1] which corresponds to /dev/i2c-0 through /dev/i2c-1. if (busNr < 0) || (busNr > 1) { return fmt.Errorf("Bus number %d out of range", busNr) @@ -194,16 +151,16 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } -func (c *Adaptor) translateDigitalPin(id string) (string, int, error) { +func (a *Adaptor) translateDigitalPin(id string) (string, int, error) { if line, ok := gpioPins[id]; ok { return "", line, nil } return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id) } -func (c *Adaptor) translatePwmPin(pin string) (string, error) { - if fn, ok := pwmPins[pin]; ok { - return fn, nil +func (a *Adaptor) translatePWMPin(id string) (string, int, error) { + if channel, ok := pwmPins[id]; ok { + return "/sys/class/pwm/pwmchip0", channel, nil } - return "", errors.New("Not a valid pin") + return "", 0, fmt.Errorf("'%s' is not a valid pin id for PWM on '%s'", id, a.name) } diff --git a/platforms/jetson/jetson_adaptor_test.go b/platforms/jetson/jetson_adaptor_test.go index 11c9e3338..7f3599b06 100644 --- a/platforms/jetson/jetson_adaptor_test.go +++ b/platforms/jetson/jetson_adaptor_test.go @@ -66,15 +66,12 @@ func TestFinalize(t *testing.T) { func TestPWMPinsConnect(t *testing.T) { a := NewAdaptor() - assert.Equal(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) err := a.PwmWrite("33", 1) require.ErrorContains(t, err, "not connected") err = a.Connect() require.NoError(t, err) - assert.NotEqual(t, (map[string]gobot.PWMPinner)(nil), a.pwmPins) - assert.Empty(t, a.pwmPins) } func TestPWMPinsReConnect(t *testing.T) { @@ -84,18 +81,16 @@ func TestPWMPinsReConnect(t *testing.T) { "/sys/class/pwm/pwmchip0/unexport", "/sys/class/pwm/pwmchip0/pwm2/duty_cycle", "/sys/class/pwm/pwmchip0/pwm2/period", + "/sys/class/pwm/pwmchip0/pwm2/polarity", "/sys/class/pwm/pwmchip0/pwm2/enable", } a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) - assert.Empty(t, a.pwmPins) require.NoError(t, a.PwmWrite("33", 1)) - assert.Len(t, a.pwmPins, 1) require.NoError(t, a.Finalize()) // act err := a.Connect() // assert require.NoError(t, err) - assert.Empty(t, a.pwmPins) } func TestDigitalIO(t *testing.T) { @@ -240,3 +235,35 @@ func Test_validateI2cBusNumber(t *testing.T) { }) } } + +func Test_translatePWMPin(t *testing.T) { + tests := map[string]struct { + pin string + wantDir string + wantChannel int + wantErr error + }{ + "32_pwm0": { + pin: "32", + wantDir: "/sys/class/pwm/pwmchip0", + wantChannel: 0, + }, + "33_pwm2": { + pin: "33", + wantDir: "/sys/class/pwm/pwmchip0", + wantChannel: 2, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := NewAdaptor() + // act + dir, channel, err := a.translatePWMPin(tc.pin) + // assert + assert.Equal(t, tc.wantErr, err) + assert.Equal(t, tc.wantDir, dir) + assert.Equal(t, tc.wantChannel, channel) + }) + } +} diff --git a/platforms/jetson/jetson_pin_map.go b/platforms/jetson/jetson_pin_map.go index 7aae07d84..7abff1e99 100644 --- a/platforms/jetson/jetson_pin_map.go +++ b/platforms/jetson/jetson_pin_map.go @@ -25,7 +25,8 @@ var gpioPins = map[string]int{ "40": 78, } -var pwmPins = map[string]string{ - "32": "0", - "33": "2", +// pin to pwm channel (pwm0, pwm2) +var pwmPins = map[string]int{ + "32": 0, + "33": 2, } diff --git a/platforms/jetson/pwm_pin.go b/platforms/jetson/pwm_pin.go deleted file mode 100644 index 558e832ef..000000000 --- a/platforms/jetson/pwm_pin.go +++ /dev/null @@ -1,148 +0,0 @@ -package jetson - -import ( - "errors" - "fmt" - "os" - "path" - "strconv" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/system" -) - -const ( - minimumPeriod = 5334 - minimumRate = 0.05 -) - -// PWMPin is the Jetson Nano implementation of the PWMPinner interface. -// It uses gpio pwm. -type PWMPin struct { - sys *system.Accesser - path string - fn string - dc uint32 - period uint32 - enabled bool -} - -// NewPWMPin returns a new PWMPin -// pin32 pwm0, pin33 pwm2 -func NewPWMPin(sys *system.Accesser, path string, fn string) *PWMPin { - p := &PWMPin{ - sys: sys, - path: path, - fn: fn, - } - return p -} - -// Export exports the pin for use by the Jetson Nano -func (p *PWMPin) Export() error { - return p.writeFile("export", p.fn) -} - -// Unexport releases the pin from the operating system -func (p *PWMPin) Unexport() error { - return p.writeFile("unexport", p.fn) -} - -// Enabled returns the cached enabled state of the PWM pin -func (p *PWMPin) Enabled() (bool, error) { - return p.enabled, nil -} - -// SetEnabled enables/disables the PWM pin -func (p *PWMPin) SetEnabled(e bool) error { - if err := p.writeFile(fmt.Sprintf("pwm%s/enable", p.fn), strconv.Itoa(bool2int(e))); err != nil { - return err - } - p.enabled = e - return nil -} - -// Polarity returns always the polarity "true" for normal -func (p *PWMPin) Polarity() (bool, error) { - return true, nil -} - -// SetPolarity does not do anything when using Jetson Nano -func (p *PWMPin) SetPolarity(bool) error { - return nil -} - -// Period returns the cached PWM period for pin -func (p *PWMPin) Period() (uint32, error) { - if p.period == 0 { - return p.period, errors.New("Jetson PWM pin period not set") - } - - return p.period, nil -} - -// SetPeriod uses Jetson Nano setting and cannot be changed once set -func (p *PWMPin) SetPeriod(period uint32) error { - if p.period != 0 { - return errors.New("Cannot set the period of individual PWM pins on Jetson") - } - // JetsonNano Minimum period - if period < minimumPeriod { - return errors.New("Cannot set the period more then minimum") - } - //nolint:perfsprint // ok here - if err := p.writeFile(fmt.Sprintf("pwm%s/period", p.fn), fmt.Sprintf("%v", period)); err != nil { - return err - } - p.period = period - return nil -} - -// DutyCycle returns the cached duty cycle for the pin -func (p *PWMPin) DutyCycle() (uint32, error) { - return p.dc, nil -} - -// SetDutyCycle writes the duty cycle to the pin -func (p *PWMPin) SetDutyCycle(duty uint32) error { - if p.period == 0 { - return errors.New("Jetson PWM pin period not set") - } - - if duty > p.period { - return errors.New("Duty cycle exceeds period") - } - - rate := gobot.FromScale(float64(duty), 0, float64(p.period)) - // never go below minimum allowed duty because very short duty - if rate < minimumRate { - duty = uint32(minimumRate * float64(p.period) / 100) - } - //nolint:perfsprint // ok here - if err := p.writeFile(fmt.Sprintf("pwm%s/duty_cycle", p.fn), fmt.Sprintf("%v", duty)); err != nil { - return err - } - - p.dc = duty - return nil -} - -func (p *PWMPin) writeFile(subpath string, value string) error { - sysfspath := path.Join(p.path, subpath) - fi, err := p.sys.OpenFile(sysfspath, os.O_WRONLY|os.O_APPEND, 0o644) - defer fi.Close() //nolint:staticcheck // for historical reasons - - if err != nil { - return err - } - - _, err = fi.WriteString(value) - return err -} - -func bool2int(b bool) int { - if b { - return 1 - } - return 0 -} diff --git a/platforms/jetson/pwm_pin_test.go b/platforms/jetson/pwm_pin_test.go deleted file mode 100644 index 14cf878e0..000000000 --- a/platforms/jetson/pwm_pin_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package jetson - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/system" -) - -var _ gobot.PWMPinner = (*PWMPin)(nil) - -func TestPwmPin(t *testing.T) { - a := system.NewAccesser() - const ( - exportPath = "/sys/class/pwm/pwmchip0/export" - unexportPath = "/sys/class/pwm/pwmchip0/unexport" - enablePath = "/sys/class/pwm/pwmchip0/pwm3/enable" - periodPath = "/sys/class/pwm/pwmchip0/pwm3/period" - dutyCyclePath = "/sys/class/pwm/pwmchip0/pwm3/duty_cycle" - ) - mockPaths := []string{ - exportPath, - unexportPath, - enablePath, - periodPath, - dutyCyclePath, - } - fs := a.UseMockFilesystem(mockPaths) - - pin := NewPWMPin(a, "/sys/class/pwm/pwmchip0", "3") - require.Equal(t, "", fs.Files[exportPath].Contents) - require.Equal(t, "", fs.Files[unexportPath].Contents) - require.Equal(t, "", fs.Files[enablePath].Contents) - require.Equal(t, "", fs.Files[periodPath].Contents) - require.Equal(t, "", fs.Files[dutyCyclePath].Contents) - - require.NoError(t, pin.Export()) - assert.Equal(t, "3", fs.Files[exportPath].Contents) - - require.NoError(t, pin.SetEnabled(true)) - assert.Equal(t, "1", fs.Files[enablePath].Contents) - - val, _ := pin.Polarity() - assert.True(t, val) - require.NoError(t, pin.SetPolarity(false)) - val, _ = pin.Polarity() - assert.True(t, val) - - _, err := pin.Period() - require.ErrorContains(t, err, "Jetson PWM pin period not set") - require.ErrorContains(t, pin.SetDutyCycle(10000), "Jetson PWM pin period not set") - assert.Equal(t, "", fs.Files[dutyCyclePath].Contents) - - require.NoError(t, pin.SetPeriod(20000000)) - assert.Equal(t, "20000000", fs.Files[periodPath].Contents) - period, _ := pin.Period() - assert.Equal(t, uint32(20000000), period) - require.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Jetson") - assert.Equal(t, "20000000", fs.Files[periodPath].Contents) - - dc, _ := pin.DutyCycle() - assert.Equal(t, uint32(0), dc) - - require.NoError(t, pin.SetDutyCycle(10000)) - assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) - dc, _ = pin.DutyCycle() - assert.Equal(t, uint32(10000), dc) - - require.ErrorContains(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") - dc, _ = pin.DutyCycle() - assert.Equal(t, "10000", fs.Files[dutyCyclePath].Contents) - assert.Equal(t, uint32(10000), dc) - - require.NoError(t, pin.Unexport()) - assert.Equal(t, "3", fs.Files[unexportPath].Contents) -} diff --git a/platforms/nanopi/nanopi_adaptor.go b/platforms/nanopi/nanopi_adaptor.go index ab78758d8..d0da14c1d 100644 --- a/platforms/nanopi/nanopi_adaptor.go +++ b/platforms/nanopi/nanopi_adaptor.go @@ -12,8 +12,6 @@ import ( ) const ( - pwmInvertedIdentifier = "inversed" - defaultI2cBusNumber = 0 defaultSpiBusNumber = 0 @@ -83,7 +81,7 @@ func NewNeoAdaptor(opts ...interface{}) *Adaptor { } var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) - pwmPinsOpts := []adaptors.PwmPinsOptionApplier{adaptors.WithPWMPolarityInvertedIdentifier(pwmInvertedIdentifier)} + var pwmPinsOpts []adaptors.PwmPinsOptionApplier for _, opt := range opts { switch o := opt.(type) { case func(adaptors.DigitalPinsOptioner): diff --git a/platforms/nanopi/nanopi_adaptor_test.go b/platforms/nanopi/nanopi_adaptor_test.go index 5410323bc..79f46018f 100644 --- a/platforms/nanopi/nanopi_adaptor_test.go +++ b/platforms/nanopi/nanopi_adaptor_test.go @@ -31,6 +31,8 @@ const ( pwmPeriodPath = pwmPwmDir + "period" pwmDutyCyclePath = pwmPwmDir + "duty_cycle" pwmPolarityPath = pwmPwmDir + "polarity" + + pwmInvertedIdentifier = "inversed" ) var pwmMockPaths = []string{ diff --git a/platforms/raspi/README.md b/platforms/raspi/README.md index 34d42a34d..8db99b238 100644 --- a/platforms/raspi/README.md +++ b/platforms/raspi/README.md @@ -51,9 +51,7 @@ func main() { } ``` -## How to Connect - -### Compiling +## Compiling Compile your Gobot program on your workstation like this: @@ -74,9 +72,48 @@ scp raspi_blink pi@192.168.1.xxx:/home/pi/ ssh -t pi@192.168.1.xxx "./raspi_blink" ``` -### Enabling PWM output on GPIO pins +## Enabling PWM output on GPIO pins + +### Using Linux Kernel sysfs implementation + +The PWM needs to be enabled in the device tree. Please read `/boot/overlays/README` of your device. Usually "pwm0" can +be activated for all raspi variants with a line `dtoverlay=pwm,pin=18,func=2` added to `/boot/config.txt`. The number +relates to "GPIO18", not the header number, which is "12" in this case. + +Now the pin can be used with gobot by the pwm channel name, e.g. for our example above: + +```go +... +// create the adaptor with a 50Hz default frequency for usage with servos +a := NewAdaptor(adaptors.WithPWMDefaultPeriod(20000000)) +// move servo connected with header pin 12 to 90° +a.ServoWrite("pwm0", 90) +... +``` + +> If the activation fails or something strange happen, maybe the audio driver conflicts with the PWM. Please deactivate +> the audio device tree overlay in `/boot/config.txt` to avoid conflicts. + +### Using pi-blaster + +For support PWM on all pins, you may use a program called pi-blaster. You can follow the instructions for install in +the pi-blaster repo here: + +For using a PWM for servo, the default 100Hz period needs to be adjusted to 50Hz in the source code of the driver. +Please refer to . -For extended PWM support on the Raspberry Pi, you will need to use a program called pi-blaster. You can follow the -instructions for pi-blaster install in the pi-blaster repo here: +It is not possible to change the period from gobot side. -[https://github.com/sarfata/pi-blaster](https://github.com/sarfata/pi-blaster) +Now the pin can be used with gobot by the header number, e.g.: + +```go +... +// create the adaptor with usage of pi-blaster instead of default sysfs, 50Hz default is given for calculate +// duty cycle for servos but will not change everything for the pi-blaster driver, see description above +a := NewAdaptor(adaptors.WithPWMUsePiBlaster(), adaptors.WithPWMDefaultPeriod(20000000)) +// move servo to 90° +a.ServoWrite("11", 90) +// this will not work like expected, see description +a.SetPeriod("11", 20000000) +... +``` diff --git a/platforms/raspi/pwm_pin.go b/platforms/raspi/pwm_pin.go deleted file mode 100644 index 70aa59452..000000000 --- a/platforms/raspi/pwm_pin.go +++ /dev/null @@ -1,119 +0,0 @@ -package raspi - -import ( - "errors" - "fmt" - "os" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/system" -) - -// PWMPin is the Raspberry Pi implementation of the PWMPinner interface. -// It uses Pi Blaster. -type PWMPin struct { - sys *system.Accesser - path string - pin string - dc uint32 - period uint32 -} - -// NewPWMPin returns a new PWMPin -func NewPWMPin(sys *system.Accesser, path string, pin string) *PWMPin { - return &PWMPin{ - sys: sys, - path: path, - pin: pin, - } -} - -// Export exports the pin for use by the Raspberry Pi -func (p *PWMPin) Export() error { - return nil -} - -// Unexport releases the pin from the operating system -func (p *PWMPin) Unexport() error { - return p.writeValue(fmt.Sprintf("release %v\n", p.pin)) -} - -// Enabled returns always true for "enabled" -func (p *PWMPin) Enabled() (bool, error) { - return true, nil -} - -// SetEnabled do nothing for PiBlaster -func (p *PWMPin) SetEnabled(e bool) error { - return nil -} - -// Polarity returns always true for "normal" -func (p *PWMPin) Polarity() (bool, error) { - return true, nil -} - -// SetPolarity does not do anything when using PiBlaster -func (p *PWMPin) SetPolarity(bool) error { - return nil -} - -// Period returns the cached PWM period for pin -func (p *PWMPin) Period() (uint32, error) { - if p.period == 0 { - return p.period, errors.New("Raspi PWM pin period not set") - } - - return p.period, nil -} - -// SetPeriod uses PiBlaster setting and cannot be changed once set -func (p *PWMPin) SetPeriod(period uint32) error { - if p.period != 0 { - return errors.New("Cannot set the period of individual PWM pins on Raspi") - } - p.period = period - return nil -} - -// DutyCycle returns the duty cycle for the pin -func (p *PWMPin) DutyCycle() (uint32, error) { - return p.dc, nil -} - -// SetDutyCycle writes the duty cycle to the pin -func (p *PWMPin) SetDutyCycle(duty uint32) error { - if p.period == 0 { - return errors.New("Raspi PWM pin period not set") - } - - if duty > p.period { - return errors.New("Duty cycle exceeds period") - } - - val := gobot.FromScale(float64(duty), 0, float64(p.period)) - // never go below minimum allowed duty for pi blaster - // unless the duty equals to 0 - if val < 0.05 && val != 0 { - val = 0.05 - } - - if err := p.writeValue(fmt.Sprintf("%v=%v\n", p.pin, val)); err != nil { - return err - } - - p.dc = duty - return nil -} - -func (p *PWMPin) writeValue(data string) error { - fi, err := p.sys.OpenFile(p.path, os.O_WRONLY|os.O_APPEND, 0o644) - defer fi.Close() //nolint:staticcheck // for historical reasons - - if err != nil { - return err - } - - _, err = fi.WriteString(data) - return err -} diff --git a/platforms/raspi/pwm_pin_test.go b/platforms/raspi/pwm_pin_test.go deleted file mode 100644 index f25cd0c08..000000000 --- a/platforms/raspi/pwm_pin_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package raspi - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/system" -) - -var _ gobot.PWMPinner = (*PWMPin)(nil) - -func TestPwmPin(t *testing.T) { - const path = "/dev/pi-blaster" - a := system.NewAccesser() - a.UseMockFilesystem([]string{path}) - - pin := NewPWMPin(a, path, "1") - - require.NoError(t, pin.Export()) - require.NoError(t, pin.SetEnabled(true)) - - val, _ := pin.Polarity() - assert.True(t, val) - - require.NoError(t, pin.SetPolarity(false)) - - val, _ = pin.Polarity() - assert.True(t, val) - - _, err := pin.Period() - require.ErrorContains(t, err, "Raspi PWM pin period not set") - require.ErrorContains(t, pin.SetDutyCycle(10000), "Raspi PWM pin period not set") - - require.NoError(t, pin.SetPeriod(20000000)) - period, _ := pin.Period() - assert.Equal(t, uint32(20000000), period) - require.ErrorContains(t, pin.SetPeriod(10000000), "Cannot set the period of individual PWM pins on Raspi") - - dc, _ := pin.DutyCycle() - assert.Equal(t, uint32(0), dc) - - require.NoError(t, pin.SetDutyCycle(10000)) - - dc, _ = pin.DutyCycle() - assert.Equal(t, uint32(10000), dc) - - require.ErrorContains(t, pin.SetDutyCycle(999999999), "Duty cycle exceeds period") - dc, _ = pin.DutyCycle() - assert.Equal(t, uint32(10000), dc) - - require.NoError(t, pin.Unexport()) -} diff --git a/platforms/raspi/raspi_adaptor.go b/platforms/raspi/raspi_adaptor.go index a98ff9fe1..1d917b19a 100644 --- a/platforms/raspi/raspi_adaptor.go +++ b/platforms/raspi/raspi_adaptor.go @@ -1,7 +1,6 @@ package raspi import ( - "errors" "fmt" "strconv" "strings" @@ -37,12 +36,11 @@ type Adaptor struct { mutex sync.Mutex sys *system.Accesser revision string - pwmPins map[string]gobot.PWMPinner *adaptors.AnalogPinsAdaptor *adaptors.DigitalPinsAdaptor + *adaptors.PWMPinsAdaptor *adaptors.I2cBusAdaptor *adaptors.SpiBusAdaptor - PiBlasterPeriod uint32 } // NewAdaptor creates a Raspi Adaptor @@ -56,83 +54,95 @@ type Adaptor struct { // adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior // adaptors.WithGpioDebounce(pin, period): sets the input debouncer // adaptors.WithGpioEventOnFallingEdge/RaisingEdge/BothEdges(pin, handler): activate edge detection -func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { +func NewAdaptor(opts ...interface{}) *Adaptor { sys := system.NewAccesser(system.WithDigitalPinGpiodAccess()) - c := &Adaptor{ - name: gobot.DefaultName("RaspberryPi"), - sys: sys, - PiBlasterPeriod: 10000000, + a := &Adaptor{ + name: gobot.DefaultName("RaspberryPi"), + sys: sys, + } + + var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) + var pwmPinsOpts []adaptors.PwmPinsOptionApplier + for _, opt := range opts { + switch o := opt.(type) { + case func(adaptors.DigitalPinsOptioner): + digitalPinsOpts = append(digitalPinsOpts, o) + case adaptors.PwmPinsOptionApplier: + pwmPinsOpts = append(pwmPinsOpts, o) + default: + panic(fmt.Sprintf("'%s' can not be applied on adaptor '%s'", opt, a.name)) + } } - c.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, c.translateAnalogPin) - c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.getPinTranslatorFunction(), opts...) - c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, 1) - c.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, c.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, + + a.AnalogPinsAdaptor = adaptors.NewAnalogPinsAdaptor(sys, a.translateAnalogPin) + a.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, a.getPinTranslatorFunction(), digitalPinsOpts...) + a.PWMPinsAdaptor = adaptors.NewPWMPinsAdaptor(sys, a.getPinTranslatorFunction(), pwmPinsOpts...) + a.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, a.validateI2cBusNumber, 1) + a.SpiBusAdaptor = adaptors.NewSpiBusAdaptor(sys, a.validateSpiBusNumber, defaultSpiBusNumber, defaultSpiChipNumber, defaultSpiMode, defaultSpiBitsNumber, defaultSpiMaxSpeed) - return c + return a } // Name returns the Adaptor's name -func (c *Adaptor) Name() string { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Name() string { + a.mutex.Lock() + defer a.mutex.Unlock() - return c.name + return a.name } // SetName sets the Adaptor's name -func (c *Adaptor) SetName(n string) { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) SetName(n string) { + a.mutex.Lock() + defer a.mutex.Unlock() - c.name = n + a.name = n } // Connect create new connection to board and pins. -func (c *Adaptor) Connect() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Connect() error { + a.mutex.Lock() + defer a.mutex.Unlock() + + if err := a.SpiBusAdaptor.Connect(); err != nil { + return err + } - if err := c.SpiBusAdaptor.Connect(); err != nil { + if err := a.I2cBusAdaptor.Connect(); err != nil { return err } - if err := c.I2cBusAdaptor.Connect(); err != nil { + if err := a.AnalogPinsAdaptor.Connect(); err != nil { return err } - if err := c.AnalogPinsAdaptor.Connect(); err != nil { + if err := a.PWMPinsAdaptor.Connect(); err != nil { return err } - c.pwmPins = make(map[string]gobot.PWMPinner) - return c.DigitalPinsAdaptor.Connect() + return a.DigitalPinsAdaptor.Connect() } // Finalize closes connection to board and pins -func (c *Adaptor) Finalize() error { - c.mutex.Lock() - defer c.mutex.Unlock() +func (a *Adaptor) Finalize() error { + a.mutex.Lock() + defer a.mutex.Unlock() - err := c.DigitalPinsAdaptor.Finalize() + err := a.DigitalPinsAdaptor.Finalize() - for _, pin := range c.pwmPins { - if pin != nil { - if perr := pin.Unexport(); err != nil { - err = multierror.Append(err, perr) - } - } + if e := a.PWMPinsAdaptor.Finalize(); e != nil { + err = multierror.Append(err, e) } - c.pwmPins = nil - if e := c.AnalogPinsAdaptor.Finalize(); e != nil { + if e := a.AnalogPinsAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.I2cBusAdaptor.Finalize(); e != nil { + if e := a.I2cBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } - if e := c.SpiBusAdaptor.Finalize(); e != nil { + if e := a.SpiBusAdaptor.Finalize(); e != nil { err = multierror.Append(err, e) } return err @@ -140,51 +150,15 @@ func (c *Adaptor) Finalize() error { // DefaultI2cBus returns the default i2c bus for this platform. // This overrides the base function due to the revision dependency. -func (c *Adaptor) DefaultI2cBus() int { - rev := c.readRevision() +func (a *Adaptor) DefaultI2cBus() int { + rev := a.readRevision() if rev == "2" || rev == "3" { return 1 } return 0 } -// PWMPin returns a raspi.PWMPin which provides the gobot.PWMPinner interface -func (c *Adaptor) PWMPin(id string) (gobot.PWMPinner, error) { - c.mutex.Lock() - defer c.mutex.Unlock() - - return c.pwmPin(id) -} - -// PwmWrite writes a PWM signal to the specified pin -func (c *Adaptor) PwmWrite(pin string, val byte) error { - c.mutex.Lock() - defer c.mutex.Unlock() - - sysPin, err := c.pwmPin(pin) - if err != nil { - return err - } - - duty := uint32(gobot.FromScale(float64(val), 0, 255) * float64(c.PiBlasterPeriod)) - return sysPin.SetDutyCycle(duty) -} - -// ServoWrite writes a servo signal to the specified pin -func (c *Adaptor) ServoWrite(pin string, angle byte) error { - c.mutex.Lock() - defer c.mutex.Unlock() - - sysPin, err := c.pwmPin(pin) - if err != nil { - return err - } - - duty := uint32(gobot.FromScale(float64(angle), 0, 180) * float64(c.PiBlasterPeriod)) - return sysPin.SetDutyCycle(duty) -} - -func (c *Adaptor) validateSpiBusNumber(busNr int) error { +func (a *Adaptor) validateSpiBusNumber(busNr int) error { // Valid bus numbers are [0,1] which corresponds to /dev/spidev0.x through /dev/spidev1.x. // x is the chip number <255 if (busNr < 0) || (busNr > 1) { @@ -193,7 +167,7 @@ func (c *Adaptor) validateSpiBusNumber(busNr int) error { return nil } -func (c *Adaptor) validateI2cBusNumber(busNr int) error { +func (a *Adaptor) validateI2cBusNumber(busNr int) error { // Valid bus number is [0..1] which corresponds to /dev/i2c-0 through /dev/i2c-1. if (busNr < 0) || (busNr > 1) { return fmt.Errorf("Bus number %d out of range", busNr) @@ -201,14 +175,14 @@ func (c *Adaptor) validateI2cBusNumber(busNr int) error { return nil } -func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { +func (a *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, error) { pinInfo, ok := analogPinDefinitions[id] if !ok { return "", false, false, 0, fmt.Errorf("'%s' is not a valid id for a analog pin", id) } path := pinInfo.path - info, err := c.sys.Stat(path) + info, err := a.sys.Stat(path) if err != nil { return "", false, false, 0, fmt.Errorf("Error (%v) on access '%s'", err, path) } @@ -219,28 +193,37 @@ func (c *Adaptor) translateAnalogPin(id string) (string, bool, bool, uint16, err return path, pinInfo.r, pinInfo.w, pinInfo.bufLen, nil } -func (c *Adaptor) getPinTranslatorFunction() func(string) (string, int, error) { +// getPinTranslatorFunction returns a function to be able to translate GPIO and PWM pins. +// This means for pi-blaster usage, each pin can be used and therefore the pin is given as number, like a GPIO pin. +// For sysfs-PWM usage, the pin will be given as "pwm0" or "pwm1", because the real pin number depends on the user +// configuration in "/boot/config.txt". For further details, see "/boot/overlays/README". +func (a *Adaptor) getPinTranslatorFunction() func(string) (string, int, error) { return func(pin string) (string, int, error) { var line int - if val, ok := pins[pin][c.readRevision()]; ok { + if val, ok := pins[pin][a.readRevision()]; ok { line = val } else if val, ok := pins[pin]["*"]; ok { line = val } else { - return "", 0, errors.New("Not a valid pin") + return "", 0, fmt.Errorf("'%s' is not a valid pin id for raspi revision %s", pin, a.revision) } - // TODO: Pi1 model B has only this single "gpiochip0", a change of the translator is needed, - // to support different chips with different revisions - return "gpiochip0", line, nil + // We always use "gpiochip0", because currently all pins are available with this approach. A change of the + // translator would be needed to support different chips (e.g. gpiochip1) with different revisions. + path := "gpiochip0" + if strings.HasPrefix(pin, "pwm") { + path = "/sys/class/pwm/pwmchip0" + } + + return path, line, nil } } -func (c *Adaptor) readRevision() string { - if c.revision == "" { - c.revision = "0" - content, err := c.sys.ReadFile(infoFile) +func (a *Adaptor) readRevision() string { + if a.revision == "" { + a.revision = "0" + content, err := a.sys.ReadFile(infoFile) if err != nil { - return c.revision + return a.revision } for _, v := range strings.Split(string(content), "\n") { if strings.Contains(v, "Revision") { @@ -248,34 +231,15 @@ func (c *Adaptor) readRevision() string { version, _ := strconv.ParseInt("0x"+s[len(s)-1], 0, 64) switch { case version <= 3: - c.revision = "1" + a.revision = "1" case version <= 15: - c.revision = "2" + a.revision = "2" default: - c.revision = "3" + a.revision = "3" } } } } - return c.revision -} - -func (c *Adaptor) pwmPin(id string) (gobot.PWMPinner, error) { - pin := c.pwmPins[id] - - if pin == nil { - tf := c.getPinTranslatorFunction() - _, i, err := tf(id) - if err != nil { - return nil, err - } - pin = NewPWMPin(c.sys, "/dev/pi-blaster", strconv.Itoa(i)) - if err := pin.SetPeriod(c.PiBlasterPeriod); err != nil { - return nil, err - } - c.pwmPins[id] = pin - } - - return pin, nil + return a.revision } diff --git a/platforms/raspi/raspi_adaptor_test.go b/platforms/raspi/raspi_adaptor_test.go index c48f7ae46..a463963a6 100644 --- a/platforms/raspi/raspi_adaptor_test.go +++ b/platforms/raspi/raspi_adaptor_test.go @@ -16,9 +16,32 @@ import ( "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/drivers/spi" + "gobot.io/x/gobot/v2/platforms/adaptors" "gobot.io/x/gobot/v2/system" ) +const ( + pwmDir = "/sys/class/pwm/pwmchip0/" //nolint:gosec // false positive + pwmPwmDir = pwmDir + "pwm0/" + pwmExportPath = pwmDir + "export" + pwmUnexportPath = pwmDir + "unexport" + pwmEnablePath = pwmPwmDir + "enable" + pwmPeriodPath = pwmPwmDir + "period" + pwmDutyCyclePath = pwmPwmDir + "duty_cycle" + pwmPolarityPath = pwmPwmDir + "polarity" + + pwmInvertedIdentifier = "inversed" +) + +var pwmMockPaths = []string{ + pwmExportPath, + pwmUnexportPath, + pwmEnablePath, + pwmPeriodPath, + pwmDutyCyclePath, + pwmPolarityPath, +} + // make sure that this Adaptor fulfills all the required interfaces var ( _ gobot.Adaptor = (*Adaptor)(nil) @@ -33,10 +56,19 @@ var ( _ spi.Connector = (*Adaptor)(nil) ) +func preparePwmFs(fs *system.MockFilesystem) { + fs.Files[pwmEnablePath].Contents = "0" + fs.Files[pwmPeriodPath].Contents = "0" + fs.Files[pwmDutyCyclePath].Contents = "0" + fs.Files[pwmPolarityPath].Contents = pwmInvertedIdentifier +} + func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system.MockFilesystem) { a := NewAdaptor() fs := a.sys.UseMockFilesystem(mockPaths) - _ = a.Connect() + if err := a.Connect(); err != nil { + panic(err) + } return a, fs } @@ -133,35 +165,96 @@ func TestAnalog(t *testing.T) { require.NoError(t, a.Finalize()) } -func TestDigitalPWM(t *testing.T) { - mockedPaths := []string{"/dev/pi-blaster"} - a, fs := initTestAdaptorWithMockedFilesystem(mockedPaths) - a.PiBlasterPeriod = 20000000 - - require.NoError(t, a.PwmWrite("7", 4)) +func TestPwmWrite(t *testing.T) { + // arrange + a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) + preparePwmFs(fs) + // act + err := a.PwmWrite("pwm0", 100) + // assert + require.NoError(t, err) + assert.Equal(t, "0", fs.Files[pwmExportPath].Contents) + assert.Equal(t, "1", fs.Files[pwmEnablePath].Contents) + assert.Equal(t, "10000000", fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, "3921568", fs.Files[pwmDutyCyclePath].Contents) + assert.Equal(t, "normal", fs.Files[pwmPolarityPath].Contents) + // act & assert invalid pin + err = a.PwmWrite("pwm1", 42) + require.ErrorContains(t, err, "'pwm1' is not a valid pin id for raspi revision 0") + require.NoError(t, a.Finalize()) +} - pin, _ := a.PWMPin("7") - period, _ := pin.Period() - assert.Equal(t, uint32(20000000), period) +func TestServoWrite(t *testing.T) { + // arrange: prepare 50Hz for servos + const ( + pin = "pwm0" + fiftyHzNano = 20000000 + ) + a := NewAdaptor(adaptors.WithPWMDefaultPeriodForPin(pin, fiftyHzNano)) + fs := a.sys.UseMockFilesystem(pwmMockPaths) + preparePwmFs(fs) + require.NoError(t, a.Connect()) + // act & assert for 0° (min default value) + err := a.ServoWrite(pin, 0) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, "500000", fs.Files[pwmDutyCyclePath].Contents) + // act & assert for 180° (max default value) + err = a.ServoWrite(pin, 180) + require.NoError(t, err) + assert.Equal(t, strconv.Itoa(fiftyHzNano), fs.Files[pwmPeriodPath].Contents) + assert.Equal(t, "2500000", fs.Files[pwmDutyCyclePath].Contents) + // act & assert invalid pins + err = a.ServoWrite("3", 120) + require.ErrorContains(t, err, "'3' is not a valid pin id for raspi revision 0") + require.NoError(t, a.Finalize()) +} +func TestPWMWrite_piPlaster(t *testing.T) { + // arrange + const hundredHzNano = 10000000 + mockedPaths := []string{"/dev/pi-blaster"} + a := NewAdaptor(adaptors.WithPWMUsePiBlaster()) + fs := a.sys.UseMockFilesystem(mockedPaths) + require.NoError(t, a.Connect()) + // act & assert: Write & Pin & Period require.NoError(t, a.PwmWrite("7", 255)) - assert.Equal(t, "4=1", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - - require.NoError(t, a.ServoWrite("11", 90)) - - assert.Equal(t, "17=0.5", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) - - require.ErrorContains(t, a.PwmWrite("notexist", 1), "Not a valid pin") - require.ErrorContains(t, a.ServoWrite("notexist", 1), "Not a valid pin") - + pin, _ := a.PWMPin("7") + period, err := pin.Period() + require.NoError(t, err) + assert.Equal(t, uint32(hundredHzNano), period) + // act & assert: nonexistent pin + require.ErrorContains(t, a.PwmWrite("notexist", 1), "'notexist' is not a valid pin id for raspi revision 0") + // act & assert: SetDutyCycle pin, _ = a.PWMPin("12") - period, _ = pin.Period() - assert.Equal(t, uint32(20000000), period) - require.NoError(t, pin.SetDutyCycle(1.5*1000*1000)) + assert.Equal(t, "18=0.15", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) +} - assert.Equal(t, "18=0.075", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) +func TestPWM_piPlaster(t *testing.T) { + // arrange + const fiftyHzNano = 20000000 // 20 ms + mockedPaths := []string{"/dev/pi-blaster"} + a := NewAdaptor(adaptors.WithPWMUsePiBlaster(), adaptors.WithPWMDefaultPeriod(fiftyHzNano)) + fs := a.sys.UseMockFilesystem(mockedPaths) + require.NoError(t, a.Connect()) + // act & assert: Pin & Period + pin, _ := a.PWMPin("7") + period, err := pin.Period() + require.NoError(t, err) + assert.Equal(t, uint32(fiftyHzNano), period) + // act & assert for 180° (max default value), 2.5 ms => 12.5% + require.NoError(t, a.ServoWrite("11", 180)) + assert.Equal(t, "17=0.125", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) + // act & assert for 90° (center value), 1.5 ms => 7.5% duty + require.NoError(t, a.ServoWrite("11", 90)) + assert.Equal(t, "17=0.075", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) + // act & assert for 0° (min default value), 0.5 ms => 2.5% duty + require.NoError(t, a.ServoWrite("11", 0)) + assert.Equal(t, "17=0.025", strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0]) + // act & assert: nonexistent pin + require.ErrorContains(t, a.ServoWrite("notexist", 1), "'notexist' is not a valid pin id for raspi revision 0") } func TestDigitalIO(t *testing.T) { @@ -187,7 +280,7 @@ func TestDigitalIO(t *testing.T) { require.NoError(t, err) assert.Equal(t, 1, i) - require.ErrorContains(t, a.DigitalWrite("notexist", 1), "Not a valid pin") + require.ErrorContains(t, a.DigitalWrite("notexist", 1), "'notexist' is not a valid pin id for raspi revision 2") require.NoError(t, a.Finalize()) } @@ -214,55 +307,6 @@ func TestDigitalPinConcurrency(t *testing.T) { } } -func TestPWMPin(t *testing.T) { - a := NewAdaptor() - if err := a.Connect(); err != nil { - panic(err) - } - - assert.Empty(t, a.pwmPins) - - a.revision = "3" - firstSysPin, err := a.PWMPin("35") - require.NoError(t, err) - assert.Len(t, a.pwmPins, 1) - - secondSysPin, err := a.PWMPin("35") - - require.NoError(t, err) - assert.Len(t, a.pwmPins, 1) - assert.Equal(t, secondSysPin, firstSysPin) - - otherSysPin, err := a.PWMPin("36") - - require.NoError(t, err) - assert.Len(t, a.pwmPins, 2) - assert.NotEqual(t, otherSysPin, firstSysPin) -} - -func TestPWMPinsReConnect(t *testing.T) { - // arrange - a := NewAdaptor() - a.revision = "3" - if err := a.Connect(); err != nil { - panic(err) - } - - _, err := a.PWMPin("35") - require.NoError(t, err) - assert.Len(t, a.pwmPins, 1) - require.NoError(t, a.Finalize()) - // act - err = a.Connect() - // assert - require.NoError(t, err) - assert.Empty(t, a.pwmPins) - _, _ = a.PWMPin("35") - _, err = a.PWMPin("36") - require.NoError(t, err) - assert.Len(t, a.pwmPins, 2) -} - func TestSpiDefaultValues(t *testing.T) { a := NewAdaptor() @@ -407,3 +451,73 @@ func Test_translateAnalogPin(t *testing.T) { }) } } + +func Test_getPinTranslatorFunction(t *testing.T) { + tests := map[string]struct { + id string + revision string + wantPath string + wantLine int + wantErr string + }{ + "translate_12_rev0": { + id: "12", + wantPath: "gpiochip0", + wantLine: 18, + }, + "translate_13_rev0": { + id: "13", + wantErr: "'13' is not a valid pin id for raspi revision 0", + }, + "translate_13_rev1": { + id: "13", + revision: "1", + wantPath: "gpiochip0", + wantLine: 21, + }, + "translate_29_rev1": { + id: "29", + revision: "1", + wantErr: "'29' is not a valid pin id for raspi revision 1", + }, + "translate_29_rev3": { + id: "29", + revision: "3", + wantPath: "gpiochip0", + wantLine: 5, + }, + "translate_pwm0_rev0": { + id: "pwm0", + wantPath: "/sys/class/pwm/pwmchip0", + wantLine: 0, + }, + "translate_pwm1_rev0": { + id: "pwm1", + wantErr: "'pwm1' is not a valid pin id for raspi revision 0", + }, + "translate_pwm1_rev3": { + id: "pwm1", + revision: "3", + wantPath: "/sys/class/pwm/pwmchip0", + wantLine: 1, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := NewAdaptor() + a.revision = tc.revision + // act + f := a.getPinTranslatorFunction() + path, line, err := f(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.wantLine, line) + }) + } +} diff --git a/platforms/raspi/raspi_pin_map.go b/platforms/raspi/raspi_pin_map.go index 6fdda4835..6a7bdf7ea 100644 --- a/platforms/raspi/raspi_pin_map.go +++ b/platforms/raspi/raspi_pin_map.go @@ -85,6 +85,12 @@ var pins = map[string]map[string]int{ "40": { "3": 21, }, + "pwm0": { // pin 12 (GPIO18) and pin 32 (GPIO12) can be configured for "pwm0" + "*": 0, + }, + "pwm1": { // pin 33 (GPIO13) and pin 35 (GPIO19) can be configured for "pwm1" + "3": 1, + }, } var analogPinDefinitions = map[string]analogPinDefinition{ diff --git a/platforms/tinkerboard/adaptor.go b/platforms/tinkerboard/adaptor.go index 01f926660..8dc9a4b5b 100644 --- a/platforms/tinkerboard/adaptor.go +++ b/platforms/tinkerboard/adaptor.go @@ -12,8 +12,6 @@ import ( ) const ( - pwmInvertedIdentifier = "inversed" - defaultI2cBusNumber = 1 defaultSpiBusNumber = 0 @@ -80,7 +78,7 @@ func NewAdaptor(opts ...interface{}) *Adaptor { } var digitalPinsOpts []func(adaptors.DigitalPinsOptioner) - pwmPinsOpts := []adaptors.PwmPinsOptionApplier{adaptors.WithPWMPolarityInvertedIdentifier(pwmInvertedIdentifier)} + var pwmPinsOpts []adaptors.PwmPinsOptionApplier for _, opt := range opts { switch o := opt.(type) { case func(adaptors.DigitalPinsOptioner): diff --git a/platforms/tinkerboard/adaptor_test.go b/platforms/tinkerboard/adaptor_test.go index 0b6a5fe6d..9667dcea1 100644 --- a/platforms/tinkerboard/adaptor_test.go +++ b/platforms/tinkerboard/adaptor_test.go @@ -31,6 +31,8 @@ const ( pwmPeriodPath = pwmPwmDir + "period" pwmDutyCyclePath = pwmPwmDir + "duty_cycle" pwmPolarityPath = pwmPwmDir + "polarity" + + pwmInvertedIdentifier = "inversed" ) var pwmMockPaths = []string{ diff --git a/system/pwmpin_sysfs_test.go b/system/pwmpin_sysfs_test.go index a9460667f..51a7f7747 100644 --- a/system/pwmpin_sysfs_test.go +++ b/system/pwmpin_sysfs_test.go @@ -14,7 +14,7 @@ var _ gobot.PWMPinner = (*pwmPinSysFs)(nil) const ( normal = "normal" - inverted = "inverted" + inverted = "inversed" ) func initTestPWMPinSysFsWithMockedFilesystem(mockPaths []string) (*pwmPinSysFs, *MockFilesystem) { From f042926dd9939e85f35845e720723bc5240b05a1 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sat, 6 Jan 2024 19:19:08 +0100 Subject: [PATCH 38/57] build(go, deps): update modules (#1052) --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 8ab13ac89..8a5b93b70 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( go.bug.st/serial v1.6.1 gocv.io/x/gocv v0.35.0 golang.org/x/net v0.19.0 - golang.org/x/sys v0.15.0 + golang.org/x/sys v0.16.0 periph.io/x/conn/v3 v3.7.0 periph.io/x/host/v3 v3.8.2 tinygo.org/x/bluetooth v0.8.0 @@ -36,13 +36,13 @@ require ( github.com/klauspost/compress v1.17.4 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 // indirect - github.com/nats-io/nkeys v0.4.6 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/saltosystems/winrt-go v0.0.0-20231011131235-9071442c0c84 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/tinygo-org/cbgo v0.0.4 // indirect - golang.org/x/crypto v0.16.0 // indirect - golang.org/x/sync v0.5.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/sync v0.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index aa4cf3f7c..5a87cda0a 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 h1:BuVRHr4HHJbk1 github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= -github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= -github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -87,8 +87,8 @@ gocv.io/x/gocv v0.35.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -97,8 +97,8 @@ golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -106,8 +106,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= From 474d5530acda3fac1e0ca35dae0356a3273b5b2c Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 7 Jan 2024 10:49:54 +0100 Subject: [PATCH 39/57] docs(core): prepare for release v2.3.0 (#1053) --- .chglog/README.md | 19 +++++++++--------- CHANGELOG.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/.chglog/README.md b/.chglog/README.md index 7c81e3bd5..48f775df0 100644 --- a/.chglog/README.md +++ b/.chglog/README.md @@ -8,22 +8,23 @@ It is possible to test the tool by `git-chglog --init` without overriding anythi ## Usage -Example for a new release "v2.2.0": +Example for a new release "v2.3.0": ```sh +# optional update tool by: go install github.com/git-chglog/git-chglog/cmd/git-chglog@latest git checkout release git pull git fetch --tags git checkout dev git pull upstream dev -git checkout -b rel/prepare_for_release_v220 -git-chglog --config .chglog/config_gobot.yml --no-case --next-tag v2.2.0 v2.1.1.. > .chglog/chglog_tmp.md +git checkout -b rel/prepare_for_release_v230 +git-chglog --config .chglog/config_gobot.yml --no-case --next-tag v2.3.0 v2.2.0.. > .chglog/chglog_tmp.md ``` ## Compare If unsure about any result of running git-chglog, just use: -`git log --since=2023-07-07 --pretty="- %s"` +`git log --since=2023-10-30 --pretty="- %s"` ## Manual adjustment @@ -43,24 +44,24 @@ An example for the following commits: * build(style): adjust rule for golangci-lint ```md -### build +### Build * **style**: adjust rule for golangci-lint -### docs +### Docs * **core**: usage of Kernel driver -### i2c +### I2c * **PCF8583**: added -### gpio +### Gpio * **HD44780**: fix wrong constants -### raspi +### Raspi * **PWM**: refactor usage diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fd63f0a2..5576ac2d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,53 @@ # CHANGELOG -## [Unreleased](https://github.com/hybridgroup/gobot/compare/v2.2.0...HEAD) +## [Unreleased](https://github.com/hybridgroup/gobot/compare/v2.3.0...HEAD) + +## [v2.3.0](https://github.com/hybridgroup/gobot/compare/v2.2.0...v2.3.0) (2024-01-06) + +### Adaptors + +* **pwm:** introduce scale option for servo ([#1046](https://github.com/hybridgroup/gobot/issues/1046)) +* **analogpins:** add a generic analog pin adaptor ([#1041](https://github.com/hybridgroup/gobot/issues/1041)) + +### Aio + +* fix data race in AnalogSensorDriver ([#1024](https://github.com/hybridgroup/gobot/issues/1024)) +* **all:** introduce functional options ([#1039](https://github.com/hybridgroup/gobot/issues/1039)) +* **analog sensor:** fix deadlock in cyclic reading ([#1042](https://github.com/hybridgroup/gobot/issues/1042)) +* **thermalzone:** add driver for read a thermalzone from system ([#1040](https://github.com/hybridgroup/gobot/issues/1040)) + +### Build + +* **go, deps:** update modules ([#1047](https://github.com/hybridgroup/gobot/issues/1047), [#1052](https://github.com/hybridgroup/gobot/issues/1052)) + +### Doc + +* **test:** use -race for tests by default ([#1035](https://github.com/hybridgroup/gobot/issues/1035)) + +### Gpio + +* fix data race in StepperDriver ([#1029](https://github.com/hybridgroup/gobot/issues/1029)) +* fix data race in PIRMotionDriver ([#1028](https://github.com/hybridgroup/gobot/issues/1028)) +* fix data race in ButtonDriver ([#1027](https://github.com/hybridgroup/gobot/issues/1027)) +* fix data race in EasyDriver ([#1025](https://github.com/hybridgroup/gobot/issues/1025)) +* **all:** introduce functional options ([#1045](https://github.com/hybridgroup/gobot/issues/1045)) + +### I2c + +* **core:** fix problems with usage of uintptr ([#1033](https://github.com/hybridgroup/gobot/issues/1033)) + +### Lint + +* **all:** fix issues of errorlint etc ([#1037](https://github.com/hybridgroup/gobot/issues/1037)) +* **all:** switch to 1.55.2 and adjust linter issues ([#1036](https://github.com/hybridgroup/gobot/issues/1036)) + +### Ollie + +* **test:** fix data race in test ([#1034](https://github.com/hybridgroup/gobot/issues/1034)) + +### Raspi + +* **pwm:** add support for sysfs and fix pi-blaster ([#1048](https://github.com/hybridgroup/gobot/issues/1048)) ## [v2.2.0](https://github.com/hybridgroup/gobot/compare/v2.1.1...v2.2.0) (2023-10-29) From 3ac63bfd278f74598b8c413267349db6d0809dfe Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 4 Feb 2024 18:50:43 +0100 Subject: [PATCH 40/57] ble: introduce in drivers folder (#1057) --- Makefile | 2 +- README.md | 83 ++- adaptor.go | 14 + appveyor.yml | 8 +- doc.go | 122 ++-- drivers/{gpio => }/MIGRATION.md | 88 ++- drivers/ble/LICENSE | 13 + drivers/ble/README.md | 28 + drivers/ble/battery_driver.go | 39 ++ drivers/ble/battery_driver_test.go | 33 ++ drivers/ble/ble_driver.go | 118 ++++ drivers/ble/ble_driver_test.go | 70 +++ drivers/ble/device_information_driver.go | 92 +++ drivers/ble/device_information_driver_test.go | 44 ++ drivers/ble/doc.go | 7 + .../ble/generic_access_driver.go | 48 +- drivers/ble/generic_access_driver_test.go | 37 ++ drivers/ble/microbit/LICENSE | 13 + drivers/ble/microbit/accelerometer_driver.go | 67 +++ .../microbit/accelerometer_driver_test.go | 31 +- drivers/ble/microbit/button_driver.go | 50 ++ .../ble}/microbit/button_driver_test.go | 30 +- drivers/ble/microbit/doc.go | 7 + drivers/ble/microbit/io_pin_driver.go | 250 ++++++++ drivers/ble/microbit/io_pin_driver_test.go | 165 ++++++ .../ble}/microbit/led_driver.go | 61 +- .../ble}/microbit/led_driver_test.go | 26 +- drivers/ble/microbit/magnetometer_driver.go | 67 +++ .../ble}/microbit/magnetometer_driver_test.go | 22 +- drivers/ble/microbit/temperature_driver.go | 46 ++ .../ble}/microbit/temperature_driver_test.go | 20 +- drivers/ble/parrot/LICENSE | 13 + drivers/ble/parrot/doc.go | 7 + drivers/ble/parrot/minidrone_driver.go | 503 ++++++++++++++++ .../ble/parrot}/minidrone_driver_test.go | 54 +- drivers/ble/serial_port.go | 84 +++ drivers/ble/serial_port_test.go | 20 + {platforms => drivers/ble}/sphero/LICENSE | 0 drivers/ble/sphero/doc.go | 9 + drivers/ble/sphero/sphero_bb8_driver.go | 28 + drivers/ble/sphero/sphero_bb8_driver_test.go | 21 + drivers/ble/sphero/sphero_ollie_driver.go | 446 +++++++++++++++ .../ble/sphero/sphero_ollie_driver_test.go | 45 +- drivers/ble/sphero/sphero_sprkplus_driver.go | 28 + .../ble/sphero/sphero_sprkplus_driver_test.go | 21 + .../ble/testutil/testutil.go | 79 ++- drivers/common/bit/bit.go | 20 + drivers/common/bit/bit_test.go | 34 ++ drivers/common/sphero/sphero_driver.go | 33 ++ drivers/common/sphero/sphero_driver_test.go | 20 + .../common}/sphero/sphero_packets.go | 76 +-- drivers/i2c/i2c_connection.go | 13 - drivers/i2c/i2c_connection_test.go | 12 - drivers/i2c/mcp23017_driver.go | 5 +- drivers/i2c/pca9501_driver.go | 18 +- drivers/serial/LICENSE | 13 + drivers/serial/README.md | 15 + drivers/serial/doc.go | 7 + drivers/serial/helpers_test.go | 28 + drivers/serial/serial_driver.go | 104 ++++ drivers/serial/serial_driver_test.go | 69 +++ drivers/serial/sphero_driver.go | 476 ++++++++++++++++ .../serial}/sphero_driver_test.go | 58 +- examples/ble_battery.go | 5 +- ...{bb8-collision.go => ble_bb8-collision.go} | 8 +- examples/{bb8.go => ble_bb8.go} | 8 +- examples/ble_device_info.go | 5 +- examples/ble_generic_access.go | 5 +- examples/ble_multiple_generic.go | 5 +- examples/ble_multiple_info.go | 5 +- examples/{ollie.go => ble_ollie.go} | 8 +- .../{ollie_boost.go => ble_ollie_boost.go} | 8 +- .../{ollie_crazy.go => ble_ollie_crazy.go} | 10 +- examples/{ollie_mqtt.go => ble_ollie_mqtt.go} | 8 +- ...llie_multiple.go => ble_ollie_multiple.go} | 8 +- examples/{ollie_roll.go => ble_ollie_roll.go} | 8 +- examples/{ollie_spin.go => ble_ollie_spin.go} | 10 +- examples/{sprkplus.go => ble_sprkplus.go} | 8 +- ...collision.go => ble_sprkplus_collision.go} | 8 +- examples/leap_sphero.go | 7 +- examples/microbit_accelerometer.go | 8 +- examples/microbit_blink.go | 6 +- examples/microbit_buttons.go | 10 +- examples/microbit_buttons_leds.go | 10 +- examples/microbit_io_button.go | 6 +- examples/microbit_led.go | 6 +- examples/microbit_magnetometer.go | 8 +- examples/microbit_temperature.go | 8 +- examples/minidrone.go | 8 +- examples/minidrone_events.go | 20 +- examples/minidrone_mambo_ps3.go | 32 +- examples/minidrone_ps3.go | 24 +- examples/{sphero.go => serial_sphero.go} | 12 +- .../{sphero_api.go => serial_sphero_api.go} | 7 +- ...ration.go => serial_sphero_calibration.go} | 7 +- ...ro_conways.go => serial_sphero_conways.go} | 12 +- .../{sphero_dpad.go => serial_sphero_dpad.go} | 7 +- ...hero_master.go => serial_sphero_master.go} | 9 +- ..._multiple.go => serial_sphero_multiple.go} | 10 +- platforms/adaptors/pwmpinsadaptoroptions.go | 2 +- platforms/ble/battery_driver.go | 60 -- platforms/ble/battery_driver_test.go | 41 -- platforms/ble/device_information_driver.go | 107 ---- .../ble/device_information_driver_test.go | 81 --- platforms/ble/doc.go | 13 - platforms/ble/generic_access_driver_test.go | 51 -- platforms/ble/helpers_test.go | 65 --- platforms/ble/serial_port.go | 77 --- platforms/ble/serial_port_test.go | 16 - platforms/{ble => bleclient}/LICENSE | 0 platforms/{ble => bleclient}/README.md | 13 +- .../{ble => bleclient}/ble_client_adaptor.go | 92 ++- .../ble_client_adaptor_test.go | 15 +- platforms/bleclient/doc.go | 7 + platforms/{ble => bleclient}/uuid.go | 2 +- platforms/firmata/ble_firmata_adaptor.go | 6 +- platforms/microbit/README.md | 23 +- platforms/microbit/accelerometer_driver.go | 97 ---- platforms/microbit/button_driver.go | 75 --- platforms/microbit/doc.go | 4 +- platforms/microbit/io_pin_driver.go | 272 --------- platforms/microbit/io_pin_driver_test.go | 161 ------ platforms/microbit/magnetometer_driver.go | 97 ---- platforms/microbit/temperature_driver.go | 70 --- platforms/parrot/README.md | 1 + platforms/parrot/minidrone/README.md | 8 +- platforms/parrot/minidrone/doc.go | 4 +- platforms/parrot/minidrone/helpers_test.go | 68 --- .../parrot/minidrone/minidrone_driver.go | 535 ------------------ platforms/parrot/minidrone/pitch.go | 17 - platforms/parrot/minidrone/pitch_test.go | 19 - platforms/parrot/parrot.go | 2 +- platforms/serialport/LICENSE | 13 + platforms/serialport/README.md | 11 + .../adaptor.go} | 61 +- .../adaptor_test.go} | 6 +- platforms/serialport/doc.go | 7 + platforms/sphero/bb8/README.md | 8 +- platforms/sphero/bb8/bb8_driver.go | 22 - platforms/sphero/bb8/bb8_driver_test.go | 31 - platforms/sphero/bb8/bb8_packets.go | 15 - platforms/sphero/bb8/doc.go | 7 - platforms/sphero/bb8/helpers_test.go | 69 --- platforms/sphero/doc.go | 42 -- platforms/sphero/ollie/README.md | 8 +- platforms/sphero/ollie/doc.go | 7 - platforms/sphero/ollie/helpers_test.go | 69 --- platforms/sphero/ollie/ollie_driver.go | 481 ---------------- platforms/sphero/ollie/ollie_packets.go | 115 ---- platforms/sphero/sphero/LICENSE | 13 + platforms/sphero/{ => sphero}/README.md | 16 +- platforms/sphero/sphero_driver.go | 472 --------------- platforms/sphero/sprkplus/README.md | 8 +- platforms/sphero/sprkplus/doc.go | 7 - platforms/sphero/sprkplus/helpers_test.go | 69 --- platforms/sphero/sprkplus/sprkplus_driver.go | 22 - .../sphero/sprkplus/sprkplus_driver_test.go | 31 - platforms/sphero/sprkplus/sprkplus_packets.go | 15 - 158 files changed, 3966 insertions(+), 4154 deletions(-) rename drivers/{gpio => }/MIGRATION.md (68%) create mode 100644 drivers/ble/LICENSE create mode 100644 drivers/ble/README.md create mode 100644 drivers/ble/battery_driver.go create mode 100644 drivers/ble/battery_driver_test.go create mode 100644 drivers/ble/ble_driver.go create mode 100644 drivers/ble/ble_driver_test.go create mode 100644 drivers/ble/device_information_driver.go create mode 100644 drivers/ble/device_information_driver_test.go create mode 100644 drivers/ble/doc.go rename {platforms => drivers}/ble/generic_access_driver.go (65%) create mode 100644 drivers/ble/generic_access_driver_test.go create mode 100644 drivers/ble/microbit/LICENSE create mode 100644 drivers/ble/microbit/accelerometer_driver.go rename {platforms => drivers/ble}/microbit/accelerometer_driver_test.go (57%) create mode 100644 drivers/ble/microbit/button_driver.go rename {platforms => drivers/ble}/microbit/button_driver_test.go (50%) create mode 100644 drivers/ble/microbit/doc.go create mode 100644 drivers/ble/microbit/io_pin_driver.go create mode 100644 drivers/ble/microbit/io_pin_driver_test.go rename {platforms => drivers/ble}/microbit/led_driver.go (62%) rename {platforms => drivers/ble}/microbit/led_driver_test.go (62%) create mode 100644 drivers/ble/microbit/magnetometer_driver.go rename {platforms => drivers/ble}/microbit/magnetometer_driver_test.go (63%) create mode 100644 drivers/ble/microbit/temperature_driver.go rename {platforms => drivers/ble}/microbit/temperature_driver_test.go (62%) create mode 100644 drivers/ble/parrot/LICENSE create mode 100644 drivers/ble/parrot/doc.go create mode 100644 drivers/ble/parrot/minidrone_driver.go rename {platforms/parrot/minidrone => drivers/ble/parrot}/minidrone_driver_test.go (78%) create mode 100644 drivers/ble/serial_port.go create mode 100644 drivers/ble/serial_port_test.go rename {platforms => drivers/ble}/sphero/LICENSE (100%) create mode 100644 drivers/ble/sphero/doc.go create mode 100644 drivers/ble/sphero/sphero_bb8_driver.go create mode 100644 drivers/ble/sphero/sphero_bb8_driver_test.go create mode 100644 drivers/ble/sphero/sphero_ollie_driver.go rename platforms/sphero/ollie/ollie_driver_test.go => drivers/ble/sphero/sphero_ollie_driver_test.go (63%) create mode 100644 drivers/ble/sphero/sphero_sprkplus_driver.go create mode 100644 drivers/ble/sphero/sphero_sprkplus_driver_test.go rename platforms/microbit/helpers_test.go => drivers/ble/testutil/testutil.go (58%) create mode 100644 drivers/common/bit/bit.go create mode 100644 drivers/common/bit/bit_test.go create mode 100644 drivers/common/sphero/sphero_driver.go create mode 100644 drivers/common/sphero/sphero_driver_test.go rename {platforms => drivers/common}/sphero/sphero_packets.go (87%) create mode 100644 drivers/serial/LICENSE create mode 100644 drivers/serial/README.md create mode 100644 drivers/serial/doc.go create mode 100644 drivers/serial/helpers_test.go create mode 100644 drivers/serial/serial_driver.go create mode 100644 drivers/serial/serial_driver_test.go create mode 100644 drivers/serial/sphero_driver.go rename {platforms/sphero => drivers/serial}/sphero_driver_test.go (66%) rename examples/{bb8-collision.go => ble_bb8-collision.go} (78%) rename examples/{bb8.go => ble_bb8.go} (77%) rename examples/{ollie.go => ble_ollie.go} (72%) rename examples/{ollie_boost.go => ble_ollie_boost.go} (73%) rename examples/{ollie_crazy.go => ble_ollie_crazy.go} (60%) rename examples/{ollie_mqtt.go => ble_ollie_mqtt.go} (88%) rename examples/{ollie_multiple.go => ble_ollie_multiple.go} (83%) rename examples/{ollie_roll.go => ble_ollie_roll.go} (69%) rename examples/{ollie_spin.go => ble_ollie_spin.go} (60%) rename examples/{sprkplus.go => ble_sprkplus.go} (77%) rename examples/{sprkplus_collision.go => ble_sprkplus_collision.go} (77%) rename examples/{sphero.go => serial_sphero.go} (66%) rename examples/{sphero_api.go => serial_sphero_api.go} (79%) rename examples/{sphero_calibration.go => serial_sphero_calibration.go} (85%) rename examples/{sphero_conways.go => serial_sphero_conways.go} (85%) rename examples/{sphero_dpad.go => serial_sphero_dpad.go} (81%) rename examples/{sphero_master.go => serial_sphero_master.go} (73%) rename examples/{sphero_multiple.go => serial_sphero_multiple.go} (76%) delete mode 100644 platforms/ble/battery_driver.go delete mode 100644 platforms/ble/battery_driver_test.go delete mode 100644 platforms/ble/device_information_driver.go delete mode 100644 platforms/ble/device_information_driver_test.go delete mode 100644 platforms/ble/doc.go delete mode 100644 platforms/ble/generic_access_driver_test.go delete mode 100644 platforms/ble/helpers_test.go delete mode 100644 platforms/ble/serial_port.go delete mode 100644 platforms/ble/serial_port_test.go rename platforms/{ble => bleclient}/LICENSE (100%) rename platforms/{ble => bleclient}/README.md (85%) rename platforms/{ble => bleclient}/ble_client_adaptor.go (63%) rename platforms/{ble => bleclient}/ble_client_adaptor_test.go (52%) create mode 100644 platforms/bleclient/doc.go rename platforms/{ble => bleclient}/uuid.go (96%) delete mode 100644 platforms/microbit/accelerometer_driver.go delete mode 100644 platforms/microbit/button_driver.go delete mode 100644 platforms/microbit/io_pin_driver.go delete mode 100644 platforms/microbit/io_pin_driver_test.go delete mode 100644 platforms/microbit/magnetometer_driver.go delete mode 100644 platforms/microbit/temperature_driver.go delete mode 100644 platforms/parrot/minidrone/helpers_test.go delete mode 100644 platforms/parrot/minidrone/minidrone_driver.go delete mode 100644 platforms/parrot/minidrone/pitch.go delete mode 100644 platforms/parrot/minidrone/pitch_test.go create mode 100644 platforms/serialport/LICENSE create mode 100644 platforms/serialport/README.md rename platforms/{sphero/sphero_adaptor.go => serialport/adaptor.go} (58%) rename platforms/{sphero/sphero_adaptor_test.go => serialport/adaptor_test.go} (94%) create mode 100644 platforms/serialport/doc.go delete mode 100644 platforms/sphero/bb8/bb8_driver.go delete mode 100644 platforms/sphero/bb8/bb8_driver_test.go delete mode 100644 platforms/sphero/bb8/bb8_packets.go delete mode 100644 platforms/sphero/bb8/doc.go delete mode 100644 platforms/sphero/bb8/helpers_test.go delete mode 100644 platforms/sphero/doc.go delete mode 100644 platforms/sphero/ollie/doc.go delete mode 100644 platforms/sphero/ollie/helpers_test.go delete mode 100644 platforms/sphero/ollie/ollie_driver.go delete mode 100644 platforms/sphero/ollie/ollie_packets.go create mode 100644 platforms/sphero/sphero/LICENSE rename platforms/sphero/{ => sphero}/README.md (77%) delete mode 100644 platforms/sphero/sphero_driver.go delete mode 100644 platforms/sphero/sprkplus/doc.go delete mode 100644 platforms/sphero/sprkplus/helpers_test.go delete mode 100644 platforms/sphero/sprkplus/sprkplus_driver.go delete mode 100644 platforms/sphero/sprkplus/sprkplus_driver_test.go delete mode 100644 platforms/sphero/sprkplus/sprkplus_packets.go diff --git a/Makefile b/Makefile index e3c7883f0..0b95c4346 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ including_except := $(shell go list ./... | grep -v platforms/opencv) # Run tests on nearly all directories without test cache, with race detection test_race: - go test -failfast -count=1 -v -race $(including_except) + go test -failfast -count=1 -race $(including_except) # Run tests on nearly all directories without test cache test: diff --git a/README.md b/README.md index a9e48b4c4..c8b524320 100644 --- a/README.md +++ b/README.md @@ -101,12 +101,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { - adaptor := sphero.NewAdaptor("/dev/rfcomm0") - driver := sphero.NewSpheroDriver(adaptor) + adaptor := serialport.NewAdaptor("/dev/rfcomm0") + driver := serial.NewSpheroDriver(adaptor) work := func() { gobot.Every(3*time.Second, func() { @@ -166,18 +167,20 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) func NewSwarmBot(port string) *gobot.Robot { - spheroAdaptor := sphero.NewAdaptor(port) - spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) + spheroAdaptor := serialport.NewAdaptor(port) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor) spheroDriver.SetName("Sphero" + port) work := func() { spheroDriver.Stop() - spheroDriver.On(sphero.Collision, func(data interface{}) { + spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { fmt.Println("Collision Detected!") }) @@ -229,7 +232,7 @@ platforms are currently supported: - Audio <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/audio) - [Beaglebone Black](http://beagleboard.org/boards) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/beaglebone) - [Beaglebone PocketBeagle](http://beagleboard.org/pocket/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/beaglebone) -- [Bluetooth LE](https://www.bluetooth.com/what-is-bluetooth-technology/bluetooth-technology-basics/low-energy) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/ble) +- [Bluetooth LE](https://www.bluetooth.com/what-is-bluetooth-technology/bluetooth-technology-basics/low-energy) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/bleclient) - [C.H.I.P](http://www.nextthing.co/pages/chip) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/chip) - [C.H.I.P Pro](https://docs.getchip.com/chip_pro.html) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/chip) - [Digispark](http://digistump.com/products/1) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/digispark) @@ -259,15 +262,47 @@ platforms are currently supported: - [Pebble](https://www.getpebble.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/pebble) - [Radxa Rock Pi 4](https://wiki.radxa.com/Rock4/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/rockpi) - [Raspberry Pi](http://www.raspberrypi.org/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/raspi) -- [Sphero](http://www.sphero.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero) +- [Serial Port](https://en.wikipedia.org/wiki/Serial_port) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/serialport) +- [Sphero](http://www.sphero.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero/sphero) - [Sphero BB-8](http://www.sphero.com/bb8) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero/bb8) - [Sphero Ollie](http://www.sphero.com/ollie) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero/ollie) - [Sphero SPRK+](http://www.sphero.com/sprk-plus) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero/sprkplus) - [Tinker Board](https://www.asus.com/us/Single-Board-Computer/Tinker-Board/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/tinkerboard) - [UP2](http://www.up-board.org/upsquared/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/upboard/up2) -Support for many devices that use General Purpose Input/Output (GPIO) have -a shared set of drivers provided using the `gobot/drivers/gpio` package: +Support for many devices that use Analog Input/Output (AIO) have a shared set of drivers provided using +the `gobot/drivers/aio` package: + +- [AIO](https://en.wikipedia.org/wiki/Analog-to-digital_converter) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/aio) + - Analog Actuator + - Analog Sensor + - Grove Light Sensor + - Grove Piezo Vibration Sensor + - Grove Rotary Dial + - Grove Sound Sensor + - Grove Temperature Sensor + - Temperature Sensor (supports linear and NTC thermistor in normal and inverse mode) + - Thermal Zone Temperature Sensor + +Support for many devices that use Bluetooth LE (BLE) have a shared set of drivers provided using +the `gobot/drivers/ble` package: + +- [BLE](http://en.wikipedia.org/wiki/Bluetooth_low_energy) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/ble) + - Battery Service + - Device Information Service + - Generic Access Service + - Microbit: AccelerometerDriver + - Microbit: ButtonDriver + - Microbit: IOPinDriver + - Microbit: LEDDriver + - Microbit: MagnetometerDriver + - Microbit: TemperatureDriver + - Sphero: BB8 + - Sphero: Ollie + - Sphero: SPRK+ + +Support for many devices that use General Purpose Input/Output (GPIO) have a shared set of drivers provided using +the `gobot/drivers/gpio` package: - [GPIO](https://en.wikipedia.org/wiki/General_Purpose_Input/Output) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/gpio) - AIP1640 LED Dot Matrix/7 Segment Controller @@ -294,22 +329,8 @@ a shared set of drivers provided using the `gobot/drivers/gpio` package: - Stepper Motor - TM1638 LED Controller -Support for many devices that use Analog Input/Output (AIO) have -a shared set of drivers provided using the `gobot/drivers/aio` package: - -- [AIO](https://en.wikipedia.org/wiki/Analog-to-digital_converter) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/aio) - - Analog Actuator - - Analog Sensor - - Grove Light Sensor - - Grove Piezo Vibration Sensor - - Grove Rotary Dial - - Grove Sound Sensor - - Grove Temperature Sensor - - Temperature Sensor (supports linear and NTC thermistor in normal and inverse mode) - - Thermal Zone Temperature Sensor - -Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of -drivers provided using the `gobot/drivers/i2c` package: +Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of drivers provided using +the `gobot/drivers/i2c` package: - [I2C](https://en.wikipedia.org/wiki/I%C2%B2C) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/i2c) - Adafruit 1109 2x16 RGB-LCD with 5 keys @@ -351,6 +372,12 @@ drivers provided using the `gobot/drivers/i2c` package: - Wii Nunchuck Controller - YL-40 Brightness/Temperature sensor, Potentiometer, analog input, analog output Driver +Support for many devices that use Serial communication (UART) have a shared set of drivers provided using +the `gobot/drivers/serial` package: + +- [UART](https://en.wikipedia.org/wiki/Serial_port) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/serial) + - Sphero: Sphero + Support for devices that use Serial Peripheral Interface (SPI) have a shared set of drivers provided using the `gobot/drivers/spi` package: @@ -366,8 +393,6 @@ a shared set of drivers provided using the `gobot/drivers/spi` package: - MFRC522 RFID Card Reader - SSD1306 OLED Display Controller -More platforms and drivers are coming soon... - ## API Gobot includes a RESTful API to query the status of any robot running within a group, including the connection and diff --git a/adaptor.go b/adaptor.go index 5456136f7..6eedb50cb 100644 --- a/adaptor.go +++ b/adaptor.go @@ -225,6 +225,20 @@ type Adaptor interface { Finalize() error } +// BLEConnector is the interface that a BLE ClientAdaptor must implement +type BLEConnector interface { + Adaptor + + Reconnect() error + Disconnect() error + Address() string + + ReadCharacteristic(cUUID string) ([]byte, error) + WriteCharacteristic(cUUID string, data []byte) error + Subscribe(cUUID string, f func([]byte, error)) error + WithoutResponses(use bool) +} + // Porter is the interface that describes an adaptor's port type Porter interface { Port() string diff --git a/appveyor.yml b/appveyor.yml index dd9d21df6..3031663a6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,10 +15,14 @@ before_test: build_script: - go test -v -cpu=2 . - go test -v -cpu=2 ./drivers/aio/... - - go test -v -cpu=2 ./platforms/ble/... + - go test -v -cpu=2 ./drivers/ble/. + - go test -v -cpu=2 ./drivers/ble/parrot/. + - go test -v -cpu=2 ./drivers/ble/sphero/. + - go test -v -cpu=2 ./drivers/serial/... + - go test -v -cpu=2 ./platforms/bleclient/... - go test -v -cpu=2 ./platforms/dji/... - go test -v -cpu=2 ./platforms/firmata/... - go test -v -cpu=2 ./platforms/joystick/... - go test -v -cpu=2 ./platforms/parrot/... - - go test -v -cpu=2 ./platforms/sphero/... + - go test -v -cpu=2 ./platforms/serialport/... - cd .. diff --git a/doc.go b/doc.go index acd5e0d58..2f1eee92a 100644 --- a/doc.go +++ b/doc.go @@ -70,66 +70,68 @@ pure idiomatic Golang code. For example: Finally, you can use Master Gobot to add the complete Gobot API or control swarms of Robots: - package main - - import ( - "fmt" - "time" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/sphero" - ) - - func NewSwarmBot(port string) *gobot.Robot { - spheroAdaptor := sphero.NewAdaptor(port) - spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) - spheroDriver.SetName("Sphero" + port) - - work := func() { - spheroDriver.Stop() - - spheroDriver.On(sphero.Collision, func(data interface{}) { - fmt.Println("Collision Detected!") - }) - - gobot.Every(1*time.Second, func() { - spheroDriver.Roll(100, uint16(gobot.Rand(360))) - }) - gobot.Every(3*time.Second, func() { - spheroDriver.SetRGB(uint8(gobot.Rand(255)), - uint8(gobot.Rand(255)), - uint8(gobot.Rand(255)), - ) - }) - } - - robot := gobot.NewRobot("sphero", - []gobot.Connection{spheroAdaptor}, - []gobot.Device{spheroDriver}, - work, - ) - - return robot - } - - func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() - - spheros := []string{ - "/dev/rfcomm0", - "/dev/rfcomm1", - "/dev/rfcomm2", - "/dev/rfcomm3", - } - - for _, port := range spheros { - master.AddRobot(NewSwarmBot(port)) - } - - master.Start() - } + package main + + import ( + "fmt" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/api" + "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" + ) + + func NewSwarmBot(port string) *gobot.Robot { + spheroAdaptor := serialport.NewAdaptor(port) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor) + spheroDriver.SetName("Sphero" + port) + + work := func() { + spheroDriver.Stop() + + spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { + fmt.Println("Collision Detected!") + }) + + gobot.Every(1*time.Second, func() { + spheroDriver.Roll(100, uint16(gobot.Rand(360))) + }) + gobot.Every(3*time.Second, func() { + spheroDriver.SetRGB(uint8(gobot.Rand(255)), + uint8(gobot.Rand(255)), + uint8(gobot.Rand(255)), + ) + }) + } + + robot := gobot.NewRobot("sphero", + []gobot.Connection{spheroAdaptor}, + []gobot.Device{spheroDriver}, + work, + ) + + return robot + } + + func main() { + master := gobot.NewMaster() + api.NewAPI(master).Start() + + spheros := []string{ + "/dev/rfcomm0", + "/dev/rfcomm1", + "/dev/rfcomm2", + "/dev/rfcomm3", + } + + for _, port := range spheros { + master.AddRobot(NewSwarmBot(port)) + } + + master.Start() + } Copyright (c) 2013-2018 The Hybrid Group. Licensed under the Apache 2.0 license. */ diff --git a/drivers/gpio/MIGRATION.md b/drivers/MIGRATION.md similarity index 68% rename from drivers/gpio/MIGRATION.md rename to drivers/MIGRATION.md index c493e1b4a..2d80d434d 100644 --- a/drivers/gpio/MIGRATION.md +++ b/drivers/MIGRATION.md @@ -1,15 +1,83 @@ -# Migration of GPIO drivers +# Migration of drivers From time to time a breaking change of API can happen. Following to [SemVer](https://semver.org/), the gobot main version should be increased. In such case all users needs to adjust there projects for the next update, although they not using a driver with changed API. -To prevent this scenario for most users, the main version will not always increased, but affected GPIO drivers are listed +To prevent this scenario for most users, the main version will not always increased, but affected drivers are listed here and a migration strategy is provided. -## Switch from version 2.2.0 +## Switch from version 2.3.0 (ble and sphero adaptors affected) -### ButtonDriver, PIRMotionDriver: substitute parameter "v time.duration" +### BLE drivers and client adaptor + +All BLE drivers now can be found in the folder "drivers/ble". Formerly the drivers are located below "platforms/ble". +In addition the location of the BLE client adaptor was changed to "platforms/bleclient". Therefore a change for the +import paths is needed. The constructor function was also renamed, see below. + +```go +// old +import( + ... + "gobot.io/x/gobot/v2/platforms/ble" + ... +) + +... + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) +... + +// new +import( + ... + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/platforms/bleclient" + ... +) +... + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) +... +``` + +### Sphero adaptor split off + +The Serial Based Sphero adaptor was split off into a generic serial adaptor and the driver part. With this, the imports +needs to be adjusted. In addition all events now have a postfix "Event", see below. + +```go +// old +import( + ... + "gobot.io/x/gobot/v2/platforms/sphero" + ... +) + +... + adaptor := sphero.NewAdaptor("/dev/rfcomm0") + spheroDriver := sphero.NewSpheroDriver(adaptor) +... + spheroDriver.On(sphero.Collision, func(data interface{}) { +... + +// new +import( + ... + "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" + ... +) +... + adaptor := serialport.NewAdaptor("/dev/rfcomm0") + spheroDriver := serial.NewSpheroDriver(adaptor) +... + spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { +... +``` + +## Switch from version 2.2.0 (gpio drivers affected) + +### gpio.ButtonDriver, gpio.PIRMotionDriver: substitute parameter "v time.duration" A backward compatible case is still included, but it is recommended to use "WithButtonPollInterval" instead, see example below. @@ -22,7 +90,7 @@ d := gpio.NewButtonDriver(adaptor, "1", 50*time.Millisecond) d := gpio.NewButtonDriver(adaptor, "1", gpio.WithButtonPollInterval(50*time.Millisecond)) ``` -### EasyDriver: optional pins +### gpio.EasyDriver: optional pins There is no need to use the direction, enable or sleep feature of the driver. Therefore the parameters are removed from constructor. Please migrate according to the examples below. The order of the optional functions does not matter. @@ -42,7 +110,7 @@ d3 := gpio.NewEasyDriver(adaptor, 0.83, "31", gpio.WithEasyDirectionPin("32"), g gpio.WithEasySleepPin("34")) ``` -### BuzzerDriver: unexport 'BPM' attribute +### gpio.BuzzerDriver: unexport 'BPM' attribute ```go d := gpio.NewBuzzerDriver(adaptor, "1") @@ -55,7 +123,7 @@ d.SetBPM(120.0) fmt.Println("BPM:", d.BPM()) ``` -### RelayDriver: unexport 'Inverted' attribute +### gpio.RelayDriver: unexport 'Inverted' attribute Usually the relay is inverted or not, except be rewired. From now on the inverted behavior can only be changed on initialization. If there is really a different use case, please file a new issue. @@ -71,7 +139,7 @@ d := gpio.NewRelayDriver(adaptor, "1", gpio.WithRelayInverted()) fmt.Println("is inverted:", d.IsInverted()) ``` -### HD44780Driver: make 'SetRWPin()' an option +### gpio.HD44780Driver: make 'SetRWPin()' an option ```go // old @@ -82,7 +150,7 @@ d.SetRWPin("10") d := gpio.NewHD44780Driver(adaptor, ..., gpio.WithHD44780RWPin("10")) ``` -### ServoDriver: unexport 'CurrentAngle' and rename functions 'Min()', 'Max()', 'Center()' +### gpio.ServoDriver: unexport 'CurrentAngle' and rename functions 'Min()', 'Max()', 'Center()' ```go d := gpio.NewServoDriver(adaptor, "1") @@ -99,7 +167,7 @@ d.ToCenter() d.ToMax() ``` -### MotorDriver: unexport pin and state attributes, rename functions +### gpio.MotorDriver: unexport pin and state attributes, rename functions The motor driver was heavily revised - sorry for the inconveniences. diff --git a/drivers/ble/LICENSE b/drivers/ble/LICENSE new file mode 100644 index 000000000..257d22e97 --- /dev/null +++ b/drivers/ble/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2014-2018 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/ble/README.md b/drivers/ble/README.md new file mode 100644 index 000000000..a45b41f98 --- /dev/null +++ b/drivers/ble/README.md @@ -0,0 +1,28 @@ +# BLE + +This package provides drivers for [Bluetooth LE (BLE)](http://en.wikipedia.org/wiki/Bluetooth_low_energy) +devices. It is normally used by connecting an [BLE client adaptor](https://github.com/hybridgroup/gobot/tree/release/platforms/bleclient) +that supports the needed interfaces for BLE devices. + +## Getting Started + +Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) and the README files +in the subfolders. + +## Hardware Support + +Gobot has a extensible system for connecting to hardware devices. The following BLE devices are currently supported: + +- Battery Service +- Device Information Service +- Generic Access Service +- Microbit: Accelerometer +- Microbit: Button +- Microbit: IO Pin +- Microbit: LED +- Microbit: Magnetometer +- Microbit: Temperature +- Serial Port over BLE +- Sphero: BB8 +- Sphero: Ollie +- Sphero: SPRK+ diff --git a/drivers/ble/battery_driver.go b/drivers/ble/battery_driver.go new file mode 100644 index 000000000..f97ecafef --- /dev/null +++ b/drivers/ble/battery_driver.go @@ -0,0 +1,39 @@ +package ble + +import ( + "bytes" + "log" + + "gobot.io/x/gobot/v2" +) + +const batteryCharaShort = "2a19" + +// BatteryDriver represents the battery service for a BLE peripheral +type BatteryDriver struct { + *Driver + gobot.Eventer +} + +// NewBatteryDriver creates a new driver +func NewBatteryDriver(a gobot.BLEConnector) *BatteryDriver { + d := &BatteryDriver{ + Driver: NewDriver(a, "Battery", nil, nil), + Eventer: gobot.NewEventer(), + } + + return d +} + +// GetBatteryLevel reads and returns the current battery level +func (d *BatteryDriver) GetBatteryLevel() uint8 { + c, err := d.Adaptor().ReadCharacteristic(batteryCharaShort) + if err != nil { + log.Println(err) + return 0 + } + buf := bytes.NewBuffer(c) + val, _ := buf.ReadByte() + level := val + return level +} diff --git a/drivers/ble/battery_driver_test.go b/drivers/ble/battery_driver_test.go new file mode 100644 index 000000000..6495317ff --- /dev/null +++ b/drivers/ble/battery_driver_test.go @@ -0,0 +1,33 @@ +package ble + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" +) + +var _ gobot.Driver = (*BatteryDriver)(nil) + +func TestNewBatteryDriver(t *testing.T) { + d := NewBatteryDriver(testutil.NewBleTestAdaptor()) + assert.True(t, strings.HasPrefix(d.Name(), "Battery")) + assert.NotNil(t, d.Eventer) +} + +func TestBatteryDriverRead(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewBatteryDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + if cUUID == "2a19" { + return []byte{20}, nil + } + + return nil, nil + }) + + assert.Equal(t, uint8(20), d.GetBatteryLevel()) +} diff --git a/drivers/ble/ble_driver.go b/drivers/ble/ble_driver.go new file mode 100644 index 000000000..e1b766b36 --- /dev/null +++ b/drivers/ble/ble_driver.go @@ -0,0 +1,118 @@ +package ble + +import ( + "log" + "sync" + + "gobot.io/x/gobot/v2" +) + +// optionApplier needs to be implemented by each configurable option type +type optionApplier interface { + apply(cfg *configuration) +} + +// configuration contains all changeable attributes of the driver. +type configuration struct { + name string +} + +// nameOption is the type for applying another name to the configuration +type nameOption string + +// Driver implements the interface gobot.Driver. +type Driver struct { + gobot.Commander + connection interface{} + driverCfg *configuration + afterStart func() error + beforeHalt func() error + mutex *sync.Mutex +} + +// NewDriver creates a new basic BLE gobot driver. +func NewDriver(a interface{}, name string, afterStart func() error, beforeHalt func() error) *Driver { + if afterStart == nil { + afterStart = func() error { return nil } + } + + if beforeHalt == nil { + beforeHalt = func() error { return nil } + } + + d := Driver{ + driverCfg: &configuration{name: gobot.DefaultName(name)}, + connection: a, + afterStart: afterStart, + beforeHalt: beforeHalt, + Commander: gobot.NewCommander(), + mutex: &sync.Mutex{}, + } + + return &d +} + +// WithName is used to replace the default name of the driver. +func WithName(name string) optionApplier { + return nameOption(name) +} + +// Name returns the name of the driver. +func (d *Driver) Name() string { + return d.driverCfg.name +} + +// SetName sets the name of the driver. +// Deprecated: Please use option [aio.WithName] instead. +func (d *Driver) SetName(name string) { + WithName(name).apply(d.driverCfg) +} + +// Connection returns the connection of the driver. +func (d *Driver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.driverCfg.name) + return nil +} + +// Start initializes the driver. +func (d *Driver) Start() error { + d.mutex.Lock() + defer d.mutex.Unlock() + + // currently there is nothing to do here for the driver + + return d.afterStart() +} + +// Halt halts the driver. +func (d *Driver) Halt() error { + d.mutex.Lock() + defer d.mutex.Unlock() + + // currently there is nothing to do after halt for the driver + + return d.beforeHalt() +} + +// Adaptor returns the BLE adaptor +func (d *Driver) Adaptor() gobot.BLEConnector { + if a, ok := d.connection.(gobot.BLEConnector); ok { + return a + } + + log.Printf("%s has no BLE connector\n", d.driverCfg.name) + return nil +} + +func (d *Driver) Mutex() *sync.Mutex { + return d.mutex +} + +// apply change the name in the configuration. +func (o nameOption) apply(c *configuration) { + c.name = string(o) +} diff --git a/drivers/ble/ble_driver_test.go b/drivers/ble/ble_driver_test.go new file mode 100644 index 000000000..5e40f313b --- /dev/null +++ b/drivers/ble/ble_driver_test.go @@ -0,0 +1,70 @@ +package ble + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" +) + +var _ gobot.Driver = (*Driver)(nil) + +func initTestDriver() *Driver { + a := testutil.NewBleTestAdaptor() + d := NewDriver(a, "BLE_BASIC", nil, nil) + return d +} + +func TestNewDriver(t *testing.T) { + // arrange + const name = "mybot" + a := testutil.NewBleTestAdaptor() + // act + d := NewDriver(a, name, nil, nil) + // assert + assert.IsType(t, &Driver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), name)) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) +} + +func Test_applyWithName(t *testing.T) { + // arrange + const name = "mybot" + cfg := configuration{name: "oldname"} + // act + WithName(name).apply(&cfg) + // assert + assert.Equal(t, name, cfg.name) +} + +func TestStart(t *testing.T) { + // arrange + d := initTestDriver() + // act, assert + require.NoError(t, d.Start()) + // arrange after start function + d.afterStart = func() error { return fmt.Errorf("after start error") } + // act, assert + require.EqualError(t, d.Start(), "after start error") +} + +func TestHalt(t *testing.T) { + // arrange + d := initTestDriver() + // act, assert + require.NoError(t, d.Halt()) + // arrange after start function + d.beforeHalt = func() error { return fmt.Errorf("before halt error") } + // act, assert + require.EqualError(t, d.Halt(), "before halt error") +} diff --git a/drivers/ble/device_information_driver.go b/drivers/ble/device_information_driver.go new file mode 100644 index 000000000..8eca3c21b --- /dev/null +++ b/drivers/ble/device_information_driver.go @@ -0,0 +1,92 @@ +package ble + +import ( + "bytes" + "log" + + "gobot.io/x/gobot/v2" +) + +const ( + deviceInformationModelNumberCharaShort = "2a24" + deviceInformationFirmwareRevisionCharaShort = "2a26" + deviceInformationHardwareRevisionCharaShort = "2a27" + deviceInformationManufacturerNameCharaShort = "2a29" + deviceInformationPnPIdCharaShort = "2a50" +) + +// DeviceInformationDriver represents the device information service for a BLE peripheral +type DeviceInformationDriver struct { + *Driver + gobot.Eventer +} + +// NewDeviceInformationDriver creates a new driver +func NewDeviceInformationDriver(a gobot.BLEConnector) *DeviceInformationDriver { + n := &DeviceInformationDriver{ + Driver: NewDriver(a, "DeviceInformation", nil, nil), + Eventer: gobot.NewEventer(), + } + + return n +} + +// GetModelNumber returns the model number for the BLE Peripheral +func (d *DeviceInformationDriver) GetModelNumber() string { + c, err := d.Adaptor().ReadCharacteristic(deviceInformationModelNumberCharaShort) + if err != nil { + log.Println(err) + return "" + } + buf := bytes.NewBuffer(c) + model := buf.String() + return model +} + +// GetFirmwareRevision returns the firmware revision for the BLE Peripheral +func (d *DeviceInformationDriver) GetFirmwareRevision() string { + c, err := d.Adaptor().ReadCharacteristic(deviceInformationFirmwareRevisionCharaShort) + if err != nil { + log.Println(err) + return "" + } + buf := bytes.NewBuffer(c) + val := buf.String() + return val +} + +// GetHardwareRevision returns the hardware revision for the BLE Peripheral +func (d *DeviceInformationDriver) GetHardwareRevision() string { + c, err := d.Adaptor().ReadCharacteristic(deviceInformationHardwareRevisionCharaShort) + if err != nil { + log.Println(err) + return "" + } + buf := bytes.NewBuffer(c) + val := buf.String() + return val +} + +// GetManufacturerName returns the manufacturer name for the BLE Peripheral +func (d *DeviceInformationDriver) GetManufacturerName() string { + c, err := d.Adaptor().ReadCharacteristic(deviceInformationManufacturerNameCharaShort) + if err != nil { + log.Println(err) + return "" + } + buf := bytes.NewBuffer(c) + val := buf.String() + return val +} + +// GetPnPId returns the PnP ID for the BLE Peripheral +func (d *DeviceInformationDriver) GetPnPId() string { + c, err := d.Adaptor().ReadCharacteristic(deviceInformationPnPIdCharaShort) + if err != nil { + log.Println(err) + return "" + } + buf := bytes.NewBuffer(c) + val := buf.String() + return val +} diff --git a/drivers/ble/device_information_driver_test.go b/drivers/ble/device_information_driver_test.go new file mode 100644 index 000000000..976849e6c --- /dev/null +++ b/drivers/ble/device_information_driver_test.go @@ -0,0 +1,44 @@ +package ble + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" +) + +var _ gobot.Driver = (*DeviceInformationDriver)(nil) + +func TestNewDeviceInformationDriver(t *testing.T) { + d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) + assert.True(t, strings.HasPrefix(d.Name(), "DeviceInformation")) + assert.NotNil(t, d.Eventer) +} + +func TestDeviceInformationGetModelNumber(t *testing.T) { + d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) + assert.Equal(t, "2a24", d.GetModelNumber()) +} + +func TestDeviceInformationGetFirmwareRevision(t *testing.T) { + d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) + assert.Equal(t, "2a26", d.GetFirmwareRevision()) +} + +func TestDeviceInformationGetHardwareRevision(t *testing.T) { + d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) + assert.Equal(t, "2a27", d.GetHardwareRevision()) +} + +func TestDeviceInformationGetManufacturerName(t *testing.T) { + d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) + assert.Equal(t, "2a29", d.GetManufacturerName()) +} + +func TestDeviceInformationGetPnPId(t *testing.T) { + d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) + assert.Equal(t, "2a50", d.GetPnPId()) +} diff --git a/drivers/ble/doc.go b/drivers/ble/doc.go new file mode 100644 index 000000000..45a0afc11 --- /dev/null +++ b/drivers/ble/doc.go @@ -0,0 +1,7 @@ +/* +Package ble provides the Gobot drivers for several Bluetooth LE Services. + +For more information refer to the README: +https://github.com/hybridgroup/gobot/blob/release/drivers/ble/README.md +*/ +package ble // import "gobot.io/x/gobot/v2/drivers/ble" diff --git a/platforms/ble/generic_access_driver.go b/drivers/ble/generic_access_driver.go similarity index 65% rename from platforms/ble/generic_access_driver.go rename to drivers/ble/generic_access_driver.go index 3b3f40c08..776db09ce 100644 --- a/platforms/ble/generic_access_driver.go +++ b/drivers/ble/generic_access_driver.go @@ -8,48 +8,30 @@ import ( "gobot.io/x/gobot/v2" ) +const ( + genericAccessDeviceNameCharaShort = "2a00" + genericAccessAppearanceCharaShort = "2a01" +) + // GenericAccessDriver represents the Generic Access Service for a BLE Peripheral type GenericAccessDriver struct { - name string - connection gobot.Connection + *Driver gobot.Eventer } // NewGenericAccessDriver creates a GenericAccessDriver -func NewGenericAccessDriver(a BLEConnector) *GenericAccessDriver { - n := &GenericAccessDriver{ - name: gobot.DefaultName("GenericAccess"), - connection: a, - Eventer: gobot.NewEventer(), +func NewGenericAccessDriver(a gobot.BLEConnector) *GenericAccessDriver { + d := &GenericAccessDriver{ + Driver: NewDriver(a, "GenericAccess", nil, nil), + Eventer: gobot.NewEventer(), } - return n + return d } -// Connection returns the Driver's Connection to the associated Adaptor -func (b *GenericAccessDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver name -func (b *GenericAccessDriver) Name() string { return b.name } - -// SetName sets the Driver name -func (b *GenericAccessDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor for this device -func (b *GenericAccessDriver) adaptor() BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *GenericAccessDriver) Start() error { return nil } - -// Halt stops driver (void) -func (b *GenericAccessDriver) Halt() error { return nil } - // GetDeviceName returns the device name for the BLE Peripheral -func (b *GenericAccessDriver) GetDeviceName() string { - c, err := b.adaptor().ReadCharacteristic("2a00") +func (d *GenericAccessDriver) GetDeviceName() string { + c, err := d.Adaptor().ReadCharacteristic(genericAccessDeviceNameCharaShort) if err != nil { log.Println(err) return "" @@ -61,8 +43,8 @@ func (b *GenericAccessDriver) GetDeviceName() string { } // GetAppearance returns the appearance string for the BLE Peripheral -func (b *GenericAccessDriver) GetAppearance() string { - c, err := b.adaptor().ReadCharacteristic("2a01") +func (d *GenericAccessDriver) GetAppearance() string { + c, err := d.Adaptor().ReadCharacteristic(genericAccessAppearanceCharaShort) if err != nil { log.Println(err) return "" diff --git a/drivers/ble/generic_access_driver_test.go b/drivers/ble/generic_access_driver_test.go new file mode 100644 index 000000000..845cc5881 --- /dev/null +++ b/drivers/ble/generic_access_driver_test.go @@ -0,0 +1,37 @@ +package ble + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" +) + +var _ gobot.Driver = (*GenericAccessDriver)(nil) + +func TestNewGenericAccessDriver(t *testing.T) { + d := NewGenericAccessDriver(testutil.NewBleTestAdaptor()) + assert.True(t, strings.HasPrefix(d.Name(), "GenericAccess")) + assert.NotNil(t, d.Eventer) +} + +func TestGenericAccessDriverGetDeviceName(t *testing.T) { + d := NewGenericAccessDriver(testutil.NewBleTestAdaptor()) + assert.Equal(t, "2a00", d.GetDeviceName()) +} + +func TestGenericAccessDriverGetAppearance(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewGenericAccessDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + if cUUID == "2a01" { + return []byte{128, 0}, nil + } + return nil, nil + }) + + assert.Equal(t, "Generic Computer", d.GetAppearance()) +} diff --git a/drivers/ble/microbit/LICENSE b/drivers/ble/microbit/LICENSE new file mode 100644 index 000000000..257d22e97 --- /dev/null +++ b/drivers/ble/microbit/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2014-2018 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/ble/microbit/accelerometer_driver.go b/drivers/ble/microbit/accelerometer_driver.go new file mode 100644 index 000000000..634bee816 --- /dev/null +++ b/drivers/ble/microbit/accelerometer_driver.go @@ -0,0 +1,67 @@ +package microbit + +import ( + "bytes" + "encoding/binary" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" +) + +const ( + // accelerometerService = "e95d0753251d470aa062fa1922dfa9a8" + accelerometerChara = "e95dca4b251d470aa062fa1922dfa9a8" + + AccelerometerEvent = "accelerometer" +) + +// AccelerometerDriver is the Gobot driver for the Microbit's built-in accelerometer +type AccelerometerDriver struct { + *ble.Driver + gobot.Eventer +} + +type AccelerometerData struct { + X float32 + Y float32 + Z float32 +} + +// NewAccelerometerDriver creates a AccelerometerDriver +func NewAccelerometerDriver(a gobot.BLEConnector) *AccelerometerDriver { + d := &AccelerometerDriver{ + Eventer: gobot.NewEventer(), + } + d.Driver = ble.NewDriver(a, "Microbit Accelerometer", d.initialize, nil) + + d.AddEvent(AccelerometerEvent) + + return d +} + +// initialize tells driver to get ready to do work +func (d *AccelerometerDriver) initialize() error { + // subscribe to accelerometer notifications + return d.Adaptor().Subscribe(accelerometerChara, func(data []byte, e error) { + a := struct{ x, y, z int16 }{x: 0, y: 0, z: 0} + + buf := bytes.NewBuffer(data) + if err := binary.Read(buf, binary.LittleEndian, &a.x); err != nil { + panic(err) + } + if err := binary.Read(buf, binary.LittleEndian, &a.y); err != nil { + panic(err) + } + if err := binary.Read(buf, binary.LittleEndian, &a.z); err != nil { + panic(err) + } + + result := &AccelerometerData{ + X: float32(a.x) / 1000.0, + Y: float32(a.y) / 1000.0, + Z: float32(a.z) / 1000.0, + } + + d.Publish(d.Event(AccelerometerEvent), result) + }) +} diff --git a/platforms/microbit/accelerometer_driver_test.go b/drivers/ble/microbit/accelerometer_driver_test.go similarity index 57% rename from platforms/microbit/accelerometer_driver_test.go rename to drivers/ble/microbit/accelerometer_driver_test.go index 33ea547a5..fd59c2528 100644 --- a/platforms/microbit/accelerometer_driver_test.go +++ b/drivers/ble/microbit/accelerometer_driver_test.go @@ -10,41 +10,40 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" ) var _ gobot.Driver = (*AccelerometerDriver)(nil) -func initTestAccelerometerDriver() *AccelerometerDriver { - d := NewAccelerometerDriver(NewBleTestAdaptor()) - return d -} - -func TestAccelerometerDriver(t *testing.T) { - d := initTestAccelerometerDriver() +func TestNewAccelerometerDriver(t *testing.T) { + d := NewAccelerometerDriver(testutil.NewBleTestAdaptor()) + assert.IsType(t, &AccelerometerDriver{}, d) assert.True(t, strings.HasPrefix(d.Name(), "Microbit Accelerometer")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) + assert.NotNil(t, d.Eventer) } -func TestAccelerometerDriverStartAndHalt(t *testing.T) { - d := initTestAccelerometerDriver() +func TestAccelerometerStartAndHalt(t *testing.T) { + d := NewAccelerometerDriver(testutil.NewBleTestAdaptor()) require.NoError(t, d.Start()) require.NoError(t, d.Halt()) } -func TestAccelerometerDriverReadData(t *testing.T) { +func TestAccelerometerReadData(t *testing.T) { sem := make(chan bool) - a := NewBleTestAdaptor() + a := testutil.NewBleTestAdaptor() d := NewAccelerometerDriver(a) - _ = d.Start() - _ = d.On(Accelerometer, func(data interface{}) { + require.NoError(t, d.Start()) + + err := d.On("accelerometer", func(data interface{}) { assert.InDelta(t, float32(8.738), data.(*AccelerometerData).X, 0.0) assert.InDelta(t, float32(8.995), data.(*AccelerometerData).Y, 0.0) assert.InDelta(t, float32(9.252), data.(*AccelerometerData).Z, 0.0) sem <- true }) - a.TestReceiveNotification([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, nil) + require.NoError(t, err) + + a.SendTestDataToSubscriber([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, nil) select { case <-sem: diff --git a/drivers/ble/microbit/button_driver.go b/drivers/ble/microbit/button_driver.go new file mode 100644 index 000000000..a095f3828 --- /dev/null +++ b/drivers/ble/microbit/button_driver.go @@ -0,0 +1,50 @@ +package microbit + +import ( + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" +) + +const ( + // buttonService = "e95d9882251d470aa062fa1922dfa9a8" + buttonAChara = "e95dda90251d470aa062fa1922dfa9a8" + buttonBChara = "e95dda91251d470aa062fa1922dfa9a8" + + ButtonAEvent = "buttonA" + ButtonBEvent = "buttonB" +) + +// ButtonDriver is the Gobot driver for the Microbit's built-in buttons +type ButtonDriver struct { + *ble.Driver + gobot.Eventer +} + +// NewButtonDriver creates a new driver +func NewButtonDriver(a gobot.BLEConnector) *ButtonDriver { + d := &ButtonDriver{ + Eventer: gobot.NewEventer(), + } + + d.Driver = ble.NewDriver(a, "Microbit Button", d.initialize, nil) + + d.AddEvent(ButtonAEvent) + d.AddEvent(ButtonBEvent) + + return d +} + +// initialize tells driver to get ready to do work +func (d *ButtonDriver) initialize() error { + // subscribe to button A notifications + if err := d.Adaptor().Subscribe(buttonAChara, func(data []byte, e error) { + d.Publish(d.Event(ButtonAEvent), data) + }); err != nil { + return err + } + + // subscribe to button B notifications + return d.Adaptor().Subscribe(buttonBChara, func(data []byte, e error) { + d.Publish(d.Event(ButtonBEvent), data) + }) +} diff --git a/platforms/microbit/button_driver_test.go b/drivers/ble/microbit/button_driver_test.go similarity index 50% rename from platforms/microbit/button_driver_test.go rename to drivers/ble/microbit/button_driver_test.go index be92c0ed7..886bc05e9 100644 --- a/platforms/microbit/button_driver_test.go +++ b/drivers/ble/microbit/button_driver_test.go @@ -9,38 +9,36 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" ) var _ gobot.Driver = (*ButtonDriver)(nil) -func initTestButtonDriver() *ButtonDriver { - d := NewButtonDriver(NewBleTestAdaptor()) - return d -} - -func TestButtonDriver(t *testing.T) { - d := initTestButtonDriver() +func TestNewButtonDriver(t *testing.T) { + d := NewButtonDriver(testutil.NewBleTestAdaptor()) + assert.IsType(t, &ButtonDriver{}, d) assert.True(t, strings.HasPrefix(d.Name(), "Microbit Button")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) + assert.NotNil(t, d.Eventer) } -func TestButtonDriverStartAndHalt(t *testing.T) { - d := initTestButtonDriver() +func TestButtonStartAndHalt(t *testing.T) { + d := NewButtonDriver(testutil.NewBleTestAdaptor()) require.NoError(t, d.Start()) require.NoError(t, d.Halt()) } -func TestButtonDriverReadData(t *testing.T) { +func TestButtonReadData(t *testing.T) { sem := make(chan bool) - a := NewBleTestAdaptor() + a := testutil.NewBleTestAdaptor() d := NewButtonDriver(a) - _ = d.Start() - _ = d.On(ButtonB, func(data interface{}) { + require.NoError(t, d.Start()) + + err := d.On("buttonB", func(data interface{}) { sem <- true }) + require.NoError(t, err) - a.TestReceiveNotification([]byte{1}, nil) + a.SendTestDataToSubscriber([]byte{1}, nil) select { case <-sem: diff --git a/drivers/ble/microbit/doc.go b/drivers/ble/microbit/doc.go new file mode 100644 index 000000000..285a0ca6d --- /dev/null +++ b/drivers/ble/microbit/doc.go @@ -0,0 +1,7 @@ +/* +Package microbit contains the Gobot drivers for the Microbit platform. + +For more information refer to the microbit README: +https://github.com/hybridgroup/gobot/blob/release/platforms/microbit/README.md +*/ +package microbit // import "gobot.io/x/gobot/v2/drivers/ble/microbit" diff --git a/drivers/ble/microbit/io_pin_driver.go b/drivers/ble/microbit/io_pin_driver.go new file mode 100644 index 000000000..883568fc3 --- /dev/null +++ b/drivers/ble/microbit/io_pin_driver.go @@ -0,0 +1,250 @@ +package microbit + +import ( + "bytes" + "encoding/binary" + "errors" + "strconv" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/drivers/common/bit" +) + +const ( + // ioPinService = "e95d127b251d470aa062fa1922dfa9a8" + pinDataChara = "e95d8d00251d470aa062fa1922dfa9a8" + pinADConfigChara = "e95d5899251d470aa062fa1922dfa9a8" + pinIOConfigChara = "e95db9fe251d470aa062fa1922dfa9a8" +) + +// IOPinDriver is the Gobot driver for the Microbit's built-in digital and analog I/O +type IOPinDriver struct { + *ble.Driver + adMask int + ioMask int + gobot.Eventer +} + +// pinData has the read data for a specific digital pin +type pinData struct { + pin uint8 + value uint8 +} + +// NewIOPinDriver creates a new driver +func NewIOPinDriver(a gobot.BLEConnector) *IOPinDriver { + d := &IOPinDriver{ + Eventer: gobot.NewEventer(), + } + + d.Driver = ble.NewDriver(a, "Microbit IO Pins", d.initialize, nil) + + return d +} + +// initialize tells driver to get ready to do work +func (d *IOPinDriver) initialize() error { + if _, err := d.ReadPinADConfig(); err != nil { + return err + } + _, err := d.ReadPinIOConfig() + return err +} + +// WritePinData writes the pin data for a single pin +func (d *IOPinDriver) WritePinData(pin string, data byte) error { + i, err := strconv.Atoi(pin) + if err != nil { + return err + } + + buf := []byte{byte(i), data} + err = d.Adaptor().WriteCharacteristic(pinDataChara, buf) + return err +} + +// ReadPinADConfig reads and returns the pin A/D config mask for all pins +func (d *IOPinDriver) ReadPinADConfig() (int, error) { + c, err := d.Adaptor().ReadCharacteristic(pinADConfigChara) + if err != nil { + return 0, err + } + var result byte + for i := 0; i < 4; i++ { + result |= c[i] << uint(i) + } + + d.adMask = int(result) + return int(result), nil +} + +// WritePinADConfig writes the pin A/D config mask for all pins +func (d *IOPinDriver) WritePinADConfig(config int) error { + d.adMask = config + data := &bytes.Buffer{} + if err := binary.Write(data, binary.LittleEndian, uint32(config)); err != nil { + return err + } + + return d.Adaptor().WriteCharacteristic(pinADConfigChara, data.Bytes()) +} + +// ReadPinIOConfig reads and returns the pin IO config mask for all pins +func (d *IOPinDriver) ReadPinIOConfig() (int, error) { + c, err := d.Adaptor().ReadCharacteristic(pinIOConfigChara) + if err != nil { + return 0, err + } + + var result byte + for i := 0; i < 4; i++ { + result |= c[i] << uint(i) + } + + d.ioMask = int(result) + return int(result), nil +} + +// WritePinIOConfig writes the pin I/O config mask for all pins +func (d *IOPinDriver) WritePinIOConfig(config int) error { + d.ioMask = config + data := &bytes.Buffer{} + if err := binary.Write(data, binary.LittleEndian, uint32(config)); err != nil { + return err + } + + return d.Adaptor().WriteCharacteristic(pinIOConfigChara, data.Bytes()) +} + +// DigitalRead reads from a pin +func (d *IOPinDriver) DigitalRead(pin string) (int, error) { + p, err := validatedPin(pin) + if err != nil { + return 0, err + } + + if err := d.ensureDigital(p); err != nil { + return 0, err + } + if err := d.ensureInput(p); err != nil { + return 0, err + } + + pins, err := d.readAllPinData() + if err != nil { + return 0, err + } + + return int(pins[p].value), nil +} + +// DigitalWrite writes to a pin +func (d *IOPinDriver) DigitalWrite(pin string, level byte) error { + p, err := validatedPin(pin) + if err != nil { + return err + } + + if err := d.ensureDigital(p); err != nil { + return err + } + if err := d.ensureOutput(p); err != nil { + return err + } + + return d.WritePinData(pin, level) +} + +// AnalogRead reads from a pin +func (d *IOPinDriver) AnalogRead(pin string) (int, error) { + p, err := validatedPin(pin) + if err != nil { + return 0, err + } + + if err := d.ensureAnalog(p); err != nil { + return 0, err + } + if err := d.ensureInput(p); err != nil { + return 0, err + } + + pins, err := d.readAllPinData() + if err != nil { + return 0, err + } + + return int(pins[p].value), nil +} + +func (d *IOPinDriver) ensureDigital(pin int) error { + if bit.IsSet(d.adMask, uint8(pin)) { + return d.WritePinADConfig(bit.Clear(d.adMask, uint8(pin))) + } + + return nil +} + +func (d *IOPinDriver) ensureAnalog(pin int) error { + if !bit.IsSet(d.adMask, uint8(pin)) { + return d.WritePinADConfig(bit.Set(d.adMask, uint8(pin))) + } + + return nil +} + +func (d *IOPinDriver) ensureInput(pin int) error { + if !bit.IsSet(d.ioMask, uint8(pin)) { + return d.WritePinIOConfig(bit.Set(d.ioMask, uint8(pin))) + } + + return nil +} + +func (d *IOPinDriver) ensureOutput(pin int) error { + if bit.IsSet(d.ioMask, uint8(pin)) { + return d.WritePinIOConfig(bit.Clear(d.ioMask, uint8(pin))) + } + + return nil +} + +func (d *IOPinDriver) readAllPinData() ([]pinData, error) { + c, _ := d.Adaptor().ReadCharacteristic(pinDataChara) + buf := bytes.NewBuffer(c) + pinsData := make([]pinData, buf.Len()/2) + + for i := 0; i < buf.Len()/2; i++ { + pin, err := buf.ReadByte() + if err != nil { + return nil, err + } + + value, err := buf.ReadByte() + if err != nil { + return nil, err + } + + pinData := pinData{ + pin: pin, + value: value, + } + pinsData[i] = pinData + } + + return pinsData, nil +} + +func validatedPin(pin string) (int, error) { + i, err := strconv.Atoi(pin) + if err != nil { + return 0, err + } + + if i < 0 || i > 2 { + return 0, errors.New("Invalid pin.") + } + + return i, nil +} diff --git a/drivers/ble/microbit/io_pin_driver_test.go b/drivers/ble/microbit/io_pin_driver_test.go new file mode 100644 index 000000000..f73c1d27e --- /dev/null +++ b/drivers/ble/microbit/io_pin_driver_test.go @@ -0,0 +1,165 @@ +package microbit + +import ( + "errors" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/aio" + "gobot.io/x/gobot/v2/drivers/ble/testutil" + "gobot.io/x/gobot/v2/drivers/gpio" +) + +// the MicrobitIOPinDriver is a Driver +var _ gobot.Driver = (*IOPinDriver)(nil) + +// that supports the DigitalReader, DigitalWriter, & AnalogReader interfaces +var ( + _ gpio.DigitalReader = (*IOPinDriver)(nil) + _ gpio.DigitalWriter = (*IOPinDriver)(nil) + _ aio.AnalogReader = (*IOPinDriver)(nil) +) + +func TestNewIOPinDriver(t *testing.T) { + d := NewIOPinDriver(testutil.NewBleTestAdaptor()) + assert.IsType(t, &IOPinDriver{}, d) + assert.True(t, strings.HasPrefix(d.Name(), "Microbit IO Pin")) + assert.NotNil(t, d.Eventer) +} + +func TestIOPinStartAndHalt(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + return []byte{0, 1, 1, 0}, nil + }) + require.NoError(t, d.Start()) + require.NoError(t, d.Halt()) +} + +func TestIOPinStartError(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + return nil, errors.New("read error") + }) + require.ErrorContains(t, d.Start(), "read error") +} + +func TestIOPinDigitalRead(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + return []byte{0, 1, 1, 0, 2, 1}, nil + }) + + val, err := d.DigitalRead("0") + require.NoError(t, err) + assert.Equal(t, 1, val) + + val, err = d.DigitalRead("1") + require.NoError(t, err) + assert.Equal(t, 0, val) +} + +func TestIOPinDigitalReadInvalidPin(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + + _, err := d.DigitalRead("A3") + require.Error(t, err) + + _, err = d.DigitalRead("6") + require.ErrorContains(t, err, "Invalid pin.") +} + +func TestIOPinDigitalWrite(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + + // TODO: a better test + require.NoError(t, d.DigitalWrite("0", 1)) +} + +func TestIOPinDigitalWriteInvalidPin(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + + require.Error(t, d.DigitalWrite("A3", 1)) + require.ErrorContains(t, d.DigitalWrite("6", 1), "Invalid pin.") +} + +func TestIOPinAnalogRead(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + return []byte{0, 0, 1, 128, 2, 1}, nil + }) + + val, err := d.AnalogRead("0") + require.NoError(t, err) + assert.Equal(t, 0, val) + + val, err = d.AnalogRead("1") + require.NoError(t, err) + assert.Equal(t, 128, val) +} + +func TestIOPinAnalogReadInvalidPin(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + + _, err := d.AnalogRead("A3") + require.Error(t, err) + + _, err = d.AnalogRead("6") + require.ErrorContains(t, err, "Invalid pin.") +} + +func TestIOPinDigitalAnalogRead(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + return []byte{0, 0, 1, 128, 2, 1}, nil + }) + + val, err := d.DigitalRead("0") + require.NoError(t, err) + assert.Equal(t, 0, val) + + val, err = d.AnalogRead("0") + require.NoError(t, err) + assert.Equal(t, 0, val) +} + +func TestIOPinDigitalWriteAnalogRead(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + return []byte{0, 0, 1, 128, 2, 1}, nil + }) + + require.NoError(t, d.DigitalWrite("1", 0)) + + val, err := d.AnalogRead("1") + require.NoError(t, err) + assert.Equal(t, 128, val) +} + +func TestIOPinAnalogReadDigitalWrite(t *testing.T) { + a := testutil.NewBleTestAdaptor() + d := NewIOPinDriver(a) + a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { + return []byte{0, 0, 1, 128, 2, 1}, nil + }) + + val, err := d.AnalogRead("1") + require.NoError(t, err) + assert.Equal(t, 128, val) + + require.NoError(t, d.DigitalWrite("1", 0)) +} diff --git a/platforms/microbit/led_driver.go b/drivers/ble/microbit/led_driver.go similarity index 62% rename from platforms/microbit/led_driver.go rename to drivers/ble/microbit/led_driver.go index 83a42afe4..3de8a5b30 100644 --- a/platforms/microbit/led_driver.go +++ b/drivers/ble/microbit/led_driver.go @@ -2,71 +2,46 @@ package microbit import ( "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble" +) + +const ( + // ledService = "e95dd91d251d470aa062fa1922dfa9a8" + ledMatrixStateChara = "e95d7b77251d470aa062fa1922dfa9a8" + ledTextChara = "e95d93ee251d470aa062fa1922dfa9a8" + ledScrollingDelayChara = "e95d0d2d251d470aa062fa1922dfa9a8" ) // LEDDriver is the Gobot driver for the Microbit's LED array type LEDDriver struct { - name string - connection gobot.Connection + *ble.Driver gobot.Eventer } -const ( - // BLE services - // ledService = "e95dd91d251d470aa062fa1922dfa9a8" - - // BLE characteristics - ledMatrixStateCharacteristic = "e95d7b77251d470aa062fa1922dfa9a8" - ledTextCharacteristic = "e95d93ee251d470aa062fa1922dfa9a8" - ledScrollingDelayCharacteristic = "e95d0d2d251d470aa062fa1922dfa9a8" -) - // NewLEDDriver creates a Microbit LEDDriver -func NewLEDDriver(a ble.BLEConnector) *LEDDriver { - n := &LEDDriver{ - name: gobot.DefaultName("Microbit LED"), - connection: a, - Eventer: gobot.NewEventer(), +func NewLEDDriver(a gobot.BLEConnector) *LEDDriver { + d := &LEDDriver{ + Eventer: gobot.NewEventer(), } - return n -} - -// Connection returns the BLE connection -func (b *LEDDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver Name -func (b *LEDDriver) Name() string { return b.name } + d.Driver = ble.NewDriver(a, "Microbit LED", nil, nil) -// SetName sets the Driver Name -func (b *LEDDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *LEDDriver) adaptor() ble.BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(ble.BLEConnector) + return d } -// Start tells driver to get ready to do work -func (b *LEDDriver) Start() error { return nil } - -// Halt stops LED driver (void) -func (b *LEDDriver) Halt() error { return nil } - // ReadMatrix read the current LED matrix state func (b *LEDDriver) ReadMatrix() ([]byte, error) { - return b.adaptor().ReadCharacteristic(ledMatrixStateCharacteristic) + return b.Adaptor().ReadCharacteristic(ledMatrixStateChara) } // WriteMatrix writes an array of 5 bytes to set the LED matrix func (b *LEDDriver) WriteMatrix(data []byte) error { - return b.adaptor().WriteCharacteristic(ledMatrixStateCharacteristic, data) + return b.Adaptor().WriteCharacteristic(ledMatrixStateChara, data) } // WriteText writes a text message to the Microbit LED matrix func (b *LEDDriver) WriteText(msg string) error { - return b.adaptor().WriteCharacteristic(ledTextCharacteristic, []byte(msg)) + return b.Adaptor().WriteCharacteristic(ledTextChara, []byte(msg)) } func (b *LEDDriver) ReadScrollingDelay() (uint16, error) { @@ -75,7 +50,7 @@ func (b *LEDDriver) ReadScrollingDelay() (uint16, error) { func (b *LEDDriver) WriteScrollingDelay(delay uint16) error { buf := []byte{byte(delay)} - return b.adaptor().WriteCharacteristic(ledScrollingDelayCharacteristic, buf) + return b.Adaptor().WriteCharacteristic(ledScrollingDelayChara, buf) } // Blank clears the LEDs on the Microbit diff --git a/platforms/microbit/led_driver_test.go b/drivers/ble/microbit/led_driver_test.go similarity index 62% rename from platforms/microbit/led_driver_test.go rename to drivers/ble/microbit/led_driver_test.go index a59039dfb..18e09e7ef 100644 --- a/platforms/microbit/led_driver_test.go +++ b/drivers/ble/microbit/led_driver_test.go @@ -8,43 +8,35 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" ) var _ gobot.Driver = (*LEDDriver)(nil) func initTestLEDDriver() *LEDDriver { - d := NewLEDDriver(NewBleTestAdaptor()) + d := NewLEDDriver(testutil.NewBleTestAdaptor()) return d } -func TestLEDDriver(t *testing.T) { - d := initTestLEDDriver() +func TestNewLEDDriver(t *testing.T) { + d := NewLEDDriver(testutil.NewBleTestAdaptor()) + assert.IsType(t, &LEDDriver{}, d) assert.True(t, strings.HasPrefix(d.Name(), "Microbit LED")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) -} - -func TestLEDDriverStartAndHalt(t *testing.T) { - d := initTestLEDDriver() - require.NoError(t, d.Start()) - require.NoError(t, d.Halt()) + assert.NotNil(t, d.Eventer) } -func TestLEDDriverWriteMatrix(t *testing.T) { +func TestLEDWriteMatrix(t *testing.T) { d := initTestLEDDriver() - _ = d.Start() require.NoError(t, d.WriteMatrix([]byte{0x01, 0x02})) } -func TestLEDDriverWriteText(t *testing.T) { +func TestLEDWriteText(t *testing.T) { d := initTestLEDDriver() - _ = d.Start() require.NoError(t, d.WriteText("Hello")) } -func TestLEDDriverCommands(t *testing.T) { +func TestLEDCommands(t *testing.T) { d := initTestLEDDriver() - _ = d.Start() require.NoError(t, d.Blank()) require.NoError(t, d.Solid()) require.NoError(t, d.UpRightArrow()) diff --git a/drivers/ble/microbit/magnetometer_driver.go b/drivers/ble/microbit/magnetometer_driver.go new file mode 100644 index 000000000..2fb8972e0 --- /dev/null +++ b/drivers/ble/microbit/magnetometer_driver.go @@ -0,0 +1,67 @@ +package microbit + +import ( + "bytes" + "encoding/binary" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" +) + +const ( + // magnetometerService = "e95df2d8251d470aa062fa1922dfa9a8" + magnetometerChara = "e95dfb11251d470aa062fa1922dfa9a8" + + MagnetometerEvent = "magnetometer" +) + +// MagnetometerDriver is the Gobot driver for the Microbit's built-in magnetometer +type MagnetometerDriver struct { + *ble.Driver + gobot.Eventer +} + +type MagnetometerData struct { + X float32 + Y float32 + Z float32 +} + +// NewMagnetometerDriver creates a Microbit MagnetometerDriver +func NewMagnetometerDriver(a gobot.BLEConnector) *MagnetometerDriver { + d := &MagnetometerDriver{ + Eventer: gobot.NewEventer(), + } + d.Driver = ble.NewDriver(a, "Microbit Magnetometer", d.initialize, nil) + + d.AddEvent(MagnetometerEvent) + + return d +} + +// initialize tells driver to get ready to do work +func (d *MagnetometerDriver) initialize() error { + // subscribe to magnetometer notifications + return d.Adaptor().Subscribe(magnetometerChara, func(data []byte, e error) { + a := struct{ x, y, z int16 }{x: 0, y: 0, z: 0} + + buf := bytes.NewBuffer(data) + if err := binary.Read(buf, binary.LittleEndian, &a.x); err != nil { + panic(err) + } + if err := binary.Read(buf, binary.LittleEndian, &a.y); err != nil { + panic(err) + } + if err := binary.Read(buf, binary.LittleEndian, &a.z); err != nil { + panic(err) + } + + result := &MagnetometerData{ + X: float32(a.x) / 1000.0, + Y: float32(a.y) / 1000.0, + Z: float32(a.z) / 1000.0, + } + + d.Publish(d.Event(MagnetometerEvent), result) + }) +} diff --git a/platforms/microbit/magnetometer_driver_test.go b/drivers/ble/microbit/magnetometer_driver_test.go similarity index 63% rename from platforms/microbit/magnetometer_driver_test.go rename to drivers/ble/microbit/magnetometer_driver_test.go index 5a7d31f1f..9cd098243 100644 --- a/platforms/microbit/magnetometer_driver_test.go +++ b/drivers/ble/microbit/magnetometer_driver_test.go @@ -10,41 +10,43 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" ) var _ gobot.Driver = (*MagnetometerDriver)(nil) func initTestMagnetometerDriver() *MagnetometerDriver { - d := NewMagnetometerDriver(NewBleTestAdaptor()) + d := NewMagnetometerDriver(testutil.NewBleTestAdaptor()) return d } func TestMagnetometerDriver(t *testing.T) { - d := initTestMagnetometerDriver() + d := NewMagnetometerDriver(testutil.NewBleTestAdaptor()) + assert.IsType(t, &MagnetometerDriver{}, d) assert.True(t, strings.HasPrefix(d.Name(), "Microbit Magnetometer")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) + assert.NotNil(t, d.Eventer) } -func TestMagnetometerDriverStartAndHalt(t *testing.T) { +func TestMagnetometerStartAndHalt(t *testing.T) { d := initTestMagnetometerDriver() require.NoError(t, d.Start()) require.NoError(t, d.Halt()) } -func TestMagnetometerDriverReadData(t *testing.T) { +func TestMagnetometerReadData(t *testing.T) { sem := make(chan bool) - a := NewBleTestAdaptor() + a := testutil.NewBleTestAdaptor() d := NewMagnetometerDriver(a) - _ = d.Start() - _ = d.On(Magnetometer, func(data interface{}) { + require.NoError(t, d.Start()) + err := d.On("magnetometer", func(data interface{}) { assert.InDelta(t, float32(8.738), data.(*MagnetometerData).X, 0.0) assert.InDelta(t, float32(8.995), data.(*MagnetometerData).Y, 0.0) assert.InDelta(t, float32(9.252), data.(*MagnetometerData).Z, 0.0) sem <- true }) + require.NoError(t, err) - a.TestReceiveNotification([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, nil) + a.SendTestDataToSubscriber([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, nil) select { case <-sem: diff --git a/drivers/ble/microbit/temperature_driver.go b/drivers/ble/microbit/temperature_driver.go new file mode 100644 index 000000000..6eb6ac373 --- /dev/null +++ b/drivers/ble/microbit/temperature_driver.go @@ -0,0 +1,46 @@ +package microbit + +import ( + "bytes" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" +) + +const ( + // temperatureService = "e95d6100251d470aa062fa1922dfa9a8" + temperatureChara = "e95d9250251d470aa062fa1922dfa9a8" + + TemperatureEvent = "temperature" +) + +// TemperatureDriver is the Gobot driver for the Microbit's built-in thermometer +type TemperatureDriver struct { + *ble.Driver + gobot.Eventer +} + +// NewTemperatureDriver creates a Microbit TemperatureDriver +func NewTemperatureDriver(a gobot.BLEConnector) *TemperatureDriver { + d := &TemperatureDriver{ + Eventer: gobot.NewEventer(), + } + d.Driver = ble.NewDriver(a, "Microbit Temperature", d.initialize, nil) + + d.AddEvent(TemperatureEvent) + + return d +} + +// initialize tells driver to get ready to do work +func (d *TemperatureDriver) initialize() error { + // subscribe to temperature notifications + return d.Adaptor().Subscribe(temperatureChara, func(data []byte, e error) { + var l int8 + buf := bytes.NewBuffer(data) + val, _ := buf.ReadByte() + l = int8(val) + + d.Publish(d.Event(TemperatureEvent), l) + }) +} diff --git a/platforms/microbit/temperature_driver_test.go b/drivers/ble/microbit/temperature_driver_test.go similarity index 62% rename from platforms/microbit/temperature_driver_test.go rename to drivers/ble/microbit/temperature_driver_test.go index 3d4a81db9..070537ddd 100644 --- a/platforms/microbit/temperature_driver_test.go +++ b/drivers/ble/microbit/temperature_driver_test.go @@ -9,39 +9,41 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" ) var _ gobot.Driver = (*TemperatureDriver)(nil) func initTestTemperatureDriver() *TemperatureDriver { - d := NewTemperatureDriver(NewBleTestAdaptor()) + d := NewTemperatureDriver(testutil.NewBleTestAdaptor()) return d } func TestTemperatureDriver(t *testing.T) { d := initTestTemperatureDriver() + assert.IsType(t, &TemperatureDriver{}, d) assert.True(t, strings.HasPrefix(d.Name(), "Microbit Temperature")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) + assert.NotNil(t, d.Eventer) } -func TestTemperatureDriverStartAndHalt(t *testing.T) { +func TestTemperatureStartAndHalt(t *testing.T) { d := initTestTemperatureDriver() require.NoError(t, d.Start()) require.NoError(t, d.Halt()) } -func TestTemperatureDriverReadData(t *testing.T) { +func TestTemperatureReadData(t *testing.T) { sem := make(chan bool) - a := NewBleTestAdaptor() + a := testutil.NewBleTestAdaptor() d := NewTemperatureDriver(a) - _ = d.Start() - _ = d.On(Temperature, func(data interface{}) { + require.NoError(t, d.Start()) + err := d.On("temperature", func(data interface{}) { assert.Equal(t, int8(0x22), data) sem <- true }) + require.NoError(t, err) - a.TestReceiveNotification([]byte{0x22}, nil) + a.SendTestDataToSubscriber([]byte{0x22}, nil) select { case <-sem: diff --git a/drivers/ble/parrot/LICENSE b/drivers/ble/parrot/LICENSE new file mode 100644 index 000000000..257d22e97 --- /dev/null +++ b/drivers/ble/parrot/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2014-2018 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/ble/parrot/doc.go b/drivers/ble/parrot/doc.go new file mode 100644 index 000000000..749ce5033 --- /dev/null +++ b/drivers/ble/parrot/doc.go @@ -0,0 +1,7 @@ +/* +Package parrot contains the Gobot driver for the Parrot Minidrone platform. + +For more information refer to the minidrone README: +https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/minidrone/README.md +*/ +package parrot // import "gobot.io/x/gobot/v2/drivers/ble/parrot" diff --git a/drivers/ble/parrot/minidrone_driver.go b/drivers/ble/parrot/minidrone_driver.go new file mode 100644 index 000000000..f1fee75cb --- /dev/null +++ b/drivers/ble/parrot/minidrone_driver.go @@ -0,0 +1,503 @@ +package parrot + +import ( + "bytes" + "encoding/binary" + "fmt" + "math" + "sync" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" +) + +const ( + // droneCommandService = "9a66fa000800919111e4012d1540cb8e" + // droneNotificationService = "9a66fb000800919111e4012d1540cb8e" + + // send characteristics + pcmdChara = "9a66fa0a0800919111e4012d1540cb8e" + commandChara = "9a66fa0b0800919111e4012d1540cb8e" + priorityChara = "9a66fa0c0800919111e4012d1540cb8e" + + // receive characteristics + flightStatusChara = "9a66fb0e0800919111e4012d1540cb8e" + batteryChara = "9a66fb0f0800919111e4012d1540cb8e" + + // piloting states + flatTrimChanged = 0 + flyingStateChanged = 1 + + // flying states + flyingStateLanded = 0 + flyingStateTakeoff = 1 + flyingStateHovering = 2 + flyingStateFlying = 3 + flyingStateLanding = 4 + flyingStateEmergency = 5 + flyingStateRolling = 6 + + BatteryEvent = "battery" + FlightStatusEvent = "flightstatus" + TakeoffEvent = "takeoff" + HoveringEvent = "hovering" + FlyingEvent = "flying" + LandingEvent = "landing" + LandedEvent = "landed" + EmergencyEvent = "emergency" + RollingEvent = "rolling" + FlatTrimChangeEvent = "flattrimchange" + + // modes for LightControl + LightFixed = 0 + LightBlinked = 1 + LightOscillated = 3 + + // modes for ClawControl + ClawOpen = 0 + ClawClosed = 1 +) + +// MinidroneDriver is the Gobot interface to the Parrot Minidrone +type MinidroneDriver struct { + *ble.Driver + stepsfa0a uint16 + stepsfa0b uint16 + pcmdMutex sync.Mutex + flying bool + Pcmd Pcmd + gobot.Eventer +} + +// Pcmd is the Parrot Command structure for flight control +type Pcmd struct { + Flag int + Roll int + Pitch int + Yaw int + Gaz int + Psi float32 +} + +// NewDriver creates a Parrot Minidrone Driver +func NewMinidroneDriver(a gobot.BLEConnector) *MinidroneDriver { + d := &MinidroneDriver{ + Pcmd: Pcmd{ + Flag: 0, + Roll: 0, + Pitch: 0, + Yaw: 0, + Gaz: 0, + Psi: 0, + }, + Eventer: gobot.NewEventer(), + } + d.Driver = ble.NewDriver(a, "Minidrone", d.initialize, d.shutdown) + + d.AddEvent(BatteryEvent) + d.AddEvent(FlightStatusEvent) + d.AddEvent(TakeoffEvent) + d.AddEvent(FlyingEvent) + d.AddEvent(HoveringEvent) + d.AddEvent(LandingEvent) + d.AddEvent(LandedEvent) + d.AddEvent(EmergencyEvent) + d.AddEvent(RollingEvent) + + return d +} + +// GenerateAllStates sets up all the default states aka settings on the drone +func (d *MinidroneDriver) GenerateAllStates() error { + d.stepsfa0b++ + buf := []byte{ + 0x04, byte(d.stepsfa0b), 0x00, 0x04, 0x01, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2D, 0x31, 0x30, 0x2D, 0x32, 0x38, 0x00, + } + return d.Adaptor().WriteCharacteristic(commandChara, buf) +} + +// TakeOff tells the Minidrone to takeoff +func (d *MinidroneDriver) TakeOff() error { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x00, 0x01, 0x00} + return d.Adaptor().WriteCharacteristic(commandChara, buf) +} + +// Land tells the Minidrone to land +func (d *MinidroneDriver) Land() error { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x00, 0x03, 0x00} + return d.Adaptor().WriteCharacteristic(commandChara, buf) +} + +// FlatTrim calibrates the Minidrone to use its current position as being level +func (d *MinidroneDriver) FlatTrim() error { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x00, 0x00, 0x00} + return d.Adaptor().WriteCharacteristic(commandChara, buf) +} + +// Emergency sets the Minidrone into emergency mode +func (d *MinidroneDriver) Emergency() error { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x00, 0x04, 0x00} + return d.Adaptor().WriteCharacteristic(priorityChara, buf) +} + +// TakePicture tells the Minidrone to take a picture +func (d *MinidroneDriver) TakePicture() error { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x06, 0x01, 0x00} + return d.Adaptor().WriteCharacteristic(commandChara, buf) +} + +// StartPcmd starts the continuous Pcmd communication with the Minidrone +func (d *MinidroneDriver) StartPcmd() { + go func() { + // wait a little bit so that there is enough time to get some ACKs + time.Sleep(500 * time.Millisecond) + for { + err := d.Adaptor().WriteCharacteristic(pcmdChara, d.generatePcmd().Bytes()) + if err != nil { + fmt.Println("pcmd write error:", err) + } + time.Sleep(50 * time.Millisecond) + } + }() +} + +// Up tells the drone to ascend. Pass in an int from 0-100. +func (d *MinidroneDriver) Up(val int) error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd.Flag = 1 + d.Pcmd.Gaz = validatePitch(val) + return nil +} + +// Down tells the drone to descend. Pass in an int from 0-100. +func (d *MinidroneDriver) Down(val int) error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd.Flag = 1 + d.Pcmd.Gaz = validatePitch(val) * -1 + return nil +} + +// Forward tells the drone to go forward. Pass in an int from 0-100. +func (d *MinidroneDriver) Forward(val int) error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd.Flag = 1 + d.Pcmd.Pitch = validatePitch(val) + return nil +} + +// Backward tells drone to go in reverse. Pass in an int from 0-100. +func (d *MinidroneDriver) Backward(val int) error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd.Flag = 1 + d.Pcmd.Pitch = validatePitch(val) * -1 + return nil +} + +// Right tells drone to go right. Pass in an int from 0-100. +func (d *MinidroneDriver) Right(val int) error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd.Flag = 1 + d.Pcmd.Roll = validatePitch(val) + return nil +} + +// Left tells drone to go left. Pass in an int from 0-100. +func (d *MinidroneDriver) Left(val int) error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd.Flag = 1 + d.Pcmd.Roll = validatePitch(val) * -1 + return nil +} + +// Clockwise tells drone to rotate in a clockwise directiod. Pass in an int from 0-100. +func (d *MinidroneDriver) Clockwise(val int) error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd.Flag = 1 + d.Pcmd.Yaw = validatePitch(val) + return nil +} + +// CounterClockwise tells drone to rotate in a counter-clockwise directiod. +// Pass in an int from 0-100. +func (d *MinidroneDriver) CounterClockwise(val int) error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd.Flag = 1 + d.Pcmd.Yaw = validatePitch(val) * -1 + return nil +} + +// Stop tells the drone to stop moving in any direction and simply hover in place +func (d *MinidroneDriver) Stop() error { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + + d.Pcmd = Pcmd{ + Flag: 0, + Roll: 0, + Pitch: 0, + Yaw: 0, + Gaz: 0, + Psi: 0, + } + + return nil +} + +// StartRecording is not supported by the Parrot Minidrone +func (d *MinidroneDriver) StartRecording() error { + return nil +} + +// StopRecording is not supported by the Parrot Minidrone +func (d *MinidroneDriver) StopRecording() error { + return nil +} + +// HullProtection is not supported by the Parrot Minidrone +func (d *MinidroneDriver) HullProtection(protect bool) error { + return nil +} + +// Outdoor mode is not supported by the Parrot Minidrone +func (d *MinidroneDriver) Outdoor(outdoor bool) error { + return nil +} + +// FrontFlip tells the drone to perform a front flip +func (d *MinidroneDriver) FrontFlip() error { + return d.Adaptor().WriteCharacteristic(commandChara, d.generateAnimation(0).Bytes()) +} + +// BackFlip tells the drone to perform a backflip +func (d *MinidroneDriver) BackFlip() error { + return d.Adaptor().WriteCharacteristic(commandChara, d.generateAnimation(1).Bytes()) +} + +// RightFlip tells the drone to perform a flip to the right +func (d *MinidroneDriver) RightFlip() error { + return d.Adaptor().WriteCharacteristic(commandChara, d.generateAnimation(2).Bytes()) +} + +// LeftFlip tells the drone to perform a flip to the left +func (d *MinidroneDriver) LeftFlip() error { + return d.Adaptor().WriteCharacteristic(commandChara, d.generateAnimation(3).Bytes()) +} + +// LightControl controls lights on those Minidrone models which +// have the correct hardware, such as the Maclane, Blaze, & Swat. +// Params: +// +// id - always 0 +// mode - either LightFixed, LightBlinked, or LightOscillated +// intensity - Light intensity from 0 (OFF) to 100 (Max intensity). +// Only used in LightFixed mode. +func (d *MinidroneDriver) LightControl(id uint8, mode uint8, intensity uint8) error { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x10, 0x00, id, mode, intensity, 0x00} + return d.Adaptor().WriteCharacteristic(commandChara, buf) +} + +// ClawControl controls the claw on the Parrot Mambo +// Params: +// +// id - always 0 +// mode - either ClawOpen or ClawClosed +func (d *MinidroneDriver) ClawControl(id uint8, mode uint8) error { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x10, 0x01, id, mode, 0x00} + return d.Adaptor().WriteCharacteristic(commandChara, buf) +} + +// GunControl fires the gun on the Parrot Mambo +// Params: +// +// id - always 0 +func (d *MinidroneDriver) GunControl(id uint8) error { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x10, 0x02, id, 0x00} + return d.Adaptor().WriteCharacteristic(commandChara, buf) +} + +// initialize tells driver to get ready to do work +func (d *MinidroneDriver) initialize() error { + d.Adaptor().WithoutResponses(true) + + if err := d.GenerateAllStates(); err != nil { + return err + } + + // subscribe to battery notifications + if err := d.Adaptor().Subscribe(batteryChara, func(data []byte, e error) { + d.Publish(d.Event(BatteryEvent), data[len(data)-1]) + }); err != nil { + return err + } + + // subscribe to flying status notifications + if err := d.Adaptor().Subscribe(flightStatusChara, func(data []byte, e error) { + d.processFlightStatus(data) + }); err != nil { + return err + } + + if err := d.FlatTrim(); err != nil { + return err + } + + d.StartPcmd() + + return d.FlatTrim() +} + +// shutdown stops minidrone driver (void) +func (d *MinidroneDriver) shutdown() error { + err := d.Land() + time.Sleep(500 * time.Millisecond) + return err +} + +func (d *MinidroneDriver) generateAnimation(direction int8) *bytes.Buffer { + d.stepsfa0b++ + buf := []byte{0x02, byte(d.stepsfa0b) & 0xff, 0x02, 0x04, 0x00, 0x00, byte(direction), 0x00, 0x00, 0x00} + return bytes.NewBuffer(buf) +} + +func (d *MinidroneDriver) generatePcmd() *bytes.Buffer { + d.pcmdMutex.Lock() + defer d.pcmdMutex.Unlock() + d.stepsfa0a++ + pcmd := d.Pcmd + + cmd := &bytes.Buffer{} + if err := binary.Write(cmd, binary.LittleEndian, int8(2)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(d.stepsfa0a)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(2)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(0)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(2)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(0)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Flag)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Roll)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Pitch)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Yaw)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Gaz)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, pcmd.Psi); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int16(0)); err != nil { + panic(err) + } + if err := binary.Write(cmd, binary.LittleEndian, int16(0)); err != nil { + panic(err) + } + + return cmd +} + +func (d *MinidroneDriver) processFlightStatus(data []byte) { + if len(data) < 5 { + // ignore, just a sync + return + } + + d.Publish(FlightStatusEvent, data[4]) + + switch data[4] { + case flatTrimChanged: + d.Publish(FlatTrimChangeEvent, true) + + case flyingStateChanged: + switch data[6] { + case flyingStateLanded: + if d.flying { + d.flying = false + d.Publish(LandedEvent, true) + } + case flyingStateTakeoff: + d.Publish(TakeoffEvent, true) + case flyingStateHovering: + if !d.flying { + d.flying = true + d.Publish(HoveringEvent, true) + } + case flyingStateFlying: + if !d.flying { + d.flying = true + d.Publish(FlyingEvent, true) + } + case flyingStateLanding: + d.Publish(LandingEvent, true) + case flyingStateEmergency: + d.Publish(EmergencyEvent, true) + case flyingStateRolling: + d.Publish(RollingEvent, true) + } + } +} + +// ValidatePitch helps validate pitch values such as those created by +// a joystick to values between 0-100 that are required as +// params to Parrot Minidrone PCMDs +func ValidatePitch(data float64, offset float64) int { + value := math.Abs(data) / offset + if value >= 0.1 { + if value <= 1.0 { + return int((float64(int(value*100)) / 100) * 100) + } + return 100 + } + return 0 +} + +func validatePitch(val int) int { + if val > 100 { + return 100 + } else if val < 0 { + return 0 + } + + return val +} diff --git a/platforms/parrot/minidrone/minidrone_driver_test.go b/drivers/ble/parrot/minidrone_driver_test.go similarity index 78% rename from platforms/parrot/minidrone/minidrone_driver_test.go rename to drivers/ble/parrot/minidrone_driver_test.go index cd6bb4e06..bbae0c67e 100644 --- a/platforms/parrot/minidrone/minidrone_driver_test.go +++ b/drivers/ble/parrot/minidrone_driver_test.go @@ -1,4 +1,4 @@ -package minidrone +package parrot import ( "strings" @@ -8,124 +8,110 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" ) -var _ gobot.Driver = (*Driver)(nil) +var _ gobot.Driver = (*MinidroneDriver)(nil) -func initTestMinidroneDriver() *Driver { - d := NewDriver(NewBleTestAdaptor()) +func initTestMinidroneDriver() *MinidroneDriver { + d := NewMinidroneDriver(testutil.NewBleTestAdaptor()) + if err := d.Start(); err != nil { + panic(err) + } return d } -func TestMinidroneDriver(t *testing.T) { - d := initTestMinidroneDriver() +func TestNewMinidroneDriver(t *testing.T) { + d := NewMinidroneDriver(testutil.NewBleTestAdaptor()) assert.True(t, strings.HasPrefix(d.Name(), "Minidrone")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) + assert.NotNil(t, d.Eventer) } -func TestMinidroneDriverStartAndHalt(t *testing.T) { +func TestMinidroneHalt(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Halt()) } func TestMinidroneTakeoff(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.TakeOff()) } func TestMinidroneEmergency(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Emergency()) } func TestMinidroneTakePicture(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.TakePicture()) } func TestMinidroneUp(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Up(25)) } func TestMinidroneUpTooFar(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Up(125)) require.NoError(t, d.Up(-50)) } func TestMinidroneDown(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Down(25)) } func TestMinidroneForward(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Forward(25)) } func TestMinidroneBackward(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Backward(25)) } func TestMinidroneRight(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Right(25)) } func TestMinidroneLeft(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Left(25)) } func TestMinidroneClockwise(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Clockwise(25)) } func TestMinidroneCounterClockwise(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.CounterClockwise(25)) } func TestMinidroneStop(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.Stop()) } func TestMinidroneStartStopRecording(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.StartRecording()) require.NoError(t, d.StopRecording()) } func TestMinidroneHullProtectionOutdoor(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.HullProtection(true)) require.NoError(t, d.Outdoor(true)) } func TestMinidroneHullFlips(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.FrontFlip()) require.NoError(t, d.BackFlip()) require.NoError(t, d.RightFlip()) @@ -134,25 +120,21 @@ func TestMinidroneHullFlips(t *testing.T) { func TestMinidroneLightControl(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.LightControl(0, LightBlinked, 25)) } func TestMinidroneClawControl(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.ClawControl(0, ClawOpen)) } func TestMinidroneGunControl(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) require.NoError(t, d.GunControl(0)) } func TestMinidroneProcessFlightData(t *testing.T) { d := initTestMinidroneDriver() - require.NoError(t, d.Start()) d.processFlightStatus([]byte{0x00, 0x00, 0x00}) d.processFlightStatus([]byte{0x00, 0x00, 0x00, 0x00, 0x00}) @@ -170,3 +152,15 @@ func TestMinidroneProcessFlightData(t *testing.T) { require.NoError(t, d.Stop()) } + +func TestMinidroneValidatePitchWhenEqualOffset(t *testing.T) { + assert.Equal(t, 100, ValidatePitch(32767.0, 32767.0)) +} + +func TestMinidroneValidatePitchWhenTiny(t *testing.T) { + assert.Equal(t, 0, ValidatePitch(1.1, 32767.0)) +} + +func TestMinidroneValidatePitchWhenCentered(t *testing.T) { + assert.Equal(t, 50, ValidatePitch(16383.5, 32767.0)) +} diff --git a/drivers/ble/serial_port.go b/drivers/ble/serial_port.go new file mode 100644 index 000000000..fbf7addcb --- /dev/null +++ b/drivers/ble/serial_port.go @@ -0,0 +1,84 @@ +package ble + +import ( + "sync" + + "gobot.io/x/gobot/v2" +) + +// SerialPortDriver is a implementation of serial over Bluetooth LE +// Inspired by https://github.com/monteslu/ble-serial by @monteslu +type SerialPortDriver struct { + *Driver + rid string + tid string + // buffer of responseData and mutex to protect it + responseData []byte + responseMutex sync.Mutex +} + +// NewSerialPortDriver returns a new serial over Bluetooth LE connection +func NewSerialPortDriver(a gobot.BLEConnector, rid string, tid string) *SerialPortDriver { + d := &SerialPortDriver{ + Driver: NewDriver(a, "BleSerial", nil, nil), + rid: rid, + tid: tid, + } + + return d +} + +// Open opens a connection to a BLE serial device +func (p *SerialPortDriver) Open() error { + if err := p.Adaptor().Connect(); err != nil { + return err + } + + // subscribe to response notifications + return p.Adaptor().Subscribe(p.rid, func(data []byte, e error) { + p.responseMutex.Lock() + defer p.responseMutex.Unlock() + p.responseData = append(p.responseData, data...) + }) +} + +// Read reads bytes from BLE serial port connection +func (p *SerialPortDriver) Read(b []byte) (int, error) { + p.responseMutex.Lock() + defer p.responseMutex.Unlock() + + if len(p.responseData) == 0 { + return 0, nil + } + + n := len(b) + if len(p.responseData) < n { + n = len(p.responseData) + } + copy(b, p.responseData[:n]) + + if len(p.responseData) > n { + p.responseData = p.responseData[n:] + } else { + p.responseData = nil + } + + return n, nil +} + +// Write writes to the BLE serial port connection +func (p *SerialPortDriver) Write(b []byte) (int, error) { + err := p.Adaptor().WriteCharacteristic(p.tid, b) + n := len(b) + return n, err +} + +// Close closes the BLE serial port connection +func (p *SerialPortDriver) Close() error { + return p.Adaptor().Disconnect() +} + +// Address returns the BLE address +func (p *SerialPortDriver) Address() string { + return p.Adaptor().Address() +} diff --git a/drivers/ble/serial_port_test.go b/drivers/ble/serial_port_test.go new file mode 100644 index 000000000..1d045f3b1 --- /dev/null +++ b/drivers/ble/serial_port_test.go @@ -0,0 +1,20 @@ +package ble + +import ( + "io" + "testing" + + "github.com/stretchr/testify/assert" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" +) + +var _ gobot.Driver = (*SerialPortDriver)(nil) + +var _ io.ReadWriteCloser = (*SerialPortDriver)(nil) + +func TestBLESerialPort(t *testing.T) { + d := NewSerialPortDriver(testutil.NewBleTestAdaptor(), "123", "456") + assert.Equal(t, "01:02:03:0A:0B:0C", d.Address()) +} diff --git a/platforms/sphero/LICENSE b/drivers/ble/sphero/LICENSE similarity index 100% rename from platforms/sphero/LICENSE rename to drivers/ble/sphero/LICENSE diff --git a/drivers/ble/sphero/doc.go b/drivers/ble/sphero/doc.go new file mode 100644 index 000000000..eac84dd14 --- /dev/null +++ b/drivers/ble/sphero/doc.go @@ -0,0 +1,9 @@ +/* +Package sphero provides the Gobot drivers for the Sphero BLE based platforms. + +For further information refer to sphero readme files: +https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/bb8/README.md +https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/ollie/README.md +https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/sprkplus/README.md +*/ +package sphero // import "gobot.io/x/gobot/v2/drivers/ble/sphero" diff --git a/drivers/ble/sphero/sphero_bb8_driver.go b/drivers/ble/sphero/sphero_bb8_driver.go new file mode 100644 index 000000000..e1a459cbc --- /dev/null +++ b/drivers/ble/sphero/sphero_bb8_driver.go @@ -0,0 +1,28 @@ +package sphero + +import ( + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/common/sphero" +) + +// BB8Driver represents a Sphero BB-8 +type BB8Driver struct { + *OllieDriver +} + +// NewBB8Driver creates a driver for a Sphero BB-8 +func NewBB8Driver(a gobot.BLEConnector) *BB8Driver { + return &BB8Driver{OllieDriver: newOllieBaseDriver(a, "BB8", bb8DefaultCollisionConfig())} +} + +// bb8DefaultCollisionConfig returns a CollisionConfig with sensible collision defaults +func bb8DefaultCollisionConfig() sphero.CollisionConfig { + return sphero.CollisionConfig{ + Method: 0x01, + Xt: 0x20, + Yt: 0x20, + Xs: 0x20, + Ys: 0x20, + Dead: 0x01, + } +} diff --git a/drivers/ble/sphero/sphero_bb8_driver_test.go b/drivers/ble/sphero/sphero_bb8_driver_test.go new file mode 100644 index 000000000..962239cc0 --- /dev/null +++ b/drivers/ble/sphero/sphero_bb8_driver_test.go @@ -0,0 +1,21 @@ +package sphero + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" +) + +var _ gobot.Driver = (*BB8Driver)(nil) + +func TestNewBB8Driver(t *testing.T) { + d := NewBB8Driver(testutil.NewBleTestAdaptor()) + assert.NotNil(t, d.OllieDriver) + assert.True(t, strings.HasPrefix(d.Name(), "BB8")) + assert.NotNil(t, d.OllieDriver) + assert.Equal(t, d.defaultCollisionConfig, bb8DefaultCollisionConfig()) +} diff --git a/drivers/ble/sphero/sphero_ollie_driver.go b/drivers/ble/sphero/sphero_ollie_driver.go new file mode 100644 index 000000000..fffc4a008 --- /dev/null +++ b/drivers/ble/sphero/sphero_ollie_driver.go @@ -0,0 +1,446 @@ +package sphero + +import ( + "bytes" + "encoding/binary" + "fmt" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/drivers/common/sphero" +) + +// MotorModes is used to configure the motor +type MotorModes uint8 + +// MotorModes required for SetRawMotorValues command +const ( + Off MotorModes = iota + Forward + Reverse + Brake + Ignore +) + +const ( + // spheroBLEService = "22bb746f2bb075542d6f726568705327" + // robotControlService = "22bb746f2ba075542d6f726568705327" + + wakeChara = "22bb746f2bbf75542d6f726568705327" + txPowerChara = "22bb746f2bb275542d6f726568705327" + antiDosChara = "22bb746f2bbd75542d6f726568705327" + commandsChara = "22bb746f2ba175542d6f726568705327" + responseChara = "22bb746f2ba675542d6f726568705327" + + // packet header size + packetHeaderSize = 5 + + // Response packet max size + responsePacketMaxSize = 20 + + // Collision packet data size: The number of bytes following the DLEN field through the end of the packet + collisionDataSize = 17 + + // Full size of the collision response + collisionResponseSize = packetHeaderSize + collisionDataSize +) + +// packet describes head, body and checksum for a data package to be sent +type packet struct { + header []uint8 + body []uint8 + checksum uint8 +} + +// Point2D represents a coordinate in 2-Dimensional space, exposed because used in a callback +type Point2D struct { + X int16 + Y int16 +} + +// OllieDriver is the Gobot driver for the Sphero Ollie robot +type OllieDriver struct { + *ble.Driver + gobot.Eventer + defaultCollisionConfig sphero.CollisionConfig + seq uint8 + collisionResponse []uint8 + packetChannel chan *packet + asyncBuffer []byte + asyncMessage []byte + locatorCallback func(p Point2D) + powerstateCallback func(p sphero.PowerStatePacket) +} + +// NewOllieDriver creates a driver for a Sphero Ollie +func NewOllieDriver(a gobot.BLEConnector) *OllieDriver { + return newOllieBaseDriver(a, "Ollie", ollieDefaultCollisionConfig()) +} + +func newOllieBaseDriver(a gobot.BLEConnector, name string, dcc sphero.CollisionConfig) *OllieDriver { + d := &OllieDriver{ + defaultCollisionConfig: dcc, + Eventer: gobot.NewEventer(), + packetChannel: make(chan *packet, 1024), + } + d.Driver = ble.NewDriver(a, name, d.initialize, d.shutdown) + + d.AddEvent(sphero.ErrorEvent) + d.AddEvent(sphero.CollisionEvent) + + return d +} + +// SetTXPower sets transmit level +func (d *OllieDriver) SetTXPower(level int) error { + buf := []byte{byte(level)} + + if err := d.Adaptor().WriteCharacteristic(txPowerChara, buf); err != nil { + return err + } + + return nil +} + +// Wake wakes Ollie up so we can play +func (d *OllieDriver) Wake() error { + buf := []byte{0x01} + + if err := d.Adaptor().WriteCharacteristic(wakeChara, buf); err != nil { + return err + } + + return nil +} + +// ConfigureCollisionDetection configures the sensitivity of the detection. +func (d *OllieDriver) ConfigureCollisionDetection(cc sphero.CollisionConfig) { + d.sendCraftPacket([]uint8{cc.Method, cc.Xt, cc.Yt, cc.Xs, cc.Ys, cc.Dead}, 0x02, 0x12) +} + +// GetLocatorData calls the passed function with the data from the locator +func (d *OllieDriver) GetLocatorData(f func(p Point2D)) { + // CID 0x15 is the code for the locator request + d.sendCraftPacket([]uint8{}, 0x02, 0x15) + d.locatorCallback = f +} + +// GetPowerState calls the passed function with the Power State information from the sphero +func (d *OllieDriver) GetPowerState(f func(p sphero.PowerStatePacket)) { + // CID 0x20 is the code for the power state + d.sendCraftPacket([]uint8{}, 0x00, 0x20) + d.powerstateCallback = f +} + +// SetRGB sets the Ollie to the given r, g, and b values +func (d *OllieDriver) SetRGB(r uint8, g uint8, b uint8) { + d.sendCraftPacket([]uint8{r, g, b, 0x01}, 0x02, 0x20) +} + +// Roll tells the Ollie to roll +func (d *OllieDriver) Roll(speed uint8, heading uint16) { + d.sendCraftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x02, 0x30) +} + +// Boost executes the boost macro from within the SSB which takes a 1 byte parameter which is +// either 01h to begin boosting or 00h to stop. +func (d *OllieDriver) Boost(state bool) { + s := uint8(0x01) + if !state { + s = 0x00 + } + d.sendCraftPacket([]uint8{s}, 0x02, 0x31) +} + +// SetStabilization enables or disables the built-in auto stabilizing features of the Ollie +func (d *OllieDriver) SetStabilization(state bool) { + s := uint8(0x01) + if !state { + s = 0x00 + } + d.sendCraftPacket([]uint8{s}, 0x02, 0x02) +} + +// SetRotationRate allows you to control the rotation rate that Sphero will use to meet new heading commands. A value +// of 255 jumps to the maximum (currently 400 degrees/sec). A value of zero doesn't make much sense so it's interpreted +// as 1, the minimum. +func (d *OllieDriver) SetRotationRate(speed uint8) { + d.sendCraftPacket([]uint8{speed}, 0x02, 0x03) +} + +// SetRawMotorValues allows you to take over one or both of the motor output values, instead of having the stabilization +// system control them. Each motor (left and right) requires a mode and a power value from 0-255. +func (d *OllieDriver) SetRawMotorValues(lmode MotorModes, lpower uint8, rmode MotorModes, rpower uint8) { + d.sendCraftPacket([]uint8{uint8(lmode), lpower, uint8(rmode), rpower}, 0x02, 0x33) +} + +// SetBackLEDBrightness allows you to control the brightness of the back(tail) LED. +func (d *OllieDriver) SetBackLEDBrightness(value uint8) { + d.sendCraftPacket([]uint8{value}, 0x02, 0x21) +} + +// Stop tells the Ollie to stop +func (d *OllieDriver) Stop() { + d.Roll(0, 0) +} + +// Sleep says Go to sleep +func (d *OllieDriver) Sleep() { + d.sendCraftPacket([]uint8{0x00, 0x00, 0x00, 0x00, 0x00}, 0x00, 0x22) +} + +// SetDataStreamingConfig passes the config to the sphero to stream sensor data +func (d *OllieDriver) SetDataStreamingConfig(dsc sphero.DataStreamingConfig) error { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, dsc); err != nil { + return err + } + d.sendCraftPacket(buf.Bytes(), 0x02, 0x11) + return nil +} + +// initialize tells driver to get ready to do work +func (d *OllieDriver) initialize() error { + if err := d.antiDOSOff(); err != nil { + return err + } + if err := d.SetTXPower(7); err != nil { + return err + } + if err := d.Wake(); err != nil { + return err + } + + // subscribe to Sphero response notifications + if err := d.Adaptor().Subscribe(responseChara, d.handleResponses); err != nil { + return err + } + + go func() { + for { + packet := <-d.packetChannel + err := d.writeCommand(packet) + if err != nil { + d.Publish(d.Event(sphero.ErrorEvent), err) + } + } + }() + + go func() { + for { + if _, err := d.Adaptor().ReadCharacteristic(responseChara); err != nil { + panic(err) + } + time.Sleep(100 * time.Millisecond) + } + }() + + d.ConfigureCollisionDetection(d.defaultCollisionConfig) + d.enableStopOnDisconnect() + + return nil +} + +// antiDOSOff turns off Anti-DOS code so we can control Ollie +func (d *OllieDriver) antiDOSOff() error { + str := "011i3" + buf := &bytes.Buffer{} + buf.WriteString(str) + + if err := d.Adaptor().WriteCharacteristic(antiDosChara, buf.Bytes()); err != nil { + return err + } + + return nil +} + +func (d *OllieDriver) writeCommand(packet *packet) error { + d.Mutex().Lock() + defer d.Mutex().Unlock() + + buf := append(packet.header, packet.body...) + buf = append(buf, packet.checksum) + if err := d.Adaptor().WriteCharacteristic(commandsChara, buf); err != nil { + fmt.Println("async send command error:", err) + return err + } + + d.seq++ + return nil +} + +// enableStopOnDisconnect auto-sends a Stop command after losing the connection +func (d *OllieDriver) enableStopOnDisconnect() { + d.sendCraftPacket([]uint8{0x00, 0x00, 0x00, 0x01}, 0x02, 0x37) +} + +// shutdown stops Ollie driver (void) +func (d *OllieDriver) shutdown() error { + d.Sleep() + time.Sleep(750 * time.Microsecond) + return nil +} + +// handleResponses handles responses returned from Ollie +func (d *OllieDriver) handleResponses(data []byte, e error) { + // since packets can only be 20 bytes long, we have to puzzle them together + newMessage := false + + // append message parts to existing + if len(data) > 0 && data[0] != 0xFF { + d.asyncBuffer = append(d.asyncBuffer, data...) + } + + // clear message when new one begins (first byte is always 0xFF) + if len(data) > 0 && data[0] == 0xFF { + d.asyncMessage = d.asyncBuffer + d.asyncBuffer = data + newMessage = true + } + + parts := d.asyncMessage + // 3 is the id of data streaming, located at index 2 byte + if newMessage && len(parts) > 2 && parts[2] == 3 { + d.handleDataStreaming(parts) + } + + // index 1 is the type of the message, 0xFF being a direct response, 0xFE an asynchronous message + if len(data) > 4 && data[1] == 0xFF && data[0] == 0xFF { + // locator request + if data[4] == 0x0B && len(data) == 16 { + d.handleLocatorDetected(data) + } + + if data[4] == 0x09 { + d.handlePowerStateDetected(data) + } + } + + d.handleCollisionDetected(data) +} + +func (d *OllieDriver) handleDataStreaming(data []byte) { + // ensure data is the right length: + if len(data) != 88 { + return + } + + // data packet is the same as for the normal sphero, since the same communication api is used + // only difference in communication is that the "newer" spheros use BLE for communications + var dataPacket sphero.DataStreamingPacket + buffer := bytes.NewBuffer(data[5:]) // skip header + if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { + panic(err) + } + + d.Publish(sphero.SensorDataEvent, dataPacket) +} + +func (d *OllieDriver) handleLocatorDetected(data []uint8) { + if d.locatorCallback == nil { + return + } + + // read the unsigned raw values + ux := binary.BigEndian.Uint16(data[5:7]) + uy := binary.BigEndian.Uint16(data[7:9]) + + // convert to signed values + var x, y int16 + + if ux > 32255 { + x = int16(ux - 65535) + } else { + x = int16(ux) + } + + if uy > 32255 { + y = int16(uy - 65535) + } else { + y = int16(uy) + } + + d.locatorCallback(Point2D{X: x, Y: y}) +} + +func (d *OllieDriver) handlePowerStateDetected(data []uint8) { + var dataPacket sphero.PowerStatePacket + buffer := bytes.NewBuffer(data[5:]) // skip header + if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { + panic(err) + } + + d.powerstateCallback(dataPacket) +} + +func (d *OllieDriver) handleCollisionDetected(data []uint8) { + switch len(data) { + case responsePacketMaxSize: + // Check if this is the header of collision response. (i.e. first part of data) + // Collision response is 22 bytes long. (individual packet size is maxed at 20) + if data[1] == 0xFE && data[2] == 0x07 && len(d.collisionResponse) == 0 { + // response code 7 is for a detected collision + d.collisionResponse = append(d.collisionResponse, data...) + } + case collisionResponseSize - responsePacketMaxSize: + // if this is the remaining part of the collision response, + // then make sure the header and first part of data is already received + if len(d.collisionResponse) == responsePacketMaxSize { + d.collisionResponse = append(d.collisionResponse, data...) + } + default: + return // not collision event + } + + // check expected sizes + if len(d.collisionResponse) != collisionResponseSize || d.collisionResponse[4] != collisionDataSize { + return + } + + // confirm checksum + size := len(d.collisionResponse) + chk := d.collisionResponse[size-1] // last byte is checksum + if chk != sphero.CalculateChecksum(d.collisionResponse[2:size-1]) { + return + } + + var collision sphero.CollisionPacket + buffer := bytes.NewBuffer(d.collisionResponse[5:]) // skip header + if err := binary.Read(buffer, binary.BigEndian, &collision); err != nil { + panic(err) + } + d.collisionResponse = nil // clear the current response + + d.Publish(sphero.CollisionEvent, collision) +} + +func (d *OllieDriver) sendCraftPacket(body []uint8, did byte, cid byte) { + d.packetChannel <- d.craftPacket(body, did, cid) +} + +func (d *OllieDriver) craftPacket(body []uint8, did byte, cid byte) *packet { + dlen := len(body) + 1 + hdr := []uint8{0xFF, 0xFF, did, cid, d.seq, uint8(dlen)} + buf := append(hdr, body...) + + packet := &packet{ + body: body, + header: hdr, + checksum: sphero.CalculateChecksum(buf[2:]), + } + + return packet +} + +// ollieDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults +func ollieDefaultCollisionConfig() sphero.CollisionConfig { + return sphero.CollisionConfig{ + Method: 0x01, + Xt: 0x20, + Yt: 0x20, + Xs: 0x20, + Ys: 0x20, + Dead: 0x60, + } +} diff --git a/platforms/sphero/ollie/ollie_driver_test.go b/drivers/ble/sphero/sphero_ollie_driver_test.go similarity index 63% rename from platforms/sphero/ollie/ollie_driver_test.go rename to drivers/ble/sphero/sphero_ollie_driver_test.go index b736c0d82..d4758c970 100644 --- a/platforms/sphero/ollie/ollie_driver_test.go +++ b/drivers/ble/sphero/sphero_ollie_driver_test.go @@ -1,8 +1,7 @@ //nolint:forcetypeassert // ok here -package ollie +package sphero import ( - "fmt" "strconv" "testing" "time" @@ -11,23 +10,26 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/ble/testutil" + "gobot.io/x/gobot/v2/drivers/common/sphero" ) -var _ gobot.Driver = (*Driver)(nil) +var _ gobot.Driver = (*OllieDriver)(nil) -func initTestOllieDriver() *Driver { - d := NewDriver(NewBleTestAdaptor()) +func initTestOllieDriver() *OllieDriver { + d := NewOllieDriver(testutil.NewBleTestAdaptor()) return d } -func TestOllieDriver(t *testing.T) { - d := initTestOllieDriver() - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) +func TestNewOllieDriver(t *testing.T) { + d := NewOllieDriver(testutil.NewBleTestAdaptor()) + assert.NotNil(t, d.Driver) + assert.NotNil(t, d.Eventer) + assert.Equal(t, d.defaultCollisionConfig, ollieDefaultCollisionConfig()) + assert.NotNil(t, d.packetChannel) } -func TestOllieDriverStartAndHalt(t *testing.T) { +func TestOllieStartAndHalt(t *testing.T) { d := initTestOllieDriver() require.NoError(t, d.Start()) require.NoError(t, d.Halt()) @@ -60,22 +62,24 @@ func TestLocatorData(t *testing.T) { d.GetLocatorData(func(p Point2D) { assert.Equal(t, point.y, p.Y) }) - d.HandleResponses(packet, nil) + d.handleResponses(packet, nil) } } func TestDataStreaming(t *testing.T) { d := initTestOllieDriver() - _ = d.SetDataStreamingConfig(sphero.DefaultDataStreamingConfig()) + err := d.SetDataStreamingConfig(sphero.DefaultDataStreamingConfig()) + require.NoError(t, err) responseChan := make(chan bool) - _ = d.On("sensordata", func(data interface{}) { - cont := data.(DataStreamingPacket) - fmt.Printf("got streaming packet: %+v \n", cont) + err = d.On("sensordata", func(data interface{}) { + cont := data.(sphero.DataStreamingPacket) + // fmt.Printf("got streaming packet: %+v \n", cont) assert.Equal(t, int16(10), cont.RawAccX) responseChan <- true }) + require.NoError(t, err) // example data packet p1 := []string{ @@ -90,16 +94,17 @@ func TestDataStreaming(t *testing.T) { var bytes []byte for i := 0; i < len([]rune(elem)); i += 2 { a := []rune(elem)[i : i+2] - b, _ := strconv.ParseUint(string(a), 16, 16) + b, err := strconv.ParseUint(string(a), 16, 16) + require.NoError(t, err) + c := uint16(b) bytes = append(bytes, byte(c)) } - d.HandleResponses(bytes, nil) - + d.handleResponses(bytes, nil) } // send empty packet to indicate start of next message - d.HandleResponses([]byte{0xFF}, nil) + d.handleResponses([]byte{0xFF}, nil) select { case <-responseChan: case <-time.After(10 * time.Millisecond): diff --git a/drivers/ble/sphero/sphero_sprkplus_driver.go b/drivers/ble/sphero/sphero_sprkplus_driver.go new file mode 100644 index 000000000..744d571c9 --- /dev/null +++ b/drivers/ble/sphero/sphero_sprkplus_driver.go @@ -0,0 +1,28 @@ +package sphero + +import ( + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/common/sphero" +) + +// SPRKPlusDriver represents a Sphero SPRK+ +type SPRKPlusDriver struct { + *OllieDriver +} + +// NewSPRKPlusDriver creates a driver for a Sphero SPRK+ +func NewSPRKPlusDriver(a gobot.BLEConnector) *SPRKPlusDriver { + return &SPRKPlusDriver{OllieDriver: newOllieBaseDriver(a, "SPRKPlus", sprkplusDefaultCollisionConfig())} +} + +// sprkplusDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults +func sprkplusDefaultCollisionConfig() sphero.CollisionConfig { + return sphero.CollisionConfig{ + Method: 0x01, + Xt: 0x20, + Yt: 0x20, + Xs: 0x20, + Ys: 0x20, + Dead: 0x01, + } +} diff --git a/drivers/ble/sphero/sphero_sprkplus_driver_test.go b/drivers/ble/sphero/sphero_sprkplus_driver_test.go new file mode 100644 index 000000000..382c08ed0 --- /dev/null +++ b/drivers/ble/sphero/sphero_sprkplus_driver_test.go @@ -0,0 +1,21 @@ +package sphero + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/testutil" +) + +var _ gobot.Driver = (*SPRKPlusDriver)(nil) + +func TestNewSPRKPlusDriver(t *testing.T) { + d := NewSPRKPlusDriver(testutil.NewBleTestAdaptor()) + assert.NotNil(t, d.OllieDriver) + assert.True(t, strings.HasPrefix(d.Name(), "SPRK")) + assert.NotNil(t, d.OllieDriver) + assert.Equal(t, d.defaultCollisionConfig, sprkplusDefaultCollisionConfig()) +} diff --git a/platforms/microbit/helpers_test.go b/drivers/ble/testutil/testutil.go similarity index 58% rename from platforms/microbit/helpers_test.go rename to drivers/ble/testutil/testutil.go index acf446f2d..4724e5689 100644 --- a/platforms/microbit/helpers_test.go +++ b/drivers/ble/testutil/testutil.go @@ -1,12 +1,12 @@ -package microbit +package testutil import ( "sync" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2" ) -var _ ble.BLEConnector = (*bleTestClientAdaptor)(nil) +var _ gobot.BLEConnector = (*bleTestClientAdaptor)(nil) type bleTestClientAdaptor struct { name string @@ -14,64 +14,63 @@ type bleTestClientAdaptor struct { mtx sync.Mutex withoutResponses bool - testSubscribe func([]byte, error) - testReadCharacteristic func(string) ([]byte, error) - testWriteCharacteristic func(string, []byte) error + readCharacteristicFunc func(string) ([]byte, error) + writeCharacteristicFunc func(string, []byte) error + subscribeFunc func([]byte, error) } -func (t *bleTestClientAdaptor) Connect() error { return nil } -func (t *bleTestClientAdaptor) Reconnect() error { return nil } -func (t *bleTestClientAdaptor) Disconnect() error { return nil } -func (t *bleTestClientAdaptor) Finalize() error { return nil } -func (t *bleTestClientAdaptor) Name() string { return t.name } -func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } -func (t *bleTestClientAdaptor) Address() string { return t.address } -func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } +func NewBleTestAdaptor() *bleTestClientAdaptor { + return &bleTestClientAdaptor{ + address: "01:02:03:0A:0B:0C", + readCharacteristicFunc: func(cUUID string) ([]byte, error) { + return []byte(cUUID), nil + }, + writeCharacteristicFunc: func(cUUID string, data []byte) error { + return nil + }, + } +} -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { +func (t *bleTestClientAdaptor) SetReadCharacteristicTestFunc(f func(cUUID string) (data []byte, err error)) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testReadCharacteristic(cUUID) + t.readCharacteristicFunc = f } -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { +func (t *bleTestClientAdaptor) SetWriteCharacteristicTestFunc(f func(cUUID string, data []byte) error) { t.mtx.Lock() defer t.mtx.Unlock() - return t.testWriteCharacteristic(cUUID, data) -} - -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { - t.testSubscribe = f - return nil + t.writeCharacteristicFunc = f } -func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { +func (t *bleTestClientAdaptor) SendTestDataToSubscriber(data []byte, err error) { t.mtx.Lock() defer t.mtx.Unlock() - t.testReadCharacteristic = f + t.subscribeFunc(data, err) } -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { +func (t *bleTestClientAdaptor) Connect() error { return nil } +func (t *bleTestClientAdaptor) Reconnect() error { return nil } +func (t *bleTestClientAdaptor) Disconnect() error { return nil } +func (t *bleTestClientAdaptor) Finalize() error { return nil } +func (t *bleTestClientAdaptor) Name() string { return t.name } +func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } +func (t *bleTestClientAdaptor) Address() string { return t.address } +func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } + +func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { t.mtx.Lock() defer t.mtx.Unlock() - t.testWriteCharacteristic = f + return t.readCharacteristicFunc(cUUID) } -func (t *bleTestClientAdaptor) TestReceiveNotification(data []byte, err error) { +func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { t.mtx.Lock() defer t.mtx.Unlock() - t.testSubscribe(data, err) + return t.writeCharacteristicFunc(cUUID, data) } -func NewBleTestAdaptor() *bleTestClientAdaptor { - return &bleTestClientAdaptor{ - address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) ([]byte, error) { - return nil, nil - }, - testWriteCharacteristic: func(cUUID string, data []byte) error { - return nil - }, - testSubscribe: func([]byte, error) {}, - } +func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { + t.subscribeFunc = f + return nil } diff --git a/drivers/common/bit/bit.go b/drivers/common/bit/bit.go new file mode 100644 index 000000000..fbfda283c --- /dev/null +++ b/drivers/common/bit/bit.go @@ -0,0 +1,20 @@ +package bit + +// Set is used to set a bit in the given integer at a given position to 1. +func Set(n int, pos uint8) int { + n |= (1 << pos) + return n +} + +// Clear is used to set a bit in the given integer at a given position to 0. +func Clear(n int, pos uint8) int { + mask := ^int(1 << pos) + n &= mask + return n +} + +// IsSet tests if the bit at the given position is set in the given integer. +func IsSet(n int, pos uint8) bool { + val := n & (1 << uint(pos)) + return (val > 0) +} diff --git a/drivers/common/bit/bit_test.go b/drivers/common/bit/bit_test.go new file mode 100644 index 000000000..cd5a39961 --- /dev/null +++ b/drivers/common/bit/bit_test.go @@ -0,0 +1,34 @@ +package bit + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSet(t *testing.T) { + const ( + oldVal = 1 + bitPos = 7 + want = 129 + ) + require.False(t, IsSet(oldVal, bitPos)) + + got := Set(1, 7) + assert.Equal(t, want, got) + assert.True(t, IsSet(got, bitPos)) +} + +func TestClear(t *testing.T) { + const ( + oldVal = 128 + bitPos = 7 + want int = 0 + ) + require.True(t, IsSet(oldVal, bitPos)) + + got := Clear(128, 7) + assert.Equal(t, want, got) + assert.False(t, IsSet(got, bitPos)) +} diff --git a/drivers/common/sphero/sphero_driver.go b/drivers/common/sphero/sphero_driver.go new file mode 100644 index 000000000..d8391a150 --- /dev/null +++ b/drivers/common/sphero/sphero_driver.go @@ -0,0 +1,33 @@ +package sphero + +const ( + // ErrorEvent event when error encountered + ErrorEvent = "error" + + // SensorDataEvent event when sensor data is received + SensorDataEvent = "sensordata" + + // CollisionEvent event when collision is detected + CollisionEvent = "collision" +) + +// DefaultDataStreamingConfig returns a config with a sampling rate of 40hz, 1 sample frame per package, +// unlimited streaming, and will stream all available sensor information +func DefaultDataStreamingConfig() DataStreamingConfig { + return DataStreamingConfig{ + N: 10, + M: 1, + Mask: 4294967295, + Pcnt: 0, + Mask2: 4294967295, + } +} + +// CalculateChecksum calculates the checksum for Sphero packets +func CalculateChecksum(buf []byte) byte { + var calculatedChecksum uint16 + for i := range buf { + calculatedChecksum += uint16(buf[i]) + } + return uint8(^(calculatedChecksum % 256)) +} diff --git a/drivers/common/sphero/sphero_driver_test.go b/drivers/common/sphero/sphero_driver_test.go new file mode 100644 index 000000000..03759d7ff --- /dev/null +++ b/drivers/common/sphero/sphero_driver_test.go @@ -0,0 +1,20 @@ +package sphero + +import "testing" + +func TestCalculateChecksum(t *testing.T) { + tests := []struct { + data []byte + checksum byte + }{ + {[]byte{0x00}, 0xff}, + {[]byte{0xf0, 0x0f}, 0x00}, + } + + for _, tt := range tests { + actual := CalculateChecksum(tt.data) + if actual != tt.checksum { + t.Errorf("Expected %x, got %x for data %x.", tt.checksum, actual, tt.data) + } + } +} diff --git a/platforms/sphero/sphero_packets.go b/drivers/common/sphero/sphero_packets.go similarity index 87% rename from platforms/sphero/sphero_packets.go rename to drivers/common/sphero/sphero_packets.go index 33b17c9e8..0f6333f85 100644 --- a/platforms/sphero/sphero_packets.go +++ b/drivers/common/sphero/sphero_packets.go @@ -1,15 +1,5 @@ package sphero -// DefaultLocatorConfig returns a LocatorConfig with defaults -func DefaultLocatorConfig() LocatorConfig { - return LocatorConfig{ - Flags: 0x01, - X: 0x00, - Y: 0x00, - YawTare: 0x00, - } -} - // LocatorConfig provides configuration for the Location api. // https://github.com/orbotix/DeveloperResources/blob/master/docs/Sphero_API_1.50.pdf // The current (X,Y) coordinates of Sphero on the ground plane in centimeters. @@ -24,18 +14,6 @@ type LocatorConfig struct { YawTare int16 } -// DefaultCollisionConfig returns a CollisionConfig with sensible collision defaults -func DefaultCollisionConfig() CollisionConfig { - return CollisionConfig{ - Method: 0x01, - Xt: 0x80, - Yt: 0x80, - Xs: 0x80, - Ys: 0x80, - Dead: 0x60, - } -} - // CollisionConfig provides configuration for the collision detection alogorithm. // For more information refer to the official api specification // https://github.com/orbotix/DeveloperResources/blob/master/docs/Collision%20detection%201.2.pdf. @@ -60,32 +38,6 @@ type CollisionConfig struct { Dead uint8 } -// CollisionPacket represents the response from a Collision event -type CollisionPacket struct { - // Normalized impact components (direction of the collision event): - X, Y, Z int16 - // Thresholds exceeded by X (1h) and/or Y (2h) axis (bitmask): - Axis byte - // Power that cross threshold Xt + Xs: - XMagnitude, YMagnitude int16 - // Sphero's speed when impact detected: - Speed uint8 - // Millisecond timer - Timestamp uint32 -} - -// DefaultDataStreamingConfig returns a DataStreamingConfig with a sampling rate of 40hz, 1 sample frame per package, -// unlimited streaming, and will stream all available sensor information -func DefaultDataStreamingConfig() DataStreamingConfig { - return DataStreamingConfig{ - N: 10, - M: 1, - Mask: 4294967295, - Pcnt: 0, - Mask2: 4294967295, - } -} - // DataStreamingConfig provides configuration for Sensor Data Streaming. // For more information refer to the official api specification // https://github.com/orbotix/DeveloperResources/blob/master/docs/Sphero_API_1.50.pdf page 28 @@ -102,6 +54,34 @@ type DataStreamingConfig struct { Mask2 uint32 } +// PowerStatePacket contains all data relevant to the power state of the sphero +type PowerStatePacket struct { + // record Version Code + RecVer uint8 + // High-Level State of the Battery; 1=charging, 2=battery ok, 3=battery low, 4=battery critical + PowerState uint8 + // Battery Voltage, scaled in 100th of a Volt, 0x02EF would be 7.51 volts + BattVoltage uint16 + // Number of charges in the total lifetime of the sphero + NumCharges uint16 + // Seconds awake since last charge + TimeSinceChg uint16 +} + +// CollisionPacket represents the response from a Collision event +type CollisionPacket struct { + // Normalized impact components (direction of the collision event): + X, Y, Z int16 + // Thresholds exceeded by X (1h) and/or Y (2h) axis (bitmask): + Axis byte + // Power that cross threshold Xt + Xs: + XMagnitude, YMagnitude int16 + // Sphero's speed when impact detected: + Speed uint8 + // Millisecond timer + Timestamp uint32 +} + // DataStreamingPacket represents the response from a Data Streaming event type DataStreamingPacket struct { // 8000 0000h accelerometer axis X, raw -2048 to 2047 4mG diff --git a/drivers/i2c/i2c_connection.go b/drivers/i2c/i2c_connection.go index 3f402a8d3..e1c08a36d 100644 --- a/drivers/i2c/i2c_connection.go +++ b/drivers/i2c/i2c_connection.go @@ -110,19 +110,6 @@ func (c *i2cConnection) WriteBytes(b []byte) error { return c.bus.WriteBytes(c.address, b) } -// setBit is used to set a bit at a given position to 1. -func setBit(n uint8, pos uint8) uint8 { - n |= (1 << pos) - return n -} - -// clearBit is used to set a bit at a given position to 0. -func clearBit(n uint8, pos uint8) uint8 { - mask := ^uint8(1 << pos) - n &= mask - return n -} - func twosComplement16Bit(uValue uint16) int16 { result := int32(uValue) if result&0x8000 != 0 { diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index fdce313d2..248d90f48 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -190,15 +190,3 @@ func TestI2CWriteBlockDataAddressError(t *testing.T) { err := c.WriteBlockData(0x01, []byte{0x01, 0x02}) require.ErrorContains(t, err, "Setting address failed with syscall.Errno operation not permitted") } - -func Test_setBit(t *testing.T) { - var wantVal uint8 = 129 - gotVal := setBit(1, 7) - assert.Equal(t, wantVal, gotVal) -} - -func Test_clearBit(t *testing.T) { - var wantVal uint8 - gotVal := clearBit(128, 7) - assert.Equal(t, wantVal, gotVal) -} diff --git a/drivers/i2c/mcp23017_driver.go b/drivers/i2c/mcp23017_driver.go index d54abee76..def7fe527 100644 --- a/drivers/i2c/mcp23017_driver.go +++ b/drivers/i2c/mcp23017_driver.go @@ -6,6 +6,7 @@ import ( "strings" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/common/bit" ) // default address for device when a2/a1/a0 pins are all tied to ground @@ -323,9 +324,9 @@ func (m *MCP23017Driver) write(reg uint8, pin uint8, state bitState) error { var val uint8 if state == clear { - val = clearBit(valOrg, pin) + val = uint8(bit.Clear(int(valOrg), pin)) } else { - val = setBit(valOrg, pin) + val = uint8(bit.Set(int(valOrg), pin)) } if val != valOrg || m.mcpBehav.forceRefresh { diff --git a/drivers/i2c/pca9501_driver.go b/drivers/i2c/pca9501_driver.go index daa7da583..a71934ca7 100644 --- a/drivers/i2c/pca9501_driver.go +++ b/drivers/i2c/pca9501_driver.go @@ -1,5 +1,7 @@ package i2c +import "gobot.io/x/gobot/v2/drivers/common/bit" + // PCA9501 supports addresses from 0x00 to 0x7F // 0x00 - 0x3F: GPIO, 0x40 - 0x7F: EEPROM // @@ -80,9 +82,9 @@ func (p *PCA9501Driver) WriteGPIO(pin uint8, val uint8) error { return err } // set pin as output by clearing bit - iodirVal := clearBit(iodir, pin) + iodirVal := bit.Clear(int(iodir), pin) // write CTRL register - err = p.connection.WriteByte(iodirVal) + err = p.connection.WriteByte(uint8(iodirVal)) if err != nil { return err } @@ -92,14 +94,14 @@ func (p *PCA9501Driver) WriteGPIO(pin uint8, val uint8) error { return err } // set or reset the bit in value - var nVal uint8 + var nVal int if val == 0 { - nVal = clearBit(cVal, pin) + nVal = bit.Clear(int(cVal), pin) } else { - nVal = setBit(cVal, pin) + nVal = bit.Set(int(cVal), pin) } // write new value to port - err = p.connection.WriteByte(nVal) + err = p.connection.WriteByte(uint8(nVal)) if err != nil { return err } @@ -117,9 +119,9 @@ func (p *PCA9501Driver) ReadGPIO(pin uint8) (uint8, error) { return 0, err } // set pin as input by setting bit - iodirVal := setBit(iodir, pin) + iodirVal := bit.Set(int(iodir), pin) // write CTRL register - err = p.connection.WriteByte(iodirVal) + err = p.connection.WriteByte(uint8(iodirVal)) if err != nil { return 0, err } diff --git a/drivers/serial/LICENSE b/drivers/serial/LICENSE new file mode 100644 index 000000000..09094bb5e --- /dev/null +++ b/drivers/serial/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2013-2018 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/serial/README.md b/drivers/serial/README.md new file mode 100644 index 000000000..40da591f3 --- /dev/null +++ b/drivers/serial/README.md @@ -0,0 +1,15 @@ +# Serial + +This package provides drivers based on [Serial](https://en.wikipedia.org/wiki/Serial_port) communication ([UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter)). +devices. It is normally used by connecting an adaptor such as [SerialPort](https://gobot.io/documentation/platforms/serialport/) +that supports the needed interfaces for serial devices. + +## Getting Started + +Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) + +## Hardware Support + +Gobot has a extensible system for connecting to hardware devices. The following Serial devices are currently supported: + +- Sphero: Sphero diff --git a/drivers/serial/doc.go b/drivers/serial/doc.go new file mode 100644 index 000000000..11dd1b31e --- /dev/null +++ b/drivers/serial/doc.go @@ -0,0 +1,7 @@ +/* +Package serial provides Gobot drivers for Serial Port communication based devices. + +For further information refer to readme: +https://github.com/hybridgroup/gobot/blob/master/drivers/serial/README.md +*/ +package serial // import "gobot.io/x/gobot/v2/drivers/serial" diff --git a/drivers/serial/helpers_test.go b/drivers/serial/helpers_test.go new file mode 100644 index 000000000..b63f659f8 --- /dev/null +++ b/drivers/serial/helpers_test.go @@ -0,0 +1,28 @@ +package serial + +type serialTestAdaptor struct { + isConnected bool + name string +} + +func newSerialTestAdaptor() *serialTestAdaptor { + return &serialTestAdaptor{} +} + +func (t *serialTestAdaptor) IsConnected() bool { + return t.isConnected +} + +func (t *serialTestAdaptor) SerialRead(b []byte) (int, error) { + return len(b), nil +} + +func (t *serialTestAdaptor) SerialWrite(b []byte) (int, error) { + return len(b), nil +} + +// gobot.Adaptor interfaces +func (t *serialTestAdaptor) Connect() error { return nil } +func (t *serialTestAdaptor) Finalize() error { return nil } +func (t *serialTestAdaptor) Name() string { return t.name } +func (t *serialTestAdaptor) SetName(n string) { t.name = n } diff --git a/drivers/serial/serial_driver.go b/drivers/serial/serial_driver.go new file mode 100644 index 000000000..9b1aaf724 --- /dev/null +++ b/drivers/serial/serial_driver.go @@ -0,0 +1,104 @@ +package serial + +import ( + "log" + "sync" + + "gobot.io/x/gobot/v2" +) + +type SerialReader interface { + SerialRead(b []byte) (n int, err error) +} + +type SerialWriter interface { + SerialWrite(b []byte) (n int, err error) +} + +// optionApplier needs to be implemented by each configurable option type +type optionApplier interface { + apply(cfg *configuration) +} + +// configuration contains all changeable attributes of the driver. +type configuration struct { + name string +} + +// nameOption is the type for applying another name to the configuration +type nameOption string + +// Driver implements the interface gobot.Driver. +type driver struct { + gobot.Commander + connection interface{} + driverCfg *configuration + afterStart func() error + beforeHalt func() error + mutex *sync.Mutex +} + +// newDriver creates a new basic serial gobot driver. +func newDriver(a interface{}, name string) *driver { + d := driver{ + Commander: gobot.NewCommander(), + connection: a, + driverCfg: &configuration{name: gobot.DefaultName(name)}, + afterStart: func() error { return nil }, + beforeHalt: func() error { return nil }, + mutex: &sync.Mutex{}, + } + + return &d +} + +// WithName is used to replace the default name of the driver. +func WithName(name string) optionApplier { + return nameOption(name) +} + +// Name returns the name of the driver. +func (d *driver) Name() string { + return d.driverCfg.name +} + +// SetName sets the name of the driver. +// Deprecated: Please use option [aio.WithName] instead. +func (d *driver) SetName(name string) { + WithName(name).apply(d.driverCfg) +} + +// Connection returns the connection of the driver. +func (d *driver) Connection() gobot.Connection { + if conn, ok := d.connection.(gobot.Connection); ok { + return conn + } + + log.Printf("%s has no gobot connection\n", d.driverCfg.name) + return nil +} + +// Start initializes the driver. +func (d *driver) Start() error { + d.mutex.Lock() + defer d.mutex.Unlock() + + // currently there is nothing to do here for the driver + + return d.afterStart() +} + +// Halt halts the driver. +func (d *driver) Halt() error { + d.mutex.Lock() + defer d.mutex.Unlock() + + // currently there is nothing to do after halt for the driver + + return d.beforeHalt() +} + +// apply change the name in the configuration. +func (o nameOption) apply(c *configuration) { + c.name = string(o) +} diff --git a/drivers/serial/serial_driver_test.go b/drivers/serial/serial_driver_test.go new file mode 100644 index 000000000..b2dda80c6 --- /dev/null +++ b/drivers/serial/serial_driver_test.go @@ -0,0 +1,69 @@ +package serial + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "gobot.io/x/gobot/v2" +) + +var _ gobot.Driver = (*driver)(nil) + +func initTestDriver() *driver { + a := newSerialTestAdaptor() + d := newDriver(a, "SERIAL_BASIC") + return d +} + +func Test_newDriver(t *testing.T) { + // arrange + const name = "mybot" + a := newSerialTestAdaptor() + // act + d := newDriver(a, name) + // assert + assert.IsType(t, &driver{}, d) + assert.NotNil(t, d.driverCfg) + assert.True(t, strings.HasPrefix(d.Name(), name)) + assert.Equal(t, a, d.Connection()) + require.NoError(t, d.afterStart()) + require.NoError(t, d.beforeHalt()) + assert.NotNil(t, d.Commander) + assert.NotNil(t, d.mutex) +} + +func Test_applyWithName(t *testing.T) { + // arrange + const name = "mybot" + cfg := configuration{name: "oldname"} + // act + WithName(name).apply(&cfg) + // assert + assert.Equal(t, name, cfg.name) +} + +func TestStart(t *testing.T) { + // arrange + d := initTestDriver() + // act, assert + require.NoError(t, d.Start()) + // arrange after start function + d.afterStart = func() error { return fmt.Errorf("after start error") } + // act, assert + require.EqualError(t, d.Start(), "after start error") +} + +func TestHalt(t *testing.T) { + // arrange + d := initTestDriver() + // act, assert + require.NoError(t, d.Halt()) + // arrange after start function + d.beforeHalt = func() error { return fmt.Errorf("before halt error") } + // act, assert + require.EqualError(t, d.Halt(), "before halt error") +} diff --git a/drivers/serial/sphero_driver.go b/drivers/serial/sphero_driver.go new file mode 100644 index 000000000..b65c52f7b --- /dev/null +++ b/drivers/serial/sphero_driver.go @@ -0,0 +1,476 @@ +package serial + +import ( + "bytes" + "encoding/binary" + "errors" + "log" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/common/sphero" +) + +type spheroSerialAdaptor interface { + gobot.Adaptor + SerialReader + SerialWriter + + IsConnected() bool +} + +type packet struct { + header []uint8 + body []uint8 + checksum uint8 +} + +// SpheroDriver Represents a Sphero 2.0 +type SpheroDriver struct { + *driver + gobot.Eventer + seq uint8 + asyncResponse [][]uint8 + syncResponse [][]uint8 + packetChannel chan *packet + responseChannel chan []uint8 + originalColor []uint8 // Only used for calibration. +} + +// NewSpheroDriver returns a new SpheroDriver given a Sphero Adaptor. +// +// Adds the following API Commands: +// +// "ConfigureLocator" - See SpheroDriver.ConfigureLocator +// "Roll" - See SpheroDriver.Roll +// "Stop" - See SpheroDriver.Stop +// "GetRGB" - See SpheroDriver.GetRGB +// "ReadLocator" - See SpheroDriver.ReadLocator +// "SetBackLED" - See SpheroDriver.SetBackLED +// "SetHeading" - See SpheroDriver.SetHeading +// "SetStabilization" - See SpheroDriver.SetStabilization +// "SetDataStreaming" - See SpheroDriver.SetDataStreaming +// "SetRotationRate" - See SpheroDriver.SetRotationRate +func NewSpheroDriver(a spheroSerialAdaptor) *SpheroDriver { + d := &SpheroDriver{ + driver: newDriver(a, "Sphero"), + Eventer: gobot.NewEventer(), + packetChannel: make(chan *packet, 1024), + responseChannel: make(chan []uint8, 1024), + } + d.afterStart = d.initialize + d.beforeHalt = d.shutdown + + d.AddEvent(sphero.ErrorEvent) + d.AddEvent(sphero.CollisionEvent) + d.AddEvent(sphero.SensorDataEvent) + + //nolint:forcetypeassert // ok here + d.AddCommand("SetRGB", func(params map[string]interface{}) interface{} { + r := uint8(params["r"].(float64)) + g := uint8(params["g"].(float64)) + b := uint8(params["b"].(float64)) + d.SetRGB(r, g, b) + return nil + }) + + //nolint:forcetypeassert // ok here + d.AddCommand("Roll", func(params map[string]interface{}) interface{} { + speed := uint8(params["speed"].(float64)) + heading := uint16(params["heading"].(float64)) + d.Roll(speed, heading) + return nil + }) + + d.AddCommand("Stop", func(params map[string]interface{}) interface{} { + d.Stop() + return nil + }) + + d.AddCommand("GetRGB", func(params map[string]interface{}) interface{} { + return d.GetRGB() + }) + + d.AddCommand("ReadLocator", func(params map[string]interface{}) interface{} { + return d.ReadLocator() + }) + + //nolint:forcetypeassert // ok here + d.AddCommand("SetBackLED", func(params map[string]interface{}) interface{} { + level := uint8(params["level"].(float64)) + d.SetBackLED(level) + return nil + }) + //nolint:forcetypeassert // ok here + d.AddCommand("SetRotationRate", func(params map[string]interface{}) interface{} { + level := uint8(params["level"].(float64)) + d.SetRotationRate(level) + return nil + }) + //nolint:forcetypeassert // ok here + d.AddCommand("SetHeading", func(params map[string]interface{}) interface{} { + heading := uint16(params["heading"].(float64)) + d.SetHeading(heading) + return nil + }) + //nolint:forcetypeassert // ok here + d.AddCommand("SetStabilization", func(params map[string]interface{}) interface{} { + on := params["enable"].(bool) + d.SetStabilization(on) + return nil + }) + //nolint:forcetypeassert // ok here + d.AddCommand("SetDataStreaming", func(params map[string]interface{}) interface{} { + N := uint16(params["N"].(float64)) + M := uint16(params["M"].(float64)) + Mask := uint32(params["Mask"].(float64)) + Pcnt := uint8(params["Pcnt"].(float64)) + Mask2 := uint32(params["Mask2"].(float64)) + + d.SetDataStreaming(sphero.DataStreamingConfig{N: N, M: M, Mask2: Mask2, Pcnt: Pcnt, Mask: Mask}) + return nil + }) + //nolint:forcetypeassert // ok here + d.AddCommand("ConfigureLocator", func(params map[string]interface{}) interface{} { + Flags := uint8(params["Flags"].(float64)) + X := int16(params["X"].(float64)) + Y := int16(params["Y"].(float64)) + YawTare := int16(params["YawTare"].(float64)) + + d.ConfigureLocator(sphero.LocatorConfig{Flags: Flags, X: X, Y: Y, YawTare: YawTare}) + return nil + }) + + return d +} + +// SetRGB sets the Sphero to the given r, g, and b values +func (d *SpheroDriver) SetRGB(r uint8, g uint8, b uint8) { + d.sendCraftPacket([]uint8{r, g, b, 0x01}, 0x20) +} + +// GetRGB returns the current r, g, b value of the Sphero +func (d *SpheroDriver) GetRGB() []uint8 { + buf := d.getSyncResponse(d.craftPacket([]uint8{}, 0x22)) + if len(buf) == 9 { + return []uint8{buf[5], buf[6], buf[7]} + } + return []uint8{} +} + +// ReadLocator reads Sphero's current position (X,Y), component velocities and SOG (speed over ground). +func (d *SpheroDriver) ReadLocator() []int16 { + buf := d.getSyncResponse(d.craftPacket([]uint8{}, 0x15)) + if len(buf) == 16 { + vals := make([]int16, 5) + _ = binary.Read(bytes.NewReader(buf[5:15]), binary.BigEndian, &vals) + return vals + } + return []int16{} +} + +// SetBackLED sets the Sphero Back LED to the specified brightness +func (d *SpheroDriver) SetBackLED(level uint8) { + d.sendCraftPacket([]uint8{level}, 0x21) +} + +// SetRotationRate sets the Sphero rotation rate +// A value of 255 jumps to the maximum (currently 400 degrees/sec). +func (d *SpheroDriver) SetRotationRate(level uint8) { + d.sendCraftPacket([]uint8{level}, 0x03) +} + +// SetHeading sets the heading of the Sphero +func (d *SpheroDriver) SetHeading(heading uint16) { + d.sendCraftPacket([]uint8{uint8(heading >> 8), uint8(heading & 0xFF)}, 0x01) +} + +// SetStabilization enables or disables the built-in auto stabilizing features of the Sphero +func (d *SpheroDriver) SetStabilization(on bool) { + b := uint8(0x01) + if !on { + b = 0x00 + } + d.sendCraftPacket([]uint8{b}, 0x02) +} + +// Roll sends a roll command to the Sphero gives a speed and heading +func (d *SpheroDriver) Roll(speed uint8, heading uint16) { + d.sendCraftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x30) +} + +// ConfigureLocator configures and enables the Locator +func (d *SpheroDriver) ConfigureLocator(lc sphero.LocatorConfig) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, lc); err != nil { + panic(err) + } + + d.sendCraftPacket(buf.Bytes(), 0x13) +} + +// SetDataStreaming enables sensor data streaming +func (d *SpheroDriver) SetDataStreaming(dsc sphero.DataStreamingConfig) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, dsc); err != nil { + panic(err) + } + + d.sendCraftPacket(buf.Bytes(), 0x11) +} + +// Stop sets the Sphero to a roll speed of 0 +func (d *SpheroDriver) Stop() { + d.Roll(0, 0) +} + +// ConfigureCollisionDetection configures the sensitivity of the detection. +func (d *SpheroDriver) ConfigureCollisionDetection(cc sphero.CollisionConfig) { + d.sendCraftPacket([]uint8{cc.Method, cc.Xt, cc.Yt, cc.Xs, cc.Ys, cc.Dead}, 0x12) +} + +// SetCalibration sets up Sphero for manual heading calibration. +// It does this by turning on the tail light (so you can tell where it's +// facing) and disabling stabilization (so you can adjust the heading). +// +// When done, call FinishCalibration to set the new heading, and re-enable +// stabilization. +func (d *SpheroDriver) StartCalibration() { + d.originalColor = d.GetRGB() + d.SetRGB(0, 0, 0) + d.SetBackLED(127) + d.SetStabilization(false) +} + +// FinishCalibration ends Sphero's calibration mode, by setting +// the new heading as current, and re-enabling normal defaults. This is a NOP +// in case StartCalibration was not called. +func (d *SpheroDriver) FinishCalibration() { + if d.originalColor == nil { + // Piggybacking on the original color being set to know if we are + // calibrating or not. + return + } + + d.SetHeading(0) + d.SetRGB(d.originalColor[0], d.originalColor[1], d.originalColor[2]) + d.SetBackLED(0) + d.SetStabilization(true) + d.originalColor = nil +} + +// initialize starts the SpheroDriver and enables Collision Detection. +// Returns true on successful start. +// +// Emits the Events: +// +// Collision sphero.CollisionPacket - On Collision Detected +// SensorData sphero.DataStreamingPacket - On Data Streaming event +// Error error- On error while processing asynchronous response +func (d *SpheroDriver) initialize() error { + go func() { + for { + packet := <-d.packetChannel + err := d.write(packet) + if err != nil { + d.Publish(sphero.ErrorEvent, err) + } + } + }() + + go func() { + for { + response := <-d.responseChannel + d.syncResponse = append(d.syncResponse, response) + } + }() + + go func() { + for { + header := d.readHeader() + if len(header) > 0 { + body := d.readBody(header[4]) + data := append(header, body...) + checksum := data[len(data)-1] + if checksum != sphero.CalculateChecksum(data[2:len(data)-1]) { + continue + } + switch header[1] { + case 0xFE: + d.asyncResponse = append(d.asyncResponse, data) + case 0xFF: + d.responseChannel <- data + } + } + } + }() + + go func() { + for { + var evt []uint8 + for len(d.asyncResponse) != 0 { + evt, d.asyncResponse = d.asyncResponse[len(d.asyncResponse)-1], d.asyncResponse[:len(d.asyncResponse)-1] + if evt[2] == 0x07 { + d.handleCollisionDetected(evt) + } else if evt[2] == 0x03 { + d.handleDataStreaming(evt) + } + } + time.Sleep(100 * time.Millisecond) + } + }() + + d.ConfigureCollisionDetection(spheroDefaultCollisionConfig()) + d.enableStopOnDisconnect() + + return nil +} + +// shutdown halts the SpheroDriver and sends a SpheroDriver.Stop command to the Sphero. +// Returns true on successful halt. +func (d *SpheroDriver) shutdown() error { + if d.adaptor().IsConnected() { + gobot.Every(10*time.Millisecond, func() { + d.Stop() + }) + time.Sleep(1 * time.Second) + } + return nil +} + +func (d *SpheroDriver) enableStopOnDisconnect() { + d.sendCraftPacket([]uint8{0x00, 0x00, 0x00, 0x01}, 0x37) +} + +func (d *SpheroDriver) handleCollisionDetected(data []uint8) { + // ensure data is the right length: + if len(data) != 22 || data[4] != 17 { + return + } + var collision sphero.CollisionPacket + buffer := bytes.NewBuffer(data[5:]) // skip header + if err := binary.Read(buffer, binary.BigEndian, &collision); err != nil { + panic(err) + } + d.Publish(sphero.CollisionEvent, collision) +} + +func (d *SpheroDriver) handleDataStreaming(data []uint8) { + // ensure data is the right length: + if len(data) != 90 { + return + } + var dataPacket sphero.DataStreamingPacket + buffer := bytes.NewBuffer(data[5:]) // skip header + if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { + panic(err) + } + d.Publish(sphero.SensorDataEvent, dataPacket) +} + +func (d *SpheroDriver) getSyncResponse(packet *packet) []byte { + d.packetChannel <- packet + for i := 0; i < 500; i++ { + for key := range d.syncResponse { + if d.syncResponse[key][3] == packet.header[4] && len(d.syncResponse[key]) > 6 { + var response []byte + response, d.syncResponse = d.syncResponse[len(d.syncResponse)-1], d.syncResponse[:len(d.syncResponse)-1] + return response + } + } + time.Sleep(100 * time.Microsecond) + } + + return []byte{} +} + +func (d *SpheroDriver) sendCraftPacket(body []uint8, cid byte) { + d.packetChannel <- d.craftPacket(body, cid) +} + +func (d *SpheroDriver) craftPacket(body []uint8, cid byte) *packet { + dlen := len(body) + 1 + did := uint8(0x02) + hdr := []uint8{0xFF, 0xFF, did, cid, d.seq, uint8(dlen)} + buf := append(hdr, body...) + + packet := &packet{ + body: body, + header: hdr, + checksum: sphero.CalculateChecksum(buf[2:]), + } + + return packet +} + +func (d *SpheroDriver) write(packet *packet) error { + d.mutex.Lock() + defer d.mutex.Unlock() + + buf := append(packet.header, packet.body...) + buf = append(buf, packet.checksum) + length, err := d.adaptor().SerialWrite(buf) + if err != nil { + return err + } + + if length != len(buf) { + return errors.New("Not enough bytes written") + } + d.seq++ + return nil +} + +func (d *SpheroDriver) readHeader() []uint8 { + return d.readNextChunk(5) +} + +func (d *SpheroDriver) readBody(length uint8) []uint8 { + return d.readNextChunk(int(length)) +} + +func (d *SpheroDriver) readNextChunk(length int) []uint8 { + read := make([]uint8, length) + bytesRead := 0 + + for bytesRead < length { + time.Sleep(1 * time.Millisecond) + n, err := d.adaptor().SerialRead(read[bytesRead:]) + if err != nil { + return nil + } + bytesRead += n + } + return read +} + +func (d *SpheroDriver) adaptor() spheroSerialAdaptor { + if a, ok := d.connection.(spheroSerialAdaptor); ok { + return a + } + + log.Printf("%s has no Sphere serial connector\n", d.driverCfg.name) + return nil +} + +// spheroDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults +func spheroDefaultCollisionConfig() sphero.CollisionConfig { + return sphero.CollisionConfig{ + Method: 0x01, + Xt: 0x80, + Yt: 0x80, + Xs: 0x80, + Ys: 0x80, + Dead: 0x60, + } +} + +// spheroDefaultLocatorConfig returns a LocatorConfig with defaults +func spheroDefaultLocatorConfig() sphero.LocatorConfig { + return sphero.LocatorConfig{ + Flags: 0x01, + X: 0x00, + Y: 0x00, + YawTare: 0x00, + } +} diff --git a/platforms/sphero/sphero_driver_test.go b/drivers/serial/sphero_driver_test.go similarity index 66% rename from platforms/sphero/sphero_driver_test.go rename to drivers/serial/sphero_driver_test.go index 4004d083f..417f474d0 100644 --- a/platforms/sphero/sphero_driver_test.go +++ b/drivers/serial/sphero_driver_test.go @@ -1,5 +1,5 @@ //nolint:forcetypeassert // ok here -package sphero +package serial import ( "bytes" @@ -11,24 +11,23 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/common/sphero" ) var _ gobot.Driver = (*SpheroDriver)(nil) func initTestSpheroDriver() *SpheroDriver { - a, _ := initTestSpheroAdaptor() - _ = a.Connect() + a := newSerialTestAdaptor() return NewSpheroDriver(a) } -func TestSpheroDriverName(t *testing.T) { +func TestNewSpheroDriver(t *testing.T) { d := initTestSpheroDriver() assert.True(t, strings.HasPrefix(d.Name(), "Sphero")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) + assert.NotNil(t, d.Eventer) } -func TestSpheroDriver(t *testing.T) { +func TestSpheroCommands(t *testing.T) { d := initTestSpheroDriver() var ret interface{} @@ -80,30 +79,28 @@ func TestSpheroDriver(t *testing.T) { ret = d.Command("ReadLocator")(nil) assert.Equal(t, []int16{}, ret) - - assert.True(t, strings.HasPrefix(d.Name(), "Sphero")) - assert.True(t, strings.HasPrefix(d.Connection().Name(), "Sphero")) } -func TestSpheroDriverStart(t *testing.T) { +func TestSpheroStart(t *testing.T) { d := initTestSpheroDriver() require.NoError(t, d.Start()) } -func TestSpheroDriverHalt(t *testing.T) { - d := initTestSpheroDriver() - d.adaptor().connected = true +func TestSpheroHalt(t *testing.T) { + a := newSerialTestAdaptor() + a.isConnected = true + d := NewSpheroDriver(a) require.NoError(t, d.Halt()) } -func TestSpheroDriverSetDataStreaming(t *testing.T) { +func TestSpheroSetDataStreaming(t *testing.T) { d := initTestSpheroDriver() - d.SetDataStreaming(DefaultDataStreamingConfig()) + d.SetDataStreaming(sphero.DefaultDataStreamingConfig()) data := <-d.packetChannel buf := new(bytes.Buffer) - _ = binary.Write(buf, binary.BigEndian, DefaultDataStreamingConfig()) + _ = binary.Write(buf, binary.BigEndian, sphero.DefaultDataStreamingConfig()) assert.Equal(t, buf.Bytes(), data.body) @@ -119,20 +116,20 @@ func TestSpheroDriverSetDataStreaming(t *testing.T) { assert.Nil(t, ret) data = <-d.packetChannel - dconfig := DataStreamingConfig{N: 100, M: 200, Mask: 300, Pcnt: 255, Mask2: 400} + dconfig := sphero.DataStreamingConfig{N: 100, M: 200, Mask: 300, Pcnt: 255, Mask2: 400} buf = new(bytes.Buffer) _ = binary.Write(buf, binary.BigEndian, dconfig) assert.Equal(t, buf.Bytes(), data.body) } -func TestConfigureLocator(t *testing.T) { +func TestSpheroConfigureLocator(t *testing.T) { d := initTestSpheroDriver() - d.ConfigureLocator(DefaultLocatorConfig()) + d.ConfigureLocator(spheroDefaultLocatorConfig()) data := <-d.packetChannel buf := new(bytes.Buffer) - _ = binary.Write(buf, binary.BigEndian, DefaultLocatorConfig()) + _ = binary.Write(buf, binary.BigEndian, spheroDefaultLocatorConfig()) assert.Equal(t, buf.Bytes(), data.body) @@ -147,26 +144,9 @@ func TestConfigureLocator(t *testing.T) { assert.Nil(t, ret) data = <-d.packetChannel - lconfig := LocatorConfig{Flags: 1, X: 100, Y: 100, YawTare: 0} + lconfig := sphero.LocatorConfig{Flags: 1, X: 100, Y: 100, YawTare: 0} buf = new(bytes.Buffer) _ = binary.Write(buf, binary.BigEndian, lconfig) assert.Equal(t, buf.Bytes(), data.body) } - -func TestCalculateChecksum(t *testing.T) { - tests := []struct { - data []byte - checksum byte - }{ - {[]byte{0x00}, 0xff}, - {[]byte{0xf0, 0x0f}, 0x00}, - } - - for _, tt := range tests { - actual := calculateChecksum(tt.data) - if actual != tt.checksum { - t.Errorf("Expected %x, got %x for data %x.", tt.checksum, actual, tt.data) - } - } -} diff --git a/examples/ble_battery.go b/examples/ble_battery.go index ee8fb04f0..4656954fa 100644 --- a/examples/ble_battery.go +++ b/examples/ble_battery.go @@ -21,11 +21,12 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) battery := ble.NewBatteryDriver(bleAdaptor) work := func() { diff --git a/examples/bb8-collision.go b/examples/ble_bb8-collision.go similarity index 78% rename from examples/bb8-collision.go rename to examples/ble_bb8-collision.go index 0b4df325d..6d00daaea 100644 --- a/examples/bb8-collision.go +++ b/examples/ble_bb8-collision.go @@ -20,13 +20,13 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/bb8" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - bb := bb8.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + bb := sphero.NewBB8Driver(bleAdaptor) work := func() { bb.On("collision", func(data interface{}) { diff --git a/examples/bb8.go b/examples/ble_bb8.go similarity index 77% rename from examples/bb8.go rename to examples/ble_bb8.go index 8fc5dfc81..24d082d37 100644 --- a/examples/bb8.go +++ b/examples/ble_bb8.go @@ -20,13 +20,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/bb8" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - bb8 := bb8.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + bb8 := sphero.NewBB8Driver(bleAdaptor) work := func() { gobot.Every(1*time.Second, func() { diff --git a/examples/ble_device_info.go b/examples/ble_device_info.go index 5c612d302..bff64e7e9 100644 --- a/examples/ble_device_info.go +++ b/examples/ble_device_info.go @@ -20,11 +20,12 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) info := ble.NewDeviceInformationDriver(bleAdaptor) work := func() { diff --git a/examples/ble_generic_access.go b/examples/ble_generic_access.go index 761315192..416571206 100644 --- a/examples/ble_generic_access.go +++ b/examples/ble_generic_access.go @@ -20,11 +20,12 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) access := ble.NewGenericAccessDriver(bleAdaptor) work := func() { diff --git a/examples/ble_multiple_generic.go b/examples/ble_multiple_generic.go index 15dd9f82d..bbce13d9e 100644 --- a/examples/ble_multiple_generic.go +++ b/examples/ble_multiple_generic.go @@ -21,11 +21,12 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func NewSwarmBot(port string) *gobot.Robot { - bleAdaptor := ble.NewClientAdaptor(port) + bleAdaptor := bleclient.NewAdaptor(port) access := ble.NewGenericAccessDriver(bleAdaptor) work := func() { diff --git a/examples/ble_multiple_info.go b/examples/ble_multiple_info.go index 8f8b3100b..6155138b3 100644 --- a/examples/ble_multiple_info.go +++ b/examples/ble_multiple_info.go @@ -21,11 +21,12 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func NewSwarmBot(port string) *gobot.Robot { - bleAdaptor := ble.NewClientAdaptor(port) + bleAdaptor := bleclient.NewAdaptor(port) info := ble.NewDeviceInformationDriver(bleAdaptor) work := func() { diff --git a/examples/ollie.go b/examples/ble_ollie.go similarity index 72% rename from examples/ollie.go rename to examples/ble_ollie.go index e98da7b11..a2dfe8e19 100644 --- a/examples/ollie.go +++ b/examples/ble_ollie.go @@ -11,13 +11,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - ollie := ollie.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + ollie := sphero.NewOllieDriver(bleAdaptor) work := func() { gobot.Every(1*time.Second, func() { diff --git a/examples/ollie_boost.go b/examples/ble_ollie_boost.go similarity index 73% rename from examples/ollie_boost.go rename to examples/ble_ollie_boost.go index 389008c48..ba1859f17 100644 --- a/examples/ollie_boost.go +++ b/examples/ble_ollie_boost.go @@ -11,13 +11,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - ollieBot := ollie.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + ollieBot := sphero.NewOllieDriver(bleAdaptor) work := func() { head := 90 diff --git a/examples/ollie_crazy.go b/examples/ble_ollie_crazy.go similarity index 60% rename from examples/ollie_crazy.go rename to examples/ble_ollie_crazy.go index d6a7bf9fb..cef96f22d 100644 --- a/examples/ollie_crazy.go +++ b/examples/ble_ollie_crazy.go @@ -11,19 +11,19 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - ollieBot := ollie.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + ollieBot := sphero.NewOllieDriver(bleAdaptor) work := func() { ollieBot.SetRGB(255, 0, 255) gobot.Every(1*time.Second, func() { // Ollie performs 'crazy-ollie' trick - ollieBot.SetRawMotorValues(ollie.Forward, uint8(255), ollie.Forward, uint8(255)) + ollieBot.SetRawMotorValues(sphero.Forward, uint8(255), sphero.Forward, uint8(255)) }) } diff --git a/examples/ollie_mqtt.go b/examples/ble_ollie_mqtt.go similarity index 88% rename from examples/ollie_mqtt.go rename to examples/ble_ollie_mqtt.go index 3e8998f6f..2d9c07977 100644 --- a/examples/ollie_mqtt.go +++ b/examples/ble_ollie_mqtt.go @@ -12,9 +12,9 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" "gobot.io/x/gobot/v2/platforms/mqtt" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" ) const ( @@ -25,8 +25,8 @@ const ( ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - ollie := ollie.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + ollie := sphero.NewOllieDriver(bleAdaptor) mqttAdaptor := mqtt.NewAdaptor("tcp://iot.eclipse.org:1883", "ollie") diff --git a/examples/ollie_multiple.go b/examples/ble_ollie_multiple.go similarity index 83% rename from examples/ollie_multiple.go rename to examples/ble_ollie_multiple.go index 01dadf81a..a80f1d413 100644 --- a/examples/ollie_multiple.go +++ b/examples/ble_ollie_multiple.go @@ -20,13 +20,13 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func NewSwarmBot(port string) *gobot.Robot { - bleAdaptor := ble.NewClientAdaptor(port) - ollieDriver := ollie.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(port) + ollieDriver := sphero.NewOllieDriver(bleAdaptor) work := func() { gobot.Every(1*time.Second, func() { diff --git a/examples/ollie_roll.go b/examples/ble_ollie_roll.go similarity index 69% rename from examples/ollie_roll.go rename to examples/ble_ollie_roll.go index 3ee7c30a4..bf07d7e36 100644 --- a/examples/ollie_roll.go +++ b/examples/ble_ollie_roll.go @@ -11,13 +11,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - ollie := ollie.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + ollie := sphero.NewOllieDriver(bleAdaptor) work := func() { ollie.SetRGB(255, 0, 255) diff --git a/examples/ollie_spin.go b/examples/ble_ollie_spin.go similarity index 60% rename from examples/ollie_spin.go rename to examples/ble_ollie_spin.go index 736e9a4e4..027328f79 100644 --- a/examples/ollie_spin.go +++ b/examples/ble_ollie_spin.go @@ -11,19 +11,19 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - ollieBot := ollie.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + ollieBot := sphero.NewOllieDriver(bleAdaptor) work := func() { ollieBot.SetRGB(255, 0, 255) gobot.Every(1*time.Second, func() { // Ollie performs 360 spin trick - ollieBot.SetRawMotorValues(ollie.Forward, uint8(255), ollie.Reverse, uint8(255)) + ollieBot.SetRawMotorValues(sphero.Forward, uint8(255), sphero.Reverse, uint8(255)) }) } diff --git a/examples/sprkplus.go b/examples/ble_sprkplus.go similarity index 77% rename from examples/sprkplus.go rename to examples/ble_sprkplus.go index 8ad732e89..ad85eb50e 100644 --- a/examples/sprkplus.go +++ b/examples/ble_sprkplus.go @@ -20,13 +20,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/sprkplus" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - sprk := sprkplus.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + sprk := sphero.NewSPRKPlusDriver(bleAdaptor) work := func() { gobot.Every(1*time.Second, func() { diff --git a/examples/sprkplus_collision.go b/examples/ble_sprkplus_collision.go similarity index 77% rename from examples/sprkplus_collision.go rename to examples/ble_sprkplus_collision.go index 4d58a5f89..c053c2893 100644 --- a/examples/sprkplus_collision.go +++ b/examples/ble_sprkplus_collision.go @@ -20,13 +20,13 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/sprkplus" + "gobot.io/x/gobot/v2/drivers/ble/sphero" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - ball := sprkplus.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + ball := sphero.NewSPRKPlusDriver(bleAdaptor) work := func() { ball.On("collision", func(data interface{}) { diff --git a/examples/leap_sphero.go b/examples/leap_sphero.go index 455faec8f..91e6c179d 100644 --- a/examples/leap_sphero.go +++ b/examples/leap_sphero.go @@ -10,16 +10,17 @@ import ( "math" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/serial" "gobot.io/x/gobot/v2/platforms/leap" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { leapAdaptor := leap.NewAdaptor("127.0.0.1:6437") - spheroAdaptor := sphero.NewAdaptor("/dev/tty.Sphero-YBW-RN-SPP") + spheroAdaptor := serialport.NewAdaptor("/dev/tty.Sphero-YBW-RN-SPP") leapDriver := leap.NewDriver(leapAdaptor) - spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor) work := func() { leapDriver.On(leap.MessageEvent, func(data interface{}) { diff --git a/examples/microbit_accelerometer.go b/examples/microbit_accelerometer.go index 0d85c72f8..55fbc5350 100644 --- a/examples/microbit_accelerometer.go +++ b/examples/microbit_accelerometer.go @@ -31,16 +31,16 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/drivers/ble/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewAccelerometerDriver(bleAdaptor) work := func() { - ubit.On(microbit.Accelerometer, func(data interface{}) { + ubit.On(microbit.AccelerometerEvent, func(data interface{}) { fmt.Println("Accelerometer", data) }) } diff --git a/examples/microbit_blink.go b/examples/microbit_blink.go index d453254ca..c384c68dc 100644 --- a/examples/microbit_blink.go +++ b/examples/microbit_blink.go @@ -34,13 +34,13 @@ import ( "time" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/microbit" "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewIOPinDriver(bleAdaptor) led := gpio.NewLedDriver(ubit, "0") diff --git a/examples/microbit_buttons.go b/examples/microbit_buttons.go index afd77abd0..54123a456 100644 --- a/examples/microbit_buttons.go +++ b/examples/microbit_buttons.go @@ -29,20 +29,20 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/drivers/ble/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewButtonDriver(bleAdaptor) work := func() { - ubit.On(microbit.ButtonA, func(data interface{}) { + ubit.On(microbit.ButtonAEvent, func(data interface{}) { fmt.Println("button A", data) }) - ubit.On(microbit.ButtonB, func(data interface{}) { + ubit.On(microbit.ButtonBEvent, func(data interface{}) { fmt.Println("button B", data) }) } diff --git a/examples/microbit_buttons_leds.go b/examples/microbit_buttons_leds.go index 77cb3f0f2..222ee9d11 100644 --- a/examples/microbit_buttons_leds.go +++ b/examples/microbit_buttons_leds.go @@ -30,17 +30,17 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/drivers/ble/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) buttons := microbit.NewButtonDriver(bleAdaptor) leds := microbit.NewLEDDriver(bleAdaptor) work := func() { - buttons.On(microbit.ButtonA, func(data interface{}) { + buttons.On(microbit.ButtonAEvent, func(data interface{}) { if data.([]byte)[0] == 1 { leds.UpLeftArrow() return @@ -49,7 +49,7 @@ func main() { leds.Blank() }) - buttons.On(microbit.ButtonB, func(data interface{}) { + buttons.On(microbit.ButtonBEvent, func(data interface{}) { if data.([]byte)[0] == 1 { leds.UpRightArrow() return diff --git a/examples/microbit_io_button.go b/examples/microbit_io_button.go index c9978138f..c1e80be36 100644 --- a/examples/microbit_io_button.go +++ b/examples/microbit_io_button.go @@ -34,13 +34,13 @@ import ( "os" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble/microbit" "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewIOPinDriver(bleAdaptor) button := gpio.NewButtonDriver(ubit, "0") diff --git a/examples/microbit_led.go b/examples/microbit_led.go index a034f35b1..99586dd27 100644 --- a/examples/microbit_led.go +++ b/examples/microbit_led.go @@ -31,12 +31,12 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/drivers/ble/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewLEDDriver(bleAdaptor) work := func() { diff --git a/examples/microbit_magnetometer.go b/examples/microbit_magnetometer.go index ffae1d67f..8e78bbbff 100644 --- a/examples/microbit_magnetometer.go +++ b/examples/microbit_magnetometer.go @@ -31,16 +31,16 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/drivers/ble/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewMagnetometerDriver(bleAdaptor) work := func() { - ubit.On(microbit.Magnetometer, func(data interface{}) { + ubit.On(microbit.MagnetometerEvent, func(data interface{}) { fmt.Println("Magnetometer", data) }) } diff --git a/examples/microbit_temperature.go b/examples/microbit_temperature.go index 821aad37b..a27109768 100644 --- a/examples/microbit_temperature.go +++ b/examples/microbit_temperature.go @@ -31,16 +31,16 @@ import ( "os" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/drivers/ble/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewTemperatureDriver(bleAdaptor) work := func() { - ubit.On(microbit.Temperature, func(data interface{}) { + ubit.On(microbit.TemperatureEvent, func(data interface{}) { fmt.Println("Temperature", data) }) } diff --git a/examples/minidrone.go b/examples/minidrone.go index a7a0b93b6..17519d84b 100644 --- a/examples/minidrone.go +++ b/examples/minidrone.go @@ -20,13 +20,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/parrot/minidrone" + "gobot.io/x/gobot/v2/drivers/ble/parrot" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - drone := minidrone.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + drone := parrot.NewMinidroneDriver(bleAdaptor) work := func() { drone.TakeOff() diff --git a/examples/minidrone_events.go b/examples/minidrone_events.go index 6005d29e7..b95eb10a6 100644 --- a/examples/minidrone_events.go +++ b/examples/minidrone_events.go @@ -21,39 +21,39 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/parrot/minidrone" + "gobot.io/x/gobot/v2/drivers/ble/parrot" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - drone := minidrone.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + drone := parrot.NewMinidroneDriver(bleAdaptor) work := func() { - drone.On(minidrone.Battery, func(data interface{}) { + drone.On(parrot.BatteryEvent, func(data interface{}) { fmt.Printf("battery: %d\n", data) }) - drone.On(minidrone.FlightStatus, func(data interface{}) { + drone.On(parrot.FlightStatusEvent, func(data interface{}) { fmt.Printf("flight status: %d\n", data) }) - drone.On(minidrone.Takeoff, func(data interface{}) { + drone.On(parrot.TakeoffEvent, func(data interface{}) { fmt.Println("taking off...") }) - drone.On(minidrone.Hovering, func(data interface{}) { + drone.On(parrot.HoveringEvent, func(data interface{}) { fmt.Println("hovering!") gobot.After(5*time.Second, func() { drone.Land() }) }) - drone.On(minidrone.Landing, func(data interface{}) { + drone.On(parrot.LandingEvent, func(data interface{}) { fmt.Println("landing...") }) - drone.On(minidrone.Landed, func(data interface{}) { + drone.On(parrot.LandedEvent, func(data interface{}) { fmt.Println("landed.") }) diff --git a/examples/minidrone_mambo_ps3.go b/examples/minidrone_mambo_ps3.go index b7ccd9b3a..b1b443a72 100644 --- a/examples/minidrone_mambo_ps3.go +++ b/examples/minidrone_mambo_ps3.go @@ -28,9 +28,9 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble/parrot" + "gobot.io/x/gobot/v2/platforms/bleclient" "gobot.io/x/gobot/v2/platforms/joystick" - "gobot.io/x/gobot/v2/platforms/parrot/minidrone" ) type pair struct { @@ -48,8 +48,8 @@ func main() { "./platforms/joystick/configs/dualshock3.json", ) - droneAdaptor := ble.NewClientAdaptor(os.Args[1]) - drone := minidrone.NewDriver(droneAdaptor) + droneAdaptor := bleclient.NewAdaptor(os.Args[1]) + drone := parrot.NewMinidroneDriver(droneAdaptor) work := func() { leftX.Store(float64(0.0)) @@ -61,20 +61,20 @@ func main() { stick.On(joystick.CirclePress, func(data interface{}) { if clawOpen { - drone.ClawControl(0, minidrone.ClawClosed) + drone.ClawControl(0, parrot.ClawClosed) clawOpen = false } else { - drone.ClawControl(0, minidrone.ClawOpen) + drone.ClawControl(0, parrot.ClawOpen) clawOpen = true } }) stick.On(joystick.R2Press, func(data interface{}) { if clawOpen { - drone.ClawControl(0, minidrone.ClawClosed) + drone.ClawControl(0, parrot.ClawClosed) clawOpen = false } else { - drone.ClawControl(0, minidrone.ClawOpen) + drone.ClawControl(0, parrot.ClawOpen) clawOpen = true } }) @@ -113,18 +113,18 @@ func main() { switch { case rightStick.y < -10: - drone.Forward(minidrone.ValidatePitch(rightStick.y, offset)) + drone.Forward(parrot.ValidatePitch(rightStick.y, offset)) case rightStick.y > 10: - drone.Backward(minidrone.ValidatePitch(rightStick.y, offset)) + drone.Backward(parrot.ValidatePitch(rightStick.y, offset)) default: drone.Forward(0) } switch { case rightStick.x > 10: - drone.Right(minidrone.ValidatePitch(rightStick.x, offset)) + drone.Right(parrot.ValidatePitch(rightStick.x, offset)) case rightStick.x < -10: - drone.Left(minidrone.ValidatePitch(rightStick.x, offset)) + drone.Left(parrot.ValidatePitch(rightStick.x, offset)) default: drone.Right(0) } @@ -134,18 +134,18 @@ func main() { leftStick := getLeftStick() switch { case leftStick.y < -10: - drone.Up(minidrone.ValidatePitch(leftStick.y, offset)) + drone.Up(parrot.ValidatePitch(leftStick.y, offset)) case leftStick.y > 10: - drone.Down(minidrone.ValidatePitch(leftStick.y, offset)) + drone.Down(parrot.ValidatePitch(leftStick.y, offset)) default: drone.Up(0) } switch { case leftStick.x > 20: - drone.Clockwise(minidrone.ValidatePitch(leftStick.x, offset)) + drone.Clockwise(parrot.ValidatePitch(leftStick.x, offset)) case leftStick.x < -20: - drone.CounterClockwise(minidrone.ValidatePitch(leftStick.x, offset)) + drone.CounterClockwise(parrot.ValidatePitch(leftStick.x, offset)) default: drone.Clockwise(0) } diff --git a/examples/minidrone_ps3.go b/examples/minidrone_ps3.go index 7afd96053..a316a3d52 100644 --- a/examples/minidrone_ps3.go +++ b/examples/minidrone_ps3.go @@ -28,9 +28,9 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble/parrot" + "gobot.io/x/gobot/v2/platforms/bleclient" "gobot.io/x/gobot/v2/platforms/joystick" - "gobot.io/x/gobot/v2/platforms/parrot/minidrone" ) type pair struct { @@ -46,8 +46,8 @@ func main() { joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") - droneAdaptor := ble.NewClientAdaptor(os.Args[1]) - drone := minidrone.NewDriver(droneAdaptor) + droneAdaptor := bleclient.NewAdaptor(os.Args[1]) + drone := parrot.NewMinidroneDriver(droneAdaptor) work := func() { leftX.Store(float64(0.0)) @@ -104,18 +104,18 @@ func main() { switch { case rightStick.y < -10: - drone.Forward(minidrone.ValidatePitch(rightStick.y, offset)) + drone.Forward(parrot.ValidatePitch(rightStick.y, offset)) case rightStick.y > 10: - drone.Backward(minidrone.ValidatePitch(rightStick.y, offset)) + drone.Backward(parrot.ValidatePitch(rightStick.y, offset)) default: drone.Forward(0) } switch { case rightStick.x > 10: - drone.Right(minidrone.ValidatePitch(rightStick.x, offset)) + drone.Right(parrot.ValidatePitch(rightStick.x, offset)) case rightStick.x < -10: - drone.Left(minidrone.ValidatePitch(rightStick.x, offset)) + drone.Left(parrot.ValidatePitch(rightStick.x, offset)) default: drone.Right(0) } @@ -125,18 +125,18 @@ func main() { leftStick := getLeftStick() switch { case leftStick.y < -10: - drone.Up(minidrone.ValidatePitch(leftStick.y, offset)) + drone.Up(parrot.ValidatePitch(leftStick.y, offset)) case leftStick.y > 10: - drone.Down(minidrone.ValidatePitch(leftStick.y, offset)) + drone.Down(parrot.ValidatePitch(leftStick.y, offset)) default: drone.Up(0) } switch { case leftStick.x > 20: - drone.Clockwise(minidrone.ValidatePitch(leftStick.x, offset)) + drone.Clockwise(parrot.ValidatePitch(leftStick.x, offset)) case leftStick.x < -20: - drone.CounterClockwise(minidrone.ValidatePitch(leftStick.x, offset)) + drone.CounterClockwise(parrot.ValidatePitch(leftStick.x, offset)) default: drone.Clockwise(0) } diff --git a/examples/sphero.go b/examples/serial_sphero.go similarity index 66% rename from examples/sphero.go rename to examples/serial_sphero.go index f876f4a10..a6d942811 100644 --- a/examples/sphero.go +++ b/examples/serial_sphero.go @@ -11,21 +11,23 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { - adaptor := sphero.NewAdaptor("/dev/rfcomm0") - spheroDriver := sphero.NewSpheroDriver(adaptor) + adaptor := serialport.NewAdaptor("/dev/rfcomm0") + spheroDriver := serial.NewSpheroDriver(adaptor) work := func() { spheroDriver.SetDataStreaming(sphero.DefaultDataStreamingConfig()) - spheroDriver.On(sphero.Collision, func(data interface{}) { + spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { fmt.Printf("Collision! %+v\n", data) }) - spheroDriver.On(sphero.SensorData, func(data interface{}) { + spheroDriver.On(sphero.SensorDataEvent, func(data interface{}) { fmt.Printf("Streaming Data! %+v\n", data) }) diff --git a/examples/sphero_api.go b/examples/serial_sphero_api.go similarity index 79% rename from examples/sphero_api.go rename to examples/serial_sphero_api.go index 0c38abcef..33607ae13 100644 --- a/examples/sphero_api.go +++ b/examples/serial_sphero_api.go @@ -9,7 +9,8 @@ package main import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { @@ -21,8 +22,8 @@ func main() { } for name, port := range spheros { - spheroAdaptor := sphero.NewAdaptor(port) - spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) + spheroAdaptor := serialport.NewAdaptor(port) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor) work := func() { spheroDriver.SetRGB(uint8(255), uint8(0), uint8(0)) diff --git a/examples/sphero_calibration.go b/examples/serial_sphero_calibration.go similarity index 85% rename from examples/sphero_calibration.go rename to examples/serial_sphero_calibration.go index d48d0542b..b0f2ae353 100644 --- a/examples/sphero_calibration.go +++ b/examples/serial_sphero_calibration.go @@ -9,8 +9,9 @@ package main import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" + "gobot.io/x/gobot/v2/drivers/serial" "gobot.io/x/gobot/v2/platforms/keyboard" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { @@ -18,8 +19,8 @@ func main() { a := api.NewAPI(master) a.Start() - ballConn := sphero.NewAdaptor("/dev/rfcomm0") - ball := sphero.NewSpheroDriver(ballConn) + ballConn := serialport.NewAdaptor("/dev/rfcomm0") + ball := serial.NewSpheroDriver(ballConn) keys := keyboard.NewDriver() diff --git a/examples/sphero_conways.go b/examples/serial_sphero_conways.go similarity index 85% rename from examples/sphero_conways.go rename to examples/serial_sphero_conways.go index 23d97fc68..5113ab5a0 100644 --- a/examples/sphero_conways.go +++ b/examples/serial_sphero_conways.go @@ -11,14 +11,16 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) type conway struct { alive bool age int contacts int - cell *sphero.SpheroDriver + cell *serial.SpheroDriver } func main() { @@ -31,9 +33,9 @@ func main() { } for _, port := range spheros { - spheroAdaptor := sphero.NewAdaptor(port) + spheroAdaptor := serialport.NewAdaptor(port) - cell := sphero.NewSpheroDriver(spheroAdaptor) + cell := serial.NewSpheroDriver(spheroAdaptor) cell.SetName("Sphero" + port) work := func() { @@ -42,7 +44,7 @@ func main() { conway.birth() - cell.On(sphero.Collision, func(data interface{}) { + cell.On(sphero.CollisionEvent, func(data interface{}) { conway.contact() }) diff --git a/examples/sphero_dpad.go b/examples/serial_sphero_dpad.go similarity index 81% rename from examples/sphero_dpad.go rename to examples/serial_sphero_dpad.go index f41c16c63..45d34293c 100644 --- a/examples/sphero_dpad.go +++ b/examples/serial_sphero_dpad.go @@ -11,7 +11,8 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { @@ -19,8 +20,8 @@ func main() { a := api.NewAPI(master) a.Start() - conn := sphero.NewAdaptor("/dev/rfcomm0") - ball := sphero.NewSpheroDriver(conn) + conn := serialport.NewAdaptor("/dev/rfcomm0") + ball := serial.NewSpheroDriver(conn) robot := gobot.NewRobot("sphero-dpad", []gobot.Connection{conn}, diff --git a/examples/sphero_master.go b/examples/serial_sphero_master.go similarity index 73% rename from examples/sphero_master.go rename to examples/serial_sphero_master.go index 19fe9b439..0c7e16f0c 100644 --- a/examples/sphero_master.go +++ b/examples/serial_sphero_master.go @@ -10,7 +10,8 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { @@ -21,8 +22,8 @@ func main() { } for name, port := range spheros { - spheroAdaptor := sphero.NewAdaptor(port) - spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) + spheroAdaptor := serialport.NewAdaptor(port) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor) work := func() { spheroDriver.SetRGB(uint8(255), uint8(0), uint8(0)) @@ -40,7 +41,7 @@ func main() { robot := gobot.NewRobot("", func() { gobot.Every(1*time.Second, func() { - sphero := master.Robot("Sphero-BPO").Device("sphero").(*sphero.SpheroDriver) + sphero := master.Robot("Sphero-BPO").Device("sphero").(*serial.SpheroDriver) sphero.SetRGB(uint8(gobot.Rand(255)), uint8(gobot.Rand(255)), uint8(gobot.Rand(255)), diff --git a/examples/sphero_multiple.go b/examples/serial_sphero_multiple.go similarity index 76% rename from examples/sphero_multiple.go rename to examples/serial_sphero_multiple.go index 5748d7718..c728ce9ff 100644 --- a/examples/sphero_multiple.go +++ b/examples/serial_sphero_multiple.go @@ -12,18 +12,20 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) func NewSwarmBot(port string) *gobot.Robot { - spheroAdaptor := sphero.NewAdaptor(port) - spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) + spheroAdaptor := serialport.NewAdaptor(port) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor) spheroDriver.SetName("Sphero" + port) work := func() { spheroDriver.Stop() - spheroDriver.On(sphero.Collision, func(data interface{}) { + spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { fmt.Println("Collision Detected!") }) diff --git a/platforms/adaptors/pwmpinsadaptoroptions.go b/platforms/adaptors/pwmpinsadaptoroptions.go index 168840470..c9ad49e69 100644 --- a/platforms/adaptors/pwmpinsadaptoroptions.go +++ b/platforms/adaptors/pwmpinsadaptoroptions.go @@ -2,7 +2,7 @@ package adaptors import "time" -// pwmPinOptionApplier needs to be implemented by each configurable option type +// PwmPinsOptionApplier needs to be implemented by each configurable option type type PwmPinsOptionApplier interface { apply(cfg *pwmPinsConfiguration) } diff --git a/platforms/ble/battery_driver.go b/platforms/ble/battery_driver.go deleted file mode 100644 index 4b3e59628..000000000 --- a/platforms/ble/battery_driver.go +++ /dev/null @@ -1,60 +0,0 @@ -package ble - -import ( - "bytes" - "log" - - "gobot.io/x/gobot/v2" -) - -// BatteryDriver represents the Battery Service for a BLE Peripheral -type BatteryDriver struct { - name string - connection gobot.Connection - gobot.Eventer -} - -// NewBatteryDriver creates a BatteryDriver -func NewBatteryDriver(a BLEConnector) *BatteryDriver { - n := &BatteryDriver{ - name: gobot.DefaultName("Battery"), - connection: a, - Eventer: gobot.NewEventer(), - } - - return n -} - -// Connection returns the Driver's Connection to the associated Adaptor -func (b *BatteryDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver name -func (b *BatteryDriver) Name() string { return b.name } - -// SetName sets the Driver name -func (b *BatteryDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *BatteryDriver) adaptor() BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *BatteryDriver) Start() error { return nil } - -// Halt stops battery driver (void) -func (b *BatteryDriver) Halt() error { return nil } - -// GetBatteryLevel reads and returns the current battery level -func (b *BatteryDriver) GetBatteryLevel() uint8 { - c, err := b.adaptor().ReadCharacteristic("2a19") - if err != nil { - log.Println(err) - return 0 - } - buf := bytes.NewBuffer(c) - val, _ := buf.ReadByte() - level := val - return level -} diff --git a/platforms/ble/battery_driver_test.go b/platforms/ble/battery_driver_test.go deleted file mode 100644 index 84e671f70..000000000 --- a/platforms/ble/battery_driver_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package ble - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" -) - -var _ gobot.Driver = (*BatteryDriver)(nil) - -func initTestBatteryDriver() *BatteryDriver { - d := NewBatteryDriver(NewBleTestAdaptor()) - return d -} - -func TestBatteryDriver(t *testing.T) { - d := initTestBatteryDriver() - assert.True(t, strings.HasPrefix(d.Name(), "Battery")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) -} - -func TestBatteryDriverStartAndHalt(t *testing.T) { - d := initTestBatteryDriver() - require.NoError(t, d.Start()) - require.NoError(t, d.Halt()) -} - -func TestBatteryDriverRead(t *testing.T) { - a := NewBleTestAdaptor() - d := NewBatteryDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte{20}, nil - }) - - assert.Equal(t, uint8(20), d.GetBatteryLevel()) -} diff --git a/platforms/ble/device_information_driver.go b/platforms/ble/device_information_driver.go deleted file mode 100644 index 79710a9df..000000000 --- a/platforms/ble/device_information_driver.go +++ /dev/null @@ -1,107 +0,0 @@ -package ble - -import ( - "bytes" - "log" - - "gobot.io/x/gobot/v2" -) - -// DeviceInformationDriver represents the Device Information Service for a BLE Peripheral -type DeviceInformationDriver struct { - name string - connection gobot.Connection - gobot.Eventer -} - -// NewDeviceInformationDriver creates a DeviceInformationDriver -func NewDeviceInformationDriver(a BLEConnector) *DeviceInformationDriver { - n := &DeviceInformationDriver{ - name: gobot.DefaultName("DeviceInformation"), - connection: a, - Eventer: gobot.NewEventer(), - } - - return n -} - -// Connection returns the Driver's Connection to the associated Adaptor -func (b *DeviceInformationDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver name -func (b *DeviceInformationDriver) Name() string { return b.name } - -// SetName sets the Driver name -func (b *DeviceInformationDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor for this device -func (b *DeviceInformationDriver) adaptor() BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *DeviceInformationDriver) Start() error { return nil } - -// Halt stops driver (void) -func (b *DeviceInformationDriver) Halt() error { return nil } - -// GetModelNumber returns the model number for the BLE Peripheral -func (b *DeviceInformationDriver) GetModelNumber() string { - c, err := b.adaptor().ReadCharacteristic("2a24") - if err != nil { - log.Println(err) - return "" - } - buf := bytes.NewBuffer(c) - model := buf.String() - return model -} - -// GetFirmwareRevision returns the firmware revision for the BLE Peripheral -func (b *DeviceInformationDriver) GetFirmwareRevision() string { - c, err := b.adaptor().ReadCharacteristic("2a26") - if err != nil { - log.Println(err) - return "" - } - buf := bytes.NewBuffer(c) - val := buf.String() - return val -} - -// GetHardwareRevision returns the hardware revision for the BLE Peripheral -func (b *DeviceInformationDriver) GetHardwareRevision() string { - c, err := b.adaptor().ReadCharacteristic("2a27") - if err != nil { - log.Println(err) - return "" - } - buf := bytes.NewBuffer(c) - val := buf.String() - return val -} - -// GetManufacturerName returns the manufacturer name for the BLE Peripheral -func (b *DeviceInformationDriver) GetManufacturerName() string { - c, err := b.adaptor().ReadCharacteristic("2a29") - if err != nil { - log.Println(err) - return "" - } - buf := bytes.NewBuffer(c) - val := buf.String() - return val -} - -// GetPnPId returns the PnP ID for the BLE Peripheral -func (b *DeviceInformationDriver) GetPnPId() string { - c, err := b.adaptor().ReadCharacteristic("2a50") - if err != nil { - log.Println(err) - return "" - } - buf := bytes.NewBuffer(c) - val := buf.String() - return val -} diff --git a/platforms/ble/device_information_driver_test.go b/platforms/ble/device_information_driver_test.go deleted file mode 100644 index 1835ce8d1..000000000 --- a/platforms/ble/device_information_driver_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package ble - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" -) - -var _ gobot.Driver = (*DeviceInformationDriver)(nil) - -func initTestDeviceInformationDriver() *DeviceInformationDriver { - d := NewDeviceInformationDriver(NewBleTestAdaptor()) - return d -} - -func TestDeviceInformationDriver(t *testing.T) { - d := initTestDeviceInformationDriver() - assert.True(t, strings.HasPrefix(d.Name(), "DeviceInformation")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) -} - -func TestDeviceInformationDriverStartAndHalt(t *testing.T) { - d := initTestDeviceInformationDriver() - require.NoError(t, d.Start()) - require.NoError(t, d.Halt()) -} - -func TestDeviceInformationDriverGetModelNumber(t *testing.T) { - a := NewBleTestAdaptor() - d := NewDeviceInformationDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte("TestDevice"), nil - }) - - assert.Equal(t, "TestDevice", d.GetModelNumber()) -} - -func TestDeviceInformationDriverGetFirmwareRevision(t *testing.T) { - a := NewBleTestAdaptor() - d := NewDeviceInformationDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte("TestDevice"), nil - }) - - assert.Equal(t, "TestDevice", d.GetFirmwareRevision()) -} - -func TestDeviceInformationDriverGetHardwareRevision(t *testing.T) { - a := NewBleTestAdaptor() - d := NewDeviceInformationDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte("TestDevice"), nil - }) - - assert.Equal(t, "TestDevice", d.GetHardwareRevision()) -} - -func TestDeviceInformationDriverGetManufacturerName(t *testing.T) { - a := NewBleTestAdaptor() - d := NewDeviceInformationDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte("TestDevice"), nil - }) - - assert.Equal(t, "TestDevice", d.GetManufacturerName()) -} - -func TestDeviceInformationDriverGetPnPId(t *testing.T) { - a := NewBleTestAdaptor() - d := NewDeviceInformationDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte("TestDevice"), nil - }) - - assert.Equal(t, "TestDevice", d.GetPnPId()) -} diff --git a/platforms/ble/doc.go b/platforms/ble/doc.go deleted file mode 100644 index 39b9e8258..000000000 --- a/platforms/ble/doc.go +++ /dev/null @@ -1,13 +0,0 @@ -/* -Package ble provides the Gobot adaptor for Bluetooth LE. - -It also includes drivers for several well-known BLE Services: - -- Battery Service -- Device Information Service -- Generic Access Service - -For more information refer to the README: -https://github.com/hybridgroup/gobot/blob/master/platforms/ble/README.md -*/ -package ble // import "gobot.io/x/gobot/v2/platforms/ble" diff --git a/platforms/ble/generic_access_driver_test.go b/platforms/ble/generic_access_driver_test.go deleted file mode 100644 index c32b3384e..000000000 --- a/platforms/ble/generic_access_driver_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package ble - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" -) - -var _ gobot.Driver = (*GenericAccessDriver)(nil) - -func initTestGenericAccessDriver() *GenericAccessDriver { - d := NewGenericAccessDriver(NewBleTestAdaptor()) - return d -} - -func TestGenericAccessDriver(t *testing.T) { - d := initTestGenericAccessDriver() - assert.True(t, strings.HasPrefix(d.Name(), "GenericAccess")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) -} - -func TestGenericAccessDriverStartAndHalt(t *testing.T) { - d := initTestGenericAccessDriver() - require.NoError(t, d.Start()) - require.NoError(t, d.Halt()) -} - -func TestGenericAccessDriverGetDeviceName(t *testing.T) { - a := NewBleTestAdaptor() - d := NewGenericAccessDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte("TestDevice"), nil - }) - - assert.Equal(t, "TestDevice", d.GetDeviceName()) -} - -func TestGenericAccessDriverGetAppearance(t *testing.T) { - a := NewBleTestAdaptor() - d := NewGenericAccessDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte{128, 0}, nil - }) - - assert.Equal(t, "Generic Computer", d.GetAppearance()) -} diff --git a/platforms/ble/helpers_test.go b/platforms/ble/helpers_test.go deleted file mode 100644 index dfcd7e36d..000000000 --- a/platforms/ble/helpers_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package ble - -import "sync" - -var _ BLEConnector = (*bleTestClientAdaptor)(nil) - -type bleTestClientAdaptor struct { - name string - address string - mtx sync.Mutex - withoutResponses bool - - testReadCharacteristic func(string) ([]byte, error) - testWriteCharacteristic func(string, []byte) error -} - -func (t *bleTestClientAdaptor) Connect() error { return nil } -func (t *bleTestClientAdaptor) Reconnect() error { return nil } -func (t *bleTestClientAdaptor) Disconnect() error { return nil } -func (t *bleTestClientAdaptor) Finalize() error { return nil } -func (t *bleTestClientAdaptor) Name() string { return t.name } -func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } -func (t *bleTestClientAdaptor) Address() string { return t.address } -func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } - -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testReadCharacteristic(cUUID) -} - -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testWriteCharacteristic(cUUID, data) -} - -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { - // TODO: implement this... - return nil -} - -func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testReadCharacteristic = f -} - -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testWriteCharacteristic = f -} - -func NewBleTestAdaptor() *bleTestClientAdaptor { - return &bleTestClientAdaptor{ - address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) ([]byte, error) { - return []byte{}, nil - }, - testWriteCharacteristic: func(cUUID string, data []byte) error { - return nil - }, - } -} diff --git a/platforms/ble/serial_port.go b/platforms/ble/serial_port.go deleted file mode 100644 index 4cbfedbe6..000000000 --- a/platforms/ble/serial_port.go +++ /dev/null @@ -1,77 +0,0 @@ -package ble - -import "sync" - -// SerialPort is a implementation of serial over Bluetooth LE -// Inspired by https://github.com/monteslu/ble-serial by @monteslu -type SerialPort struct { - address string - rid string - tid string - client *ClientAdaptor - - // buffer of responseData and mutex to protect it - responseData []byte - responseMutex sync.Mutex -} - -// NewSerialPort returns a new serial over Bluetooth LE connection -func NewSerialPort(address string, rid string, tid string) *SerialPort { - return &SerialPort{address: address, rid: rid, tid: tid} -} - -// Open opens a connection to a BLE serial device -func (p *SerialPort) Open() error { - p.client = NewClientAdaptor(p.address) - - if err := p.client.Connect(); err != nil { - return err - } - - // subscribe to response notifications - return p.client.Subscribe(p.rid, func(data []byte, e error) { - p.responseMutex.Lock() - p.responseData = append(p.responseData, data...) - p.responseMutex.Unlock() - }) -} - -// Read reads bytes from BLE serial port connection -func (p *SerialPort) Read(b []byte) (int, error) { - if len(p.responseData) == 0 { - return 0, nil - } - - p.responseMutex.Lock() - n := len(b) - if len(p.responseData) < n { - n = len(p.responseData) - } - copy(b, p.responseData[:n]) - - if len(p.responseData) > n { - p.responseData = p.responseData[n:] - } else { - p.responseData = nil - } - p.responseMutex.Unlock() - - return n, nil -} - -// Write writes to the BLE serial port connection -func (p *SerialPort) Write(b []byte) (int, error) { - err := p.client.WriteCharacteristic(p.tid, b) - n := len(b) - return n, err -} - -// Close closes the BLE serial port connection -func (p *SerialPort) Close() error { - return p.client.Disconnect() -} - -// Address returns the BLE address -func (p *SerialPort) Address() string { - return p.address -} diff --git a/platforms/ble/serial_port_test.go b/platforms/ble/serial_port_test.go deleted file mode 100644 index 47dc87cdb..000000000 --- a/platforms/ble/serial_port_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package ble - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func initTestBLESerialPort() *SerialPort { - return NewSerialPort("TEST123", "123", "456") -} - -func TestBLESerialPort(t *testing.T) { - d := initTestBLESerialPort() - assert.Equal(t, "TEST123", d.Address()) -} diff --git a/platforms/ble/LICENSE b/platforms/bleclient/LICENSE similarity index 100% rename from platforms/ble/LICENSE rename to platforms/bleclient/LICENSE diff --git a/platforms/ble/README.md b/platforms/bleclient/README.md similarity index 85% rename from platforms/ble/README.md rename to platforms/bleclient/README.md index 5871bd6fe..c243cf7a7 100644 --- a/platforms/ble/README.md +++ b/platforms/bleclient/README.md @@ -2,15 +2,11 @@ The Gobot BLE adaptor makes it easy to interact with Bluetooth LE aka Bluetooth 4.0 using Go. -It is written using the [TinyGo Bluetooh](tinygo.org/x/bluetooth) package. +It is written using the [TinyGo Bluetooth](tinygo.org/x/bluetooth) package. Learn more about Bluetooth LE at -This package also includes drivers for several well-known BLE Services: - -- Battery Service -- Device Information Service -- Generic Access Service +Drivers for several BLE Services can be found in the according [driver folder](https://github.com/hybridgroup/gobot/tree/release/drivers/ble). ## How to Install @@ -65,11 +61,12 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/platforms/bleclient" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) battery := ble.NewBatteryDriver(bleAdaptor) work := func() { diff --git a/platforms/ble/ble_client_adaptor.go b/platforms/bleclient/ble_client_adaptor.go similarity index 63% rename from platforms/ble/ble_client_adaptor.go rename to platforms/bleclient/ble_client_adaptor.go index 8273e1c94..f73605930 100644 --- a/platforms/ble/ble_client_adaptor.go +++ b/platforms/bleclient/ble_client_adaptor.go @@ -1,4 +1,4 @@ -package ble +package bleclient import ( "fmt" @@ -16,22 +16,8 @@ var ( bleMutex sync.Mutex ) -// BLEConnector is the interface that a BLE ClientAdaptor must implement -type BLEConnector interface { - gobot.Adaptor - - Reconnect() error - Disconnect() error - Address() string - - ReadCharacteristic(cUUID string) ([]byte, error) - WriteCharacteristic(cUUID string, data []byte) error - Subscribe(cUUID string, f func([]byte, error)) error - WithoutResponses(use bool) -} - -// ClientAdaptor represents a Client Connection to a BLE Peripheral -type ClientAdaptor struct { +// Adaptor represents a client connection to a BLE Peripheral +type Adaptor struct { name string address string AdapterName string @@ -45,9 +31,9 @@ type ClientAdaptor struct { withoutResponses bool } -// NewClientAdaptor returns a new ClientAdaptor given an address -func NewClientAdaptor(address string) *ClientAdaptor { - return &ClientAdaptor{ +// NewAdaptor returns a new Bluetooth LE client adaptor given an address +func NewAdaptor(address string) *Adaptor { + return &Adaptor{ name: gobot.DefaultName("BLEClient"), address: address, AdapterName: "default", @@ -58,41 +44,41 @@ func NewClientAdaptor(address string) *ClientAdaptor { } // Name returns the name for the adaptor -func (b *ClientAdaptor) Name() string { return b.name } +func (a *Adaptor) Name() string { return a.name } // SetName sets the name for the adaptor -func (b *ClientAdaptor) SetName(n string) { b.name = n } +func (a *Adaptor) SetName(n string) { a.name = n } // Address returns the Bluetooth LE address for the adaptor -func (b *ClientAdaptor) Address() string { return b.address } +func (a *Adaptor) Address() string { return a.address } // WithoutResponses sets if the adaptor should expect responses after // writing characteristics for this device -func (b *ClientAdaptor) WithoutResponses(use bool) { b.withoutResponses = use } +func (a *Adaptor) WithoutResponses(use bool) { a.withoutResponses = use } // Connect initiates a connection to the BLE peripheral. Returns true on successful connection. -func (b *ClientAdaptor) Connect() error { +func (a *Adaptor) Connect() error { bleMutex.Lock() defer bleMutex.Unlock() var err error // enable adaptor - b.adpt, err = getBLEAdapter(b.AdapterName) + a.adpt, err = getBLEAdapter(a.AdapterName) if err != nil { - return fmt.Errorf("can't get adapter %s: %w", b.AdapterName, err) + return fmt.Errorf("can't get adapter %s: %w", a.AdapterName, err) } // handle address - b.addr.Set(b.Address()) + a.addr.Set(a.Address()) // scan for the address ch := make(chan bluetooth.ScanResult, 1) - err = b.adpt.Scan(func(adapter *bluetooth.Adapter, result bluetooth.ScanResult) { - if result.Address.String() == b.Address() { - if err := b.adpt.StopScan(); err != nil { + err = a.adpt.Scan(func(adapter *bluetooth.Adapter, result bluetooth.ScanResult) { + if result.Address.String() == a.Address() { + if err := a.adpt.StopScan(); err != nil { panic(err) } - b.SetName(result.LocalName()) + a.SetName(result.LocalName()) ch <- result } }) @@ -103,13 +89,13 @@ func (b *ClientAdaptor) Connect() error { // wait to connect to peripheral device result := <-ch - b.device, err = b.adpt.Connect(result.Address, bluetooth.ConnectionParams{}) + a.device, err = a.adpt.Connect(result.Address, bluetooth.ConnectionParams{}) if err != nil { return err } // get all services/characteristics - srvcs, err := b.device.DiscoverServices(nil) + srvcs, err := a.device.DiscoverServices(nil) if err != nil { return err } @@ -120,48 +106,48 @@ func (b *ClientAdaptor) Connect() error { continue } for _, char := range chars { - b.characteristics[char.UUID().String()] = char + a.characteristics[char.UUID().String()] = char } } - b.connected = true + a.connected = true return nil } // Reconnect attempts to reconnect to the BLE peripheral. If it has an active connection // it will first close that connection and then establish a new connection. // Returns true on Successful reconnection -func (b *ClientAdaptor) Reconnect() error { - if b.connected { - if err := b.Disconnect(); err != nil { +func (a *Adaptor) Reconnect() error { + if a.connected { + if err := a.Disconnect(); err != nil { return err } } - return b.Connect() + return a.Connect() } // Disconnect terminates the connection to the BLE peripheral. Returns true on successful disconnect. -func (b *ClientAdaptor) Disconnect() error { - err := b.device.Disconnect() +func (a *Adaptor) Disconnect() error { + err := a.device.Disconnect() time.Sleep(500 * time.Millisecond) return err } // Finalize finalizes the BLEAdaptor -func (b *ClientAdaptor) Finalize() error { - return b.Disconnect() +func (a *Adaptor) Finalize() error { + return a.Disconnect() } // ReadCharacteristic returns bytes from the BLE device for the // requested characteristic uuid -func (b *ClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { - if !b.connected { +func (a *Adaptor) ReadCharacteristic(cUUID string) ([]byte, error) { + if !a.connected { return nil, fmt.Errorf("Cannot read from BLE device until connected") } cUUID = convertUUID(cUUID) - if char, ok := b.characteristics[cUUID]; ok { + if char, ok := a.characteristics[cUUID]; ok { buf := make([]byte, 255) n, err := char.Read(buf) if err != nil { @@ -175,14 +161,14 @@ func (b *ClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { // WriteCharacteristic writes bytes to the BLE device for the // requested service and characteristic -func (b *ClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { - if !b.connected { +func (a *Adaptor) WriteCharacteristic(cUUID string, data []byte) error { + if !a.connected { return fmt.Errorf("Cannot write to BLE device until connected") } cUUID = convertUUID(cUUID) - if char, ok := b.characteristics[cUUID]; ok { + if char, ok := a.characteristics[cUUID]; ok { _, err := char.WriteWithoutResponse(data) if err != nil { return err @@ -195,14 +181,14 @@ func (b *ClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { // Subscribe subscribes to notifications from the BLE device for the // requested service and characteristic -func (b *ClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { - if !b.connected { +func (a *Adaptor) Subscribe(cUUID string, f func([]byte, error)) error { + if !a.connected { return fmt.Errorf("Cannot subscribe to BLE device until connected") } cUUID = convertUUID(cUUID) - if char, ok := b.characteristics[cUUID]; ok { + if char, ok := a.characteristics[cUUID]; ok { fn := func(d []byte) { f(d, nil) } diff --git a/platforms/ble/ble_client_adaptor_test.go b/platforms/bleclient/ble_client_adaptor_test.go similarity index 52% rename from platforms/ble/ble_client_adaptor_test.go rename to platforms/bleclient/ble_client_adaptor_test.go index 0862405e8..2364e9aa7 100644 --- a/platforms/ble/ble_client_adaptor_test.go +++ b/platforms/bleclient/ble_client_adaptor_test.go @@ -1,4 +1,4 @@ -package ble +package bleclient import ( "strings" @@ -9,16 +9,19 @@ import ( "gobot.io/x/gobot/v2" ) -var _ gobot.Adaptor = (*ClientAdaptor)(nil) +var ( + _ gobot.Adaptor = (*Adaptor)(nil) + _ gobot.BLEConnector = (*Adaptor)(nil) +) -func TestBLEClientAdaptor(t *testing.T) { - a := NewClientAdaptor("D7:99:5A:26:EC:38") +func TestNewAdaptor(t *testing.T) { + a := NewAdaptor("D7:99:5A:26:EC:38") assert.Equal(t, "D7:99:5A:26:EC:38", a.Address()) assert.True(t, strings.HasPrefix(a.Name(), "BLEClient")) } -func TestBLEClientAdaptorName(t *testing.T) { - a := NewClientAdaptor("D7:99:5A:26:EC:38") +func TestName(t *testing.T) { + a := NewAdaptor("D7:99:5A:26:EC:38") a.SetName("awesome") assert.Equal(t, "awesome", a.Name()) } diff --git a/platforms/bleclient/doc.go b/platforms/bleclient/doc.go new file mode 100644 index 000000000..b6ba3d1c0 --- /dev/null +++ b/platforms/bleclient/doc.go @@ -0,0 +1,7 @@ +/* +Package bleclient provides the Gobot client adaptor for Bluetooth LE. + +For more information refer to the README: +https://github.com/hybridgroup/gobot/blob/master/platforms/bleclient/README.md +*/ +package bleclient // import "gobot.io/x/gobot/v2/platforms/bleclient" diff --git a/platforms/ble/uuid.go b/platforms/bleclient/uuid.go similarity index 96% rename from platforms/ble/uuid.go rename to platforms/bleclient/uuid.go index da0c47f6f..bf120fbe7 100644 --- a/platforms/ble/uuid.go +++ b/platforms/bleclient/uuid.go @@ -1,4 +1,4 @@ -package ble +package bleclient import ( "fmt" diff --git a/platforms/firmata/ble_firmata_adaptor.go b/platforms/firmata/ble_firmata_adaptor.go index 7150b8de5..1c4f1856a 100644 --- a/platforms/firmata/ble_firmata_adaptor.go +++ b/platforms/firmata/ble_firmata_adaptor.go @@ -7,7 +7,8 @@ import ( "io" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" + "gobot.io/x/gobot/v2/drivers/ble" + "gobot.io/x/gobot/v2/platforms/bleclient" ) const ( @@ -40,7 +41,8 @@ func NewBLEAdaptor(args ...interface{}) *BLEAdaptor { a := NewAdaptor(address) a.SetName(gobot.DefaultName("BLEFirmata")) a.PortOpener = func(port string) (io.ReadWriteCloser, error) { - sp := ble.NewSerialPort(address, rid, wid) + a := bleclient.NewAdaptor(address) + sp := ble.NewSerialPortDriver(a, rid, wid) if err := sp.Open(); err != nil { return sp, err } diff --git a/platforms/microbit/README.md b/platforms/microbit/README.md index f4342e64c..b95e086a2 100644 --- a/platforms/microbit/README.md +++ b/platforms/microbit/README.md @@ -28,14 +28,9 @@ however you do not need this source code to install the firmware using the insta ## How to Use -The Gobot platform for the Microbit includes several different drivers, each one corresponding to a different capability: - -- AccelerometerDriver -- ButtonDriver -- IOPinDriver -- LEDDriver -- MagnetometerDriver -- TemperatureDriver +The Gobot package for the Microbit includes several [different drivers](https://github.com/hybridgroup/gobot/blob/release/drivers/ble/README.md). +The platform itself is represented by the generic Bluetooth LE [Client adaptor](https://github.com/hybridgroup/gobot/blob/release/platforms/bleclient/ble_client_adaptor.go), +see examples below. The following example uses the LEDDriver: @@ -47,12 +42,12 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" + "gobot.io/x/gobot/v2/drivers/ble/microbit" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewLEDDriver(bleAdaptor) work := func() { @@ -89,12 +84,12 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/microbit" + "gobot.io/x/gobot/v2/platforms/bleclient" + "gobot.io/x/gobot/v2/drivers/ble/microbit" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) ubit := microbit.NewIOPinDriver(bleAdaptor) button := gpio.NewButtonDriver(ubit, "0") diff --git a/platforms/microbit/accelerometer_driver.go b/platforms/microbit/accelerometer_driver.go deleted file mode 100644 index 76dda8fc3..000000000 --- a/platforms/microbit/accelerometer_driver.go +++ /dev/null @@ -1,97 +0,0 @@ -package microbit - -import ( - "bytes" - "encoding/binary" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" -) - -// AccelerometerDriver is the Gobot driver for the Microbit's built-in accelerometer -type AccelerometerDriver struct { - name string - connection gobot.Connection - gobot.Eventer -} - -type RawAccelerometerData struct { - X int16 - Y int16 - Z int16 -} - -type AccelerometerData struct { - X float32 - Y float32 - Z float32 -} - -const ( - // BLE services - // accelerometerService = "e95d0753251d470aa062fa1922dfa9a8" - - // BLE characteristics - accelerometerCharacteristic = "e95dca4b251d470aa062fa1922dfa9a8" - - // Accelerometer event - Accelerometer = "accelerometer" -) - -// NewAccelerometerDriver creates a Microbit AccelerometerDriver -func NewAccelerometerDriver(a ble.BLEConnector) *AccelerometerDriver { - n := &AccelerometerDriver{ - name: gobot.DefaultName("Microbit Accelerometer"), - connection: a, - Eventer: gobot.NewEventer(), - } - - n.AddEvent(Accelerometer) - - return n -} - -// Connection returns the BLE connection -func (b *AccelerometerDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver Name -func (b *AccelerometerDriver) Name() string { return b.name } - -// SetName sets the Driver Name -func (b *AccelerometerDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *AccelerometerDriver) adaptor() ble.BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(ble.BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *AccelerometerDriver) Start() error { - // subscribe to accelerometer notifications - return b.adaptor().Subscribe(accelerometerCharacteristic, func(data []byte, e error) { - a := &RawAccelerometerData{X: 0, Y: 0, Z: 0} - - buf := bytes.NewBuffer(data) - if err := binary.Read(buf, binary.LittleEndian, &a.X); err != nil { - panic(err) - } - if err := binary.Read(buf, binary.LittleEndian, &a.Y); err != nil { - panic(err) - } - if err := binary.Read(buf, binary.LittleEndian, &a.Z); err != nil { - panic(err) - } - - result := &AccelerometerData{ - X: float32(a.X) / 1000.0, - Y: float32(a.Y) / 1000.0, - Z: float32(a.Z) / 1000.0, - } - - b.Publish(b.Event(Accelerometer), result) - }) -} - -// Halt stops LED driver (void) -func (b *AccelerometerDriver) Halt() error { return nil } diff --git a/platforms/microbit/button_driver.go b/platforms/microbit/button_driver.go deleted file mode 100644 index 35a17bbfb..000000000 --- a/platforms/microbit/button_driver.go +++ /dev/null @@ -1,75 +0,0 @@ -package microbit - -import ( - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" -) - -// ButtonDriver is the Gobot driver for the Microbit's built-in buttons -type ButtonDriver struct { - name string - connection gobot.Connection - gobot.Eventer -} - -const ( - // BLE services - // buttonService = "e95d9882251d470aa062fa1922dfa9a8" - - // BLE characteristics - buttonACharacteristic = "e95dda90251d470aa062fa1922dfa9a8" - buttonBCharacteristic = "e95dda91251d470aa062fa1922dfa9a8" - - // ButtonA event - ButtonA = "buttonA" - - // ButtonB event - ButtonB = "buttonB" -) - -// NewButtonDriver creates a Microbit ButtonDriver -func NewButtonDriver(a ble.BLEConnector) *ButtonDriver { - n := &ButtonDriver{ - name: gobot.DefaultName("Microbit Button"), - connection: a, - Eventer: gobot.NewEventer(), - } - - n.AddEvent(ButtonA) - n.AddEvent(ButtonB) - - return n -} - -// Connection returns the BLE connection -func (b *ButtonDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver Name -func (b *ButtonDriver) Name() string { return b.name } - -// SetName sets the Driver Name -func (b *ButtonDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *ButtonDriver) adaptor() ble.BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(ble.BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *ButtonDriver) Start() error { - // subscribe to button A notifications - if err := b.adaptor().Subscribe(buttonACharacteristic, func(data []byte, e error) { - b.Publish(b.Event(ButtonA), data) - }); err != nil { - return err - } - - // subscribe to button B notifications - return b.adaptor().Subscribe(buttonBCharacteristic, func(data []byte, e error) { - b.Publish(b.Event(ButtonB), data) - }) -} - -// Halt stops LED driver (void) -func (b *ButtonDriver) Halt() error { return nil } diff --git a/platforms/microbit/doc.go b/platforms/microbit/doc.go index e97b9f952..334516bcc 100644 --- a/platforms/microbit/doc.go +++ b/platforms/microbit/doc.go @@ -2,6 +2,6 @@ Package microbit contains the Gobot drivers for the Microbit. For more information refer to the microbit README: -https://github.com/hybridgroup/gobot/blob/master/platforms/microbit/README.md +https://github.com/hybridgroup/gobot/blob/release/drivers/ble/microbit/README.md */ -package microbit // import "gobot.io/x/gobot/v2/platforms/microbit" +package microbit // import "gobot.io/x/gobot/v2/drivers/ble/microbit" diff --git a/platforms/microbit/io_pin_driver.go b/platforms/microbit/io_pin_driver.go deleted file mode 100644 index b57a11027..000000000 --- a/platforms/microbit/io_pin_driver.go +++ /dev/null @@ -1,272 +0,0 @@ -package microbit - -import ( - "bytes" - "encoding/binary" - "errors" - "strconv" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" -) - -// IOPinDriver is the Gobot driver for the Microbit's built-in digital and -// analog I/O -type IOPinDriver struct { - name string - adMask int - ioMask int - connection gobot.Connection - gobot.Eventer -} - -const ( - // BLE services - // ioPinService = "e95d127b251d470aa062fa1922dfa9a8" - - // BLE characteristics - pinDataCharacteristic = "e95d8d00251d470aa062fa1922dfa9a8" - pinADConfigCharacteristic = "e95d5899251d470aa062fa1922dfa9a8" - pinIOConfigCharacteristic = "e95db9fe251d470aa062fa1922dfa9a8" -) - -// PinData has the read data for a specific digital pin -type PinData struct { - pin uint8 - value uint8 -} - -// NewIOPinDriver creates a Microbit IOPinDriver -func NewIOPinDriver(a ble.BLEConnector) *IOPinDriver { - n := &IOPinDriver{ - name: gobot.DefaultName("Microbit IO Pins"), - connection: a, - Eventer: gobot.NewEventer(), - } - - return n -} - -// Connection returns the BLE connection -func (b *IOPinDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver Name -func (b *IOPinDriver) Name() string { return b.name } - -// SetName sets the Driver Name -func (b *IOPinDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *IOPinDriver) adaptor() ble.BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(ble.BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *IOPinDriver) Start() error { - if _, err := b.ReadPinADConfig(); err != nil { - return err - } - _, err := b.ReadPinIOConfig() - return err -} - -// Halt stops driver (void) -func (b *IOPinDriver) Halt() error { return nil } - -// ReadAllPinData reads and returns the pin data for all pins -func (b *IOPinDriver) ReadAllPinData() []PinData { - c, _ := b.adaptor().ReadCharacteristic(pinDataCharacteristic) - buf := bytes.NewBuffer(c) - pinsData := make([]PinData, buf.Len()/2) - - for i := 0; i < buf.Len()/2; i++ { - pinData := PinData{} - pinData.pin, _ = buf.ReadByte() - pinData.value, _ = buf.ReadByte() - pinsData[i] = pinData - } - - return pinsData -} - -// WritePinData writes the pin data for a single pin -func (b *IOPinDriver) WritePinData(pin string, data byte) error { - i, err := strconv.Atoi(pin) - if err != nil { - return err - } - - buf := []byte{byte(i), data} - err = b.adaptor().WriteCharacteristic(pinDataCharacteristic, buf) - return err -} - -// ReadPinADConfig reads and returns the pin A/D config mask for all pins -func (b *IOPinDriver) ReadPinADConfig() (int, error) { - c, err := b.adaptor().ReadCharacteristic(pinADConfigCharacteristic) - if err != nil { - return 0, err - } - var result byte - for i := 0; i < 4; i++ { - result |= c[i] << uint(i) - } - - b.adMask = int(result) - return int(result), nil -} - -// WritePinADConfig writes the pin A/D config mask for all pins -func (b *IOPinDriver) WritePinADConfig(config int) error { - b.adMask = config - data := &bytes.Buffer{} - if err := binary.Write(data, binary.LittleEndian, uint32(config)); err != nil { - return err - } - - return b.adaptor().WriteCharacteristic(pinADConfigCharacteristic, data.Bytes()) -} - -// ReadPinIOConfig reads and returns the pin IO config mask for all pins -func (b *IOPinDriver) ReadPinIOConfig() (int, error) { - c, err := b.adaptor().ReadCharacteristic(pinIOConfigCharacteristic) - if err != nil { - return 0, err - } - - var result byte - for i := 0; i < 4; i++ { - result |= c[i] << uint(i) - } - - b.ioMask = int(result) - return int(result), nil -} - -// WritePinIOConfig writes the pin I/O config mask for all pins -func (b *IOPinDriver) WritePinIOConfig(config int) error { - b.ioMask = config - data := &bytes.Buffer{} - if err := binary.Write(data, binary.LittleEndian, uint32(config)); err != nil { - return err - } - - return b.adaptor().WriteCharacteristic(pinIOConfigCharacteristic, data.Bytes()) -} - -// DigitalRead reads from a pin -func (b *IOPinDriver) DigitalRead(pin string) (int, error) { - p, err := validatedPin(pin) - if err != nil { - return 0, err - } - - if err := b.ensureDigital(p); err != nil { - return 0, err - } - if err := b.ensureInput(p); err != nil { - return 0, err - } - - pins := b.ReadAllPinData() - return int(pins[p].value), nil -} - -// DigitalWrite writes to a pin -func (b *IOPinDriver) DigitalWrite(pin string, level byte) error { - p, err := validatedPin(pin) - if err != nil { - return err - } - - if err := b.ensureDigital(p); err != nil { - return err - } - if err := b.ensureOutput(p); err != nil { - return err - } - - return b.WritePinData(pin, level) -} - -// AnalogRead reads from a pin -func (b *IOPinDriver) AnalogRead(pin string) (int, error) { - p, err := validatedPin(pin) - if err != nil { - return 0, err - } - - if err := b.ensureAnalog(p); err != nil { - return 0, err - } - if err := b.ensureInput(p); err != nil { - return 0, err - } - - pins := b.ReadAllPinData() - return int(pins[p].value), nil -} - -func (b *IOPinDriver) ensureDigital(pin int) error { - if hasBit(b.adMask, pin) { - return b.WritePinADConfig(clearBit(b.adMask, pin)) - } - - return nil -} - -func (b *IOPinDriver) ensureAnalog(pin int) error { - if !hasBit(b.adMask, pin) { - return b.WritePinADConfig(setBit(b.adMask, pin)) - } - - return nil -} - -func (b *IOPinDriver) ensureInput(pin int) error { - if !hasBit(b.ioMask, pin) { - return b.WritePinIOConfig(setBit(b.ioMask, pin)) - } - - return nil -} - -func (b *IOPinDriver) ensureOutput(pin int) error { - if hasBit(b.ioMask, pin) { - return b.WritePinIOConfig(clearBit(b.ioMask, pin)) - } - - return nil -} - -func validatedPin(pin string) (int, error) { - i, err := strconv.Atoi(pin) - if err != nil { - return 0, err - } - - if i < 0 || i > 2 { - return 0, errors.New("Invalid pin.") - } - - return i, nil -} - -// via http://stackoverflow.com/questions/23192262/how-would-you-set-and-clear-a-single-bit-in-go -// Sets the bit at pos in the integer n. -func setBit(n int, pos int) int { - n |= (1 << uint(pos)) - return n -} - -// Test if the bit at pos is set in the integer n. -func hasBit(n int, pos int) bool { - val := n & (1 << uint(pos)) - return (val > 0) -} - -// Clears the bit at pos in n. -func clearBit(n int, pos int) int { - return n &^ (1 << uint(pos)) -} diff --git a/platforms/microbit/io_pin_driver_test.go b/platforms/microbit/io_pin_driver_test.go deleted file mode 100644 index db8b3e158..000000000 --- a/platforms/microbit/io_pin_driver_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package microbit - -import ( - "errors" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/aio" - "gobot.io/x/gobot/v2/drivers/gpio" -) - -// the IOPinDriver is a Driver -var _ gobot.Driver = (*IOPinDriver)(nil) - -// that supports the DigitalReader, DigitalWriter, & AnalogReader interfaces -var ( - _ gpio.DigitalReader = (*IOPinDriver)(nil) - _ gpio.DigitalWriter = (*IOPinDriver)(nil) - _ aio.AnalogReader = (*IOPinDriver)(nil) -) - -func initTestIOPinDriver() *IOPinDriver { - d := NewIOPinDriver(NewBleTestAdaptor()) - return d -} - -func TestIOPinDriver(t *testing.T) { - d := initTestIOPinDriver() - assert.True(t, strings.HasPrefix(d.Name(), "Microbit IO Pin")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) -} - -func TestIOPinDriverStartAndHalt(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte{0, 1, 1, 0}, nil - }) - require.NoError(t, d.Start()) - require.NoError(t, d.Halt()) -} - -func TestIOPinDriverStartError(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return nil, errors.New("read error") - }) - require.ErrorContains(t, d.Start(), "read error") -} - -func TestIOPinDriverDigitalRead(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte{0, 1, 1, 0, 2, 1}, nil - }) - - val, _ := d.DigitalRead("0") - assert.Equal(t, 1, val) - - val, _ = d.DigitalRead("1") - assert.Equal(t, 0, val) -} - -func TestIOPinDriverDigitalReadInvalidPin(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - - _, err := d.DigitalRead("A3") - require.Error(t, err) - - _, err = d.DigitalRead("6") - require.ErrorContains(t, err, "Invalid pin.") -} - -func TestIOPinDriverDigitalWrite(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - - // TODO: a better test - require.NoError(t, d.DigitalWrite("0", 1)) -} - -func TestIOPinDriverDigitalWriteInvalidPin(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - - require.Error(t, d.DigitalWrite("A3", 1)) - require.ErrorContains(t, d.DigitalWrite("6", 1), "Invalid pin.") -} - -func TestIOPinDriverAnalogRead(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte{0, 0, 1, 128, 2, 1}, nil - }) - - val, _ := d.AnalogRead("0") - assert.Equal(t, 0, val) - - val, _ = d.AnalogRead("1") - assert.Equal(t, 128, val) -} - -func TestIOPinDriverAnalogReadInvalidPin(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - - _, err := d.AnalogRead("A3") - require.Error(t, err) - - _, err = d.AnalogRead("6") - require.ErrorContains(t, err, "Invalid pin.") -} - -func TestIOPinDriverDigitalAnalogRead(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte{0, 0, 1, 128, 2, 1}, nil - }) - - val, _ := d.DigitalRead("0") - assert.Equal(t, 0, val) - - val, _ = d.AnalogRead("0") - assert.Equal(t, 0, val) -} - -func TestIOPinDriverDigitalWriteAnalogRead(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte{0, 0, 1, 128, 2, 1}, nil - }) - - require.NoError(t, d.DigitalWrite("1", 0)) - - val, _ := d.AnalogRead("1") - assert.Equal(t, 128, val) -} - -func TestIOPinDriverAnalogReadDigitalWrite(t *testing.T) { - a := NewBleTestAdaptor() - d := NewIOPinDriver(a) - a.TestReadCharacteristic(func(cUUID string) ([]byte, error) { - return []byte{0, 0, 1, 128, 2, 1}, nil - }) - - val, _ := d.AnalogRead("1") - assert.Equal(t, 128, val) - - require.NoError(t, d.DigitalWrite("1", 0)) -} diff --git a/platforms/microbit/magnetometer_driver.go b/platforms/microbit/magnetometer_driver.go deleted file mode 100644 index fa89d7403..000000000 --- a/platforms/microbit/magnetometer_driver.go +++ /dev/null @@ -1,97 +0,0 @@ -package microbit - -import ( - "bytes" - "encoding/binary" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" -) - -// MagnetometerDriver is the Gobot driver for the Microbit's built-in magnetometer -type MagnetometerDriver struct { - name string - connection gobot.Connection - gobot.Eventer -} - -type RawMagnetometerData struct { - X int16 - Y int16 - Z int16 -} - -type MagnetometerData struct { - X float32 - Y float32 - Z float32 -} - -const ( - // BLE services - // magnetometerService = "e95df2d8251d470aa062fa1922dfa9a8" - - // BLE characteristics - magnetometerCharacteristic = "e95dfb11251d470aa062fa1922dfa9a8" - - // Magnetometer event - Magnetometer = "magnetometer" -) - -// NewMagnetometerDriver creates a Microbit MagnetometerDriver -func NewMagnetometerDriver(a ble.BLEConnector) *MagnetometerDriver { - n := &MagnetometerDriver{ - name: gobot.DefaultName("Microbit Magnetometer"), - connection: a, - Eventer: gobot.NewEventer(), - } - - n.AddEvent(Magnetometer) - - return n -} - -// Connection returns the BLE connection -func (b *MagnetometerDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver Name -func (b *MagnetometerDriver) Name() string { return b.name } - -// SetName sets the Driver Name -func (b *MagnetometerDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *MagnetometerDriver) adaptor() ble.BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(ble.BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *MagnetometerDriver) Start() error { - // subscribe to magnetometer notifications - return b.adaptor().Subscribe(magnetometerCharacteristic, func(data []byte, e error) { - a := &RawMagnetometerData{X: 0, Y: 0, Z: 0} - - buf := bytes.NewBuffer(data) - if err := binary.Read(buf, binary.LittleEndian, &a.X); err != nil { - panic(err) - } - if err := binary.Read(buf, binary.LittleEndian, &a.Y); err != nil { - panic(err) - } - if err := binary.Read(buf, binary.LittleEndian, &a.Z); err != nil { - panic(err) - } - - result := &MagnetometerData{ - X: float32(a.X) / 1000.0, - Y: float32(a.Y) / 1000.0, - Z: float32(a.Z) / 1000.0, - } - - b.Publish(b.Event(Magnetometer), result) - }) -} - -// Halt stops LED driver (void) -func (b *MagnetometerDriver) Halt() error { return nil } diff --git a/platforms/microbit/temperature_driver.go b/platforms/microbit/temperature_driver.go deleted file mode 100644 index e8eaab283..000000000 --- a/platforms/microbit/temperature_driver.go +++ /dev/null @@ -1,70 +0,0 @@ -package microbit - -import ( - "bytes" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" -) - -// TemperatureDriver is the Gobot driver for the Microbit's built-in thermometer -type TemperatureDriver struct { - name string - connection gobot.Connection - gobot.Eventer -} - -const ( - // BLE services - // temperatureService = "e95d6100251d470aa062fa1922dfa9a8" - - // BLE characteristics - temperatureCharacteristic = "e95d9250251d470aa062fa1922dfa9a8" - - // Temperature event - Temperature = "temperature" -) - -// NewTemperatureDriver creates a Microbit TemperatureDriver -func NewTemperatureDriver(a ble.BLEConnector) *TemperatureDriver { - n := &TemperatureDriver{ - name: gobot.DefaultName("Microbit Temperature"), - connection: a, - Eventer: gobot.NewEventer(), - } - - n.AddEvent(Temperature) - - return n -} - -// Connection returns the BLE connection -func (b *TemperatureDriver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver Name -func (b *TemperatureDriver) Name() string { return b.name } - -// SetName sets the Driver Name -func (b *TemperatureDriver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *TemperatureDriver) adaptor() ble.BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(ble.BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *TemperatureDriver) Start() error { - // subscribe to temperature notifications - return b.adaptor().Subscribe(temperatureCharacteristic, func(data []byte, e error) { - var l int8 - buf := bytes.NewBuffer(data) - val, _ := buf.ReadByte() - l = int8(val) - - b.Publish(b.Event(Temperature), l) - }) -} - -// Halt stops Temperature driver (void) -func (b *TemperatureDriver) Halt() error { return nil } diff --git a/platforms/parrot/README.md b/platforms/parrot/README.md index 1ed4dd144..52c89877e 100644 --- a/platforms/parrot/README.md +++ b/platforms/parrot/README.md @@ -3,6 +3,7 @@ This package contains the Gobot adaptors and drivers for the various Parrot (https://www.parrot.com) drones. This package currently supports the following drones: + - Parrot ARDrone 2.0 - Parrot Bebop/Bebop 2 - Parrot Minidrone diff --git a/platforms/parrot/minidrone/README.md b/platforms/parrot/minidrone/README.md index 279d458dc..dc03a75b7 100644 --- a/platforms/parrot/minidrone/README.md +++ b/platforms/parrot/minidrone/README.md @@ -36,13 +36,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/parrot/minidrone" + "gobot.io/x/gobot/v2/platforms/bleclient" + "gobot.io/x/gobot/v2/drivers/ble/parrot" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - drone := minidrone.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + drone := parrot.NewMinidroneDriver(bleAdaptor) work := func() { drone.On(minidrone.Battery, func(data interface{}) { diff --git a/platforms/parrot/minidrone/doc.go b/platforms/parrot/minidrone/doc.go index bc5524aee..cf1e40c52 100644 --- a/platforms/parrot/minidrone/doc.go +++ b/platforms/parrot/minidrone/doc.go @@ -2,6 +2,6 @@ Package minidrone contains the Gobot driver for the Parrot Minidrone. For more information refer to the minidrone README: -https://github.com/hybridgroup/gobot/blob/master/platforms/parrot/minidrone/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/minidrone/README.md */ -package minidrone // import "gobot.io/x/gobot/v2/platforms/parrot/minidrone" +package minidrone // import "gobot.io/x/gobot/v2/drivers/ble/parrot" diff --git a/platforms/parrot/minidrone/helpers_test.go b/platforms/parrot/minidrone/helpers_test.go deleted file mode 100644 index 48106b64d..000000000 --- a/platforms/parrot/minidrone/helpers_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package minidrone - -import ( - "sync" - - "gobot.io/x/gobot/v2/platforms/ble" -) - -var _ ble.BLEConnector = (*bleTestClientAdaptor)(nil) - -type bleTestClientAdaptor struct { - name string - address string - mtx sync.Mutex - withoutResponses bool - testReadCharacteristic func(string) ([]byte, error) - testWriteCharacteristic func(string, []byte) error -} - -func (t *bleTestClientAdaptor) Connect() error { return nil } -func (t *bleTestClientAdaptor) Reconnect() error { return nil } -func (t *bleTestClientAdaptor) Disconnect() error { return nil } -func (t *bleTestClientAdaptor) Finalize() error { return nil } -func (t *bleTestClientAdaptor) Name() string { return t.name } -func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } -func (t *bleTestClientAdaptor) Address() string { return t.address } -func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } - -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testReadCharacteristic(cUUID) -} - -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testWriteCharacteristic(cUUID, data) -} - -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { - // TODO: implement this... - return nil -} - -func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testReadCharacteristic = f -} - -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testWriteCharacteristic = f -} - -func NewBleTestAdaptor() *bleTestClientAdaptor { - return &bleTestClientAdaptor{ - address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) ([]byte, error) { - return nil, nil - }, - testWriteCharacteristic: func(cUUID string, data []byte) error { - return nil - }, - } -} diff --git a/platforms/parrot/minidrone/minidrone_driver.go b/platforms/parrot/minidrone/minidrone_driver.go deleted file mode 100644 index 904fe842d..000000000 --- a/platforms/parrot/minidrone/minidrone_driver.go +++ /dev/null @@ -1,535 +0,0 @@ -package minidrone - -import ( - "bytes" - "encoding/binary" - "fmt" - "sync" - "time" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" -) - -// Driver is the Gobot interface to the Parrot Minidrone -type Driver struct { - name string - connection gobot.Connection - stepsfa0a uint16 - stepsfa0b uint16 - pcmdMutex sync.Mutex - flying bool - Pcmd Pcmd - gobot.Eventer -} - -const ( - // BLE services - // droneCommandService = "9a66fa000800919111e4012d1540cb8e" - // droneNotificationService = "9a66fb000800919111e4012d1540cb8e" - - // send characteristics - pcmdCharacteristic = "9a66fa0a0800919111e4012d1540cb8e" - commandCharacteristic = "9a66fa0b0800919111e4012d1540cb8e" - priorityCharacteristic = "9a66fa0c0800919111e4012d1540cb8e" - - // receive characteristics - flightStatusCharacteristic = "9a66fb0e0800919111e4012d1540cb8e" - batteryCharacteristic = "9a66fb0f0800919111e4012d1540cb8e" - - // piloting states - flatTrimChanged = 0 - flyingStateChanged = 1 - - // flying states - flyingStateLanded = 0 - flyingStateTakeoff = 1 - flyingStateHovering = 2 - flyingStateFlying = 3 - flyingStateLanding = 4 - flyingStateEmergency = 5 - flyingStateRolling = 6 - - // Battery event - Battery = "battery" - - // FlightStatus event - FlightStatus = "flightstatus" - - // Takeoff event - Takeoff = "takeoff" - - // Hovering event - Hovering = "hovering" - - // Flying event - Flying = "flying" - - // Landing event - Landing = "landing" - - // Landed event - Landed = "landed" - - // Emergency event - Emergency = "emergency" - - // Rolling event - Rolling = "rolling" - - // FlatTrimChange event - FlatTrimChange = "flattrimchange" - - // LightFixed mode for LightControl - LightFixed = 0 - - // LightBlinked mode for LightControl - LightBlinked = 1 - - // LightOscillated mode for LightControl - LightOscillated = 3 - - // ClawOpen mode for ClawControl - ClawOpen = 0 - - // ClawClosed mode for ClawControl - ClawClosed = 1 -) - -// Pcmd is the Parrot Command structure for flight control -type Pcmd struct { - Flag int - Roll int - Pitch int - Yaw int - Gaz int - Psi float32 -} - -// NewDriver creates a Parrot Minidrone Driver -func NewDriver(a ble.BLEConnector) *Driver { - n := &Driver{ - name: gobot.DefaultName("Minidrone"), - connection: a, - Pcmd: Pcmd{ - Flag: 0, - Roll: 0, - Pitch: 0, - Yaw: 0, - Gaz: 0, - Psi: 0, - }, - Eventer: gobot.NewEventer(), - } - - n.AddEvent(Battery) - n.AddEvent(FlightStatus) - - n.AddEvent(Takeoff) - n.AddEvent(Flying) - n.AddEvent(Hovering) - n.AddEvent(Landing) - n.AddEvent(Landed) - n.AddEvent(Emergency) - n.AddEvent(Rolling) - - return n -} - -// Connection returns the BLE connection -func (b *Driver) Connection() gobot.Connection { return b.connection } - -// Name returns the Driver Name -func (b *Driver) Name() string { return b.name } - -// SetName sets the Driver Name -func (b *Driver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *Driver) adaptor() ble.BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(ble.BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *Driver) Start() error { - b.adaptor().WithoutResponses(true) - if err := b.Init(); err != nil { - return err - } - if err := b.FlatTrim(); err != nil { - return err - } - - b.StartPcmd() - - return b.FlatTrim() -} - -// Halt stops minidrone driver (void) -func (b *Driver) Halt() error { - err := b.Land() - time.Sleep(500 * time.Millisecond) - return err -} - -// Init initializes the BLE insterfaces used by the Minidrone -func (b *Driver) Init() error { - if err := b.GenerateAllStates(); err != nil { - return err - } - - // subscribe to battery notifications - if err := b.adaptor().Subscribe(batteryCharacteristic, func(data []byte, e error) { - b.Publish(b.Event(Battery), data[len(data)-1]) - }); err != nil { - return err - } - - // subscribe to flying status notifications - return b.adaptor().Subscribe(flightStatusCharacteristic, func(data []byte, e error) { - b.processFlightStatus(data) - }) -} - -// GenerateAllStates sets up all the default states aka settings on the drone -func (b *Driver) GenerateAllStates() error { - b.stepsfa0b++ - buf := []byte{ - 0x04, byte(b.stepsfa0b), 0x00, 0x04, 0x01, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2D, 0x31, 0x30, 0x2D, 0x32, 0x38, 0x00, - } - return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) -} - -// TakeOff tells the Minidrone to takeoff -func (b *Driver) TakeOff() error { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x00, 0x01, 0x00} - return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) -} - -// Land tells the Minidrone to land -func (b *Driver) Land() error { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x00, 0x03, 0x00} - return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) -} - -// FlatTrim calibrates the Minidrone to use its current position as being level -func (b *Driver) FlatTrim() error { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x00, 0x00, 0x00} - return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) -} - -// Emergency sets the Minidrone into emergency mode -func (b *Driver) Emergency() error { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x00, 0x04, 0x00} - return b.adaptor().WriteCharacteristic(priorityCharacteristic, buf) -} - -// TakePicture tells the Minidrone to take a picture -func (b *Driver) TakePicture() error { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x06, 0x01, 0x00} - return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) -} - -// StartPcmd starts the continuous Pcmd communication with the Minidrone -func (b *Driver) StartPcmd() { - go func() { - // wait a little bit so that there is enough time to get some ACKs - time.Sleep(500 * time.Millisecond) - for { - err := b.adaptor().WriteCharacteristic(pcmdCharacteristic, b.generatePcmd().Bytes()) - if err != nil { - fmt.Println("pcmd write error:", err) - } - time.Sleep(50 * time.Millisecond) - } - }() -} - -// Up tells the drone to ascend. Pass in an int from 0-100. -func (b *Driver) Up(val int) error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd.Flag = 1 - b.Pcmd.Gaz = validatePitch(val) - return nil -} - -// Down tells the drone to descend. Pass in an int from 0-100. -func (b *Driver) Down(val int) error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd.Flag = 1 - b.Pcmd.Gaz = validatePitch(val) * -1 - return nil -} - -// Forward tells the drone to go forward. Pass in an int from 0-100. -func (b *Driver) Forward(val int) error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd.Flag = 1 - b.Pcmd.Pitch = validatePitch(val) - return nil -} - -// Backward tells drone to go in reverse. Pass in an int from 0-100. -func (b *Driver) Backward(val int) error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd.Flag = 1 - b.Pcmd.Pitch = validatePitch(val) * -1 - return nil -} - -// Right tells drone to go right. Pass in an int from 0-100. -func (b *Driver) Right(val int) error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd.Flag = 1 - b.Pcmd.Roll = validatePitch(val) - return nil -} - -// Left tells drone to go left. Pass in an int from 0-100. -func (b *Driver) Left(val int) error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd.Flag = 1 - b.Pcmd.Roll = validatePitch(val) * -1 - return nil -} - -// Clockwise tells drone to rotate in a clockwise direction. Pass in an int from 0-100. -func (b *Driver) Clockwise(val int) error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd.Flag = 1 - b.Pcmd.Yaw = validatePitch(val) - return nil -} - -// CounterClockwise tells drone to rotate in a counter-clockwise direction. -// Pass in an int from 0-100. -func (b *Driver) CounterClockwise(val int) error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd.Flag = 1 - b.Pcmd.Yaw = validatePitch(val) * -1 - return nil -} - -// Stop tells the drone to stop moving in any direction and simply hover in place -func (b *Driver) Stop() error { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - - b.Pcmd = Pcmd{ - Flag: 0, - Roll: 0, - Pitch: 0, - Yaw: 0, - Gaz: 0, - Psi: 0, - } - - return nil -} - -// StartRecording is not supported by the Parrot Minidrone -func (b *Driver) StartRecording() error { - return nil -} - -// StopRecording is not supported by the Parrot Minidrone -func (b *Driver) StopRecording() error { - return nil -} - -// HullProtection is not supported by the Parrot Minidrone -func (b *Driver) HullProtection(protect bool) error { - return nil -} - -// Outdoor mode is not supported by the Parrot Minidrone -func (b *Driver) Outdoor(outdoor bool) error { - return nil -} - -// FrontFlip tells the drone to perform a front flip -func (b *Driver) FrontFlip() error { - return b.adaptor().WriteCharacteristic(commandCharacteristic, b.generateAnimation(0).Bytes()) -} - -// BackFlip tells the drone to perform a backflip -func (b *Driver) BackFlip() error { - return b.adaptor().WriteCharacteristic(commandCharacteristic, b.generateAnimation(1).Bytes()) -} - -// RightFlip tells the drone to perform a flip to the right -func (b *Driver) RightFlip() error { - return b.adaptor().WriteCharacteristic(commandCharacteristic, b.generateAnimation(2).Bytes()) -} - -// LeftFlip tells the drone to perform a flip to the left -func (b *Driver) LeftFlip() error { - return b.adaptor().WriteCharacteristic(commandCharacteristic, b.generateAnimation(3).Bytes()) -} - -// LightControl controls lights on those Minidrone models which -// have the correct hardware, such as the Maclane, Blaze, & Swat. -// Params: -// -// id - always 0 -// mode - either LightFixed, LightBlinked, or LightOscillated -// intensity - Light intensity from 0 (OFF) to 100 (Max intensity). -// Only used in LightFixed mode. -func (b *Driver) LightControl(id uint8, mode uint8, intensity uint8) error { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x10, 0x00, id, mode, intensity, 0x00} - return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) -} - -// ClawControl controls the claw on the Parrot Mambo -// Params: -// -// id - always 0 -// mode - either ClawOpen or ClawClosed -func (b *Driver) ClawControl(id uint8, mode uint8) error { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x10, 0x01, id, mode, 0x00} - return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) -} - -// GunControl fires the gun on the Parrot Mambo -// Params: -// -// id - always 0 -func (b *Driver) GunControl(id uint8) error { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x10, 0x02, id, 0x00} - return b.adaptor().WriteCharacteristic(commandCharacteristic, buf) -} - -func (b *Driver) generateAnimation(direction int8) *bytes.Buffer { - b.stepsfa0b++ - buf := []byte{0x02, byte(b.stepsfa0b) & 0xff, 0x02, 0x04, 0x00, 0x00, byte(direction), 0x00, 0x00, 0x00} - return bytes.NewBuffer(buf) -} - -func (b *Driver) generatePcmd() *bytes.Buffer { - b.pcmdMutex.Lock() - defer b.pcmdMutex.Unlock() - b.stepsfa0a++ - pcmd := b.Pcmd - - cmd := &bytes.Buffer{} - if err := binary.Write(cmd, binary.LittleEndian, int8(2)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(b.stepsfa0a)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(2)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(0)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(2)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(0)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Flag)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Roll)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Pitch)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Yaw)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Gaz)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, pcmd.Psi); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int16(0)); err != nil { - panic(err) - } - if err := binary.Write(cmd, binary.LittleEndian, int16(0)); err != nil { - panic(err) - } - - return cmd -} - -func (b *Driver) processFlightStatus(data []byte) { - if len(data) < 5 { - // ignore, just a sync - return - } - - b.Publish(FlightStatus, data[4]) - - switch data[4] { - case flatTrimChanged: - b.Publish(FlatTrimChange, true) - - case flyingStateChanged: - switch data[6] { - case flyingStateLanded: - if b.flying { - b.flying = false - b.Publish(Landed, true) - } - case flyingStateTakeoff: - b.Publish(Takeoff, true) - case flyingStateHovering: - if !b.flying { - b.flying = true - b.Publish(Hovering, true) - } - case flyingStateFlying: - if !b.flying { - b.flying = true - b.Publish(Flying, true) - } - case flyingStateLanding: - b.Publish(Landing, true) - case flyingStateEmergency: - b.Publish(Emergency, true) - case flyingStateRolling: - b.Publish(Rolling, true) - } - } -} - -func validatePitch(val int) int { - if val > 100 { - return 100 - } else if val < 0 { - return 0 - } - - return val -} diff --git a/platforms/parrot/minidrone/pitch.go b/platforms/parrot/minidrone/pitch.go deleted file mode 100644 index deadac85e..000000000 --- a/platforms/parrot/minidrone/pitch.go +++ /dev/null @@ -1,17 +0,0 @@ -package minidrone - -import "math" - -// ValidatePitch helps validate pitch values such as those created by -// a joystick to values between 0-100 that are required as -// params to Parrot Minidrone PCMDs -func ValidatePitch(data float64, offset float64) int { - value := math.Abs(data) / offset - if value >= 0.1 { - if value <= 1.0 { - return int((float64(int(value*100)) / 100) * 100) - } - return 100 - } - return 0 -} diff --git a/platforms/parrot/minidrone/pitch_test.go b/platforms/parrot/minidrone/pitch_test.go deleted file mode 100644 index 51b838bed..000000000 --- a/platforms/parrot/minidrone/pitch_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package minidrone - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestMinidroneValidatePitchWhenEqualOffset(t *testing.T) { - assert.Equal(t, 100, ValidatePitch(32767.0, 32767.0)) -} - -func TestMinidroneValidatePitchWhenTiny(t *testing.T) { - assert.Equal(t, 0, ValidatePitch(1.1, 32767.0)) -} - -func TestMinidroneValidatePitchWhenCentered(t *testing.T) { - assert.Equal(t, 50, ValidatePitch(16383.5, 32767.0)) -} diff --git a/platforms/parrot/parrot.go b/platforms/parrot/parrot.go index 11ba96ece..ab041b440 100644 --- a/platforms/parrot/parrot.go +++ b/platforms/parrot/parrot.go @@ -6,6 +6,6 @@ This package currently supports the following Parrot drones: - Intel Joule developer kit For further information refer to Parrot README: -https://gobot.io/x/gobot/v2/blob/master/platforms/parrot/README.md +https://gobot.io/x/gobot/v2/blob/release/platforms/parrot/README.md */ package parrot diff --git a/platforms/serialport/LICENSE b/platforms/serialport/LICENSE new file mode 100644 index 000000000..09094bb5e --- /dev/null +++ b/platforms/serialport/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2013-2018 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/platforms/serialport/README.md b/platforms/serialport/README.md new file mode 100644 index 000000000..2209a52a4 --- /dev/null +++ b/platforms/serialport/README.md @@ -0,0 +1,11 @@ +# Serialport + +The adaptor "serialport" is a small wrapper to get access to the serial port. + +## How to Install + +Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) + +## How to Use + +See documentation for [Sphero](https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/sphero/README.md) diff --git a/platforms/sphero/sphero_adaptor.go b/platforms/serialport/adaptor.go similarity index 58% rename from platforms/sphero/sphero_adaptor.go rename to platforms/serialport/adaptor.go index d71f10666..688ca3571 100644 --- a/platforms/sphero/sphero_adaptor.go +++ b/platforms/serialport/adaptor.go @@ -1,4 +1,4 @@ -package sphero +package serialport import ( "io" @@ -8,7 +8,7 @@ import ( "gobot.io/x/gobot/v2" ) -// Adaptor represents a Connection to a Sphero +// Adaptor represents a Gobot Adaptor for the Serial Communication type Adaptor struct { name string port string @@ -17,10 +17,10 @@ type Adaptor struct { connect func(string) (io.ReadWriteCloser, error) } -// NewAdaptor returns a new Sphero Adaptor given a port +// NewAdaptor returns a new adaptor given a port for the serial communication func NewAdaptor(port string) *Adaptor { return &Adaptor{ - name: gobot.DefaultName("Sphero"), + name: gobot.DefaultName("Serial"), port: port, connect: func(port string) (io.ReadWriteCloser, error) { return serial.Open(port, &serial.Mode{BaudRate: 115200}) @@ -34,13 +34,7 @@ func (a *Adaptor) Name() string { return a.name } // SetName sets the Adaptor's name func (a *Adaptor) SetName(n string) { a.name = n } -// Port returns the Adaptor's port -func (a *Adaptor) Port() string { return a.port } - -// SetPort sets the Adaptor's port -func (a *Adaptor) SetPort(p string) { a.port = p } - -// Connect initiates a connection to the Sphero. Returns true on successful connection. +// Connect initiates a connection to the serial port. func (a *Adaptor) Connect() error { sp, err := a.connect(a.Port()) if err != nil { @@ -52,19 +46,12 @@ func (a *Adaptor) Connect() error { return nil } -// Reconnect attempts to reconnect to the Sphero. If the Sphero has an active connection -// it will first close that connection and then establish a new connection. -// Returns true on Successful reconnection -func (a *Adaptor) Reconnect() error { - if a.connected { - if err := a.Disconnect(); err != nil { - return err - } - } - return a.Connect() +// Finalize finalizes the adaptor by disconnect +func (a *Adaptor) Finalize() error { + return a.Disconnect() } -// Disconnect terminates the connection to the Sphero. Returns true on successful disconnect. +// Disconnect terminates the connection to the port. func (a *Adaptor) Disconnect() error { if a.connected { if err := a.sp.Close(); err != nil { @@ -75,7 +62,31 @@ func (a *Adaptor) Disconnect() error { return nil } -// Finalize finalizes the Sphero Adaptor -func (a *Adaptor) Finalize() error { - return a.Disconnect() +// Reconnect attempts to reconnect to the port. If the port is connected it will first close +// that connection and then establish a new connection. +func (a *Adaptor) Reconnect() error { + if a.connected { + if err := a.Disconnect(); err != nil { + return err + } + } + return a.Connect() +} + +// Port returns the Adaptor's port +func (a *Adaptor) Port() string { return a.port } + +// IsConnected returns the connection state +func (a *Adaptor) IsConnected() bool { + return a.connected +} + +// SerialRead reads from the port +func (a *Adaptor) SerialRead(p []byte) (int, error) { + return a.sp.Read(p) +} + +// SerialWrite writes to the port +func (a *Adaptor) SerialWrite(p []byte) (int, error) { + return a.sp.Write(p) } diff --git a/platforms/sphero/sphero_adaptor_test.go b/platforms/serialport/adaptor_test.go similarity index 94% rename from platforms/sphero/sphero_adaptor_test.go rename to platforms/serialport/adaptor_test.go index a364e14c0..65d7a4486 100644 --- a/platforms/sphero/sphero_adaptor_test.go +++ b/platforms/serialport/adaptor_test.go @@ -1,4 +1,4 @@ -package sphero +package serialport import ( "errors" @@ -58,14 +58,14 @@ func initTestSpheroAdaptor() (*Adaptor, *nullReadWriteCloser) { func TestSpheroAdaptorName(t *testing.T) { a, _ := initTestSpheroAdaptor() - assert.True(t, strings.HasPrefix(a.Name(), "Sphero")) + assert.True(t, strings.HasPrefix(a.Name(), "Serial")) a.SetName("NewName") assert.Equal(t, "NewName", a.Name()) } func TestSpheroAdaptor(t *testing.T) { a, _ := initTestSpheroAdaptor() - assert.True(t, strings.HasPrefix(a.Name(), "Sphero")) + assert.True(t, strings.HasPrefix(a.Name(), "Serial")) assert.Equal(t, "/dev/null", a.Port()) } diff --git a/platforms/serialport/doc.go b/platforms/serialport/doc.go new file mode 100644 index 000000000..5baa09f4d --- /dev/null +++ b/platforms/serialport/doc.go @@ -0,0 +1,7 @@ +/* +Package serialport provides the Gobot adaptor for serial communication with drivers. + +For further information refer to readme: +https://github.com/hybridgroup/gobot/blob/master/platforms/serialport/README.md +*/ +package serialport // import "gobot.io/x/gobot/v2/platforms/serialport" diff --git a/platforms/sphero/bb8/README.md b/platforms/sphero/bb8/README.md index b097ae57b..e9b2f85b7 100644 --- a/platforms/sphero/bb8/README.md +++ b/platforms/sphero/bb8/README.md @@ -16,13 +16,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/bb8" + "gobot.io/x/gobot/v2/platforms/bleclient" + "gobot.io/x/gobot/v2/drivers/ble/sphero/bb8" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - bb8 := bb8.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + bb8 := bb8.NewBB8Driver(bleAdaptor) work := func() { gobot.Every(1*time.Second, func() { diff --git a/platforms/sphero/bb8/bb8_driver.go b/platforms/sphero/bb8/bb8_driver.go deleted file mode 100644 index 8e4115833..000000000 --- a/platforms/sphero/bb8/bb8_driver.go +++ /dev/null @@ -1,22 +0,0 @@ -package bb8 - -import ( - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" -) - -// Driver represents a Sphero BB-8 -type BB8Driver struct { - *ollie.Driver -} - -// NewDriver creates a Driver for a Sphero BB-8 -func NewDriver(a ble.BLEConnector) *BB8Driver { - d := ollie.NewDriver(a) - d.SetName(gobot.DefaultName("BB8")) - - return &BB8Driver{ - Driver: d, - } -} diff --git a/platforms/sphero/bb8/bb8_driver_test.go b/platforms/sphero/bb8/bb8_driver_test.go deleted file mode 100644 index b0ec1c1b9..000000000 --- a/platforms/sphero/bb8/bb8_driver_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package bb8 - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" -) - -var _ gobot.Driver = (*BB8Driver)(nil) - -func initTestBB8Driver() *BB8Driver { - d := NewDriver(NewBleTestAdaptor()) - return d -} - -func TestBB8Driver(t *testing.T) { - d := initTestBB8Driver() - assert.True(t, strings.HasPrefix(d.Name(), "BB8")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) -} - -func TestBB8DriverStartAndHalt(t *testing.T) { - d := initTestBB8Driver() - require.NoError(t, d.Start()) - require.NoError(t, d.Halt()) -} diff --git a/platforms/sphero/bb8/bb8_packets.go b/platforms/sphero/bb8/bb8_packets.go deleted file mode 100644 index d28d4d852..000000000 --- a/platforms/sphero/bb8/bb8_packets.go +++ /dev/null @@ -1,15 +0,0 @@ -package bb8 - -import "gobot.io/x/gobot/v2/platforms/sphero" - -// DefaultCollisionConfig returns a CollisionConfig with sensible collision defaults -func DefaultCollisionConfig() sphero.CollisionConfig { - return sphero.CollisionConfig{ - Method: 0x01, - Xt: 0x20, - Yt: 0x20, - Xs: 0x20, - Ys: 0x20, - Dead: 0x01, - } -} diff --git a/platforms/sphero/bb8/doc.go b/platforms/sphero/bb8/doc.go deleted file mode 100644 index 80aca8fe6..000000000 --- a/platforms/sphero/bb8/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -Package bb8 contains the Gobot driver for the Sphero BB-8. - -For more information refer to the BB-8 README: -https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/bb8/README.md -*/ -package bb8 // import "gobot.io/x/gobot/v2/platforms/sphero/bb8" diff --git a/platforms/sphero/bb8/helpers_test.go b/platforms/sphero/bb8/helpers_test.go deleted file mode 100644 index 9738f6987..000000000 --- a/platforms/sphero/bb8/helpers_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package bb8 - -import ( - "sync" - - "gobot.io/x/gobot/v2/platforms/ble" -) - -var _ ble.BLEConnector = (*bleTestClientAdaptor)(nil) - -type bleTestClientAdaptor struct { - name string - address string - mtx sync.Mutex - withoutResponses bool - - testReadCharacteristic func(string) ([]byte, error) - testWriteCharacteristic func(string, []byte) error -} - -func (t *bleTestClientAdaptor) Connect() error { return nil } -func (t *bleTestClientAdaptor) Reconnect() error { return nil } -func (t *bleTestClientAdaptor) Disconnect() error { return nil } -func (t *bleTestClientAdaptor) Finalize() error { return nil } -func (t *bleTestClientAdaptor) Name() string { return t.name } -func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } -func (t *bleTestClientAdaptor) Address() string { return t.address } -func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } - -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testReadCharacteristic(cUUID) -} - -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testWriteCharacteristic(cUUID, data) -} - -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { - // TODO: implement this... - return nil -} - -func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testReadCharacteristic = f -} - -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testWriteCharacteristic = f -} - -func NewBleTestAdaptor() *bleTestClientAdaptor { - return &bleTestClientAdaptor{ - address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) ([]byte, error) { - return nil, nil - }, - testWriteCharacteristic: func(cUUID string, data []byte) error { - return nil - }, - } -} diff --git a/platforms/sphero/doc.go b/platforms/sphero/doc.go deleted file mode 100644 index bfe1f7f6c..000000000 --- a/platforms/sphero/doc.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Package sphero provides the Gobot adaptor and driver for the Sphero. - -Installing: - - Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) - -Example: - - package main - - import ( - "fmt" - "time" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/sphero" - ) - - func main() { - adaptor := sphero.NewAdaptor("/dev/rfcomm0") - driver := sphero.NewSpheroDriver(adaptor) - - work := func() { - gobot.Every(3*time.Second, func() { - driver.Roll(30, uint16(gobot.Rand(360))) - }) - } - - robot := gobot.NewRobot("sphero", - []gobot.Connection{adaptor}, - []gobot.Device{driver}, - work, - ) - - robot.Start() - } - -For further information refer to sphero readme: -https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/README.md -*/ -package sphero // import "gobot.io/x/gobot/v2/platforms/sphero" diff --git a/platforms/sphero/ollie/README.md b/platforms/sphero/ollie/README.md index 2f2b541a8..803016f5d 100644 --- a/platforms/sphero/ollie/README.md +++ b/platforms/sphero/ollie/README.md @@ -16,13 +16,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" + "gobot.io/x/gobot/v2/platforms/bleclient" + "gobot.io/x/gobot/v2/drivers/ble/sphero/ollie" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - ollie := ollie.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + ollie := ollie.NewOllieDriver(bleAdaptor) work := func() { gobot.Every(1*time.Second, func() { diff --git a/platforms/sphero/ollie/doc.go b/platforms/sphero/ollie/doc.go deleted file mode 100644 index e848ccbad..000000000 --- a/platforms/sphero/ollie/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -Package ollie contains the Gobot driver for the Sphero Ollie. - -For more information refer to the Ollie README: -https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/ollie/README.md -*/ -package ollie // import "gobot.io/x/gobot/v2/platforms/sphero/ollie" diff --git a/platforms/sphero/ollie/helpers_test.go b/platforms/sphero/ollie/helpers_test.go deleted file mode 100644 index 031c4f922..000000000 --- a/platforms/sphero/ollie/helpers_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package ollie - -import ( - "sync" - - "gobot.io/x/gobot/v2/platforms/ble" -) - -var _ ble.BLEConnector = (*bleTestClientAdaptor)(nil) - -type bleTestClientAdaptor struct { - name string - address string - mtx sync.Mutex - withoutResponses bool - - testReadCharacteristic func(string) ([]byte, error) - testWriteCharacteristic func(string, []byte) error -} - -func (t *bleTestClientAdaptor) Connect() error { return nil } -func (t *bleTestClientAdaptor) Reconnect() error { return nil } -func (t *bleTestClientAdaptor) Disconnect() error { return nil } -func (t *bleTestClientAdaptor) Finalize() error { return nil } -func (t *bleTestClientAdaptor) Name() string { return t.name } -func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } -func (t *bleTestClientAdaptor) Address() string { return t.address } -func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } - -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testReadCharacteristic(cUUID) -} - -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testWriteCharacteristic(cUUID, data) -} - -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { - // TODO: implement this... - return nil -} - -func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testReadCharacteristic = f -} - -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testWriteCharacteristic = f -} - -func NewBleTestAdaptor() *bleTestClientAdaptor { - return &bleTestClientAdaptor{ - address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) ([]byte, error) { - return nil, nil - }, - testWriteCharacteristic: func(cUUID string, data []byte) error { - return nil - }, - } -} diff --git a/platforms/sphero/ollie/ollie_driver.go b/platforms/sphero/ollie/ollie_driver.go deleted file mode 100644 index d544d3a66..000000000 --- a/platforms/sphero/ollie/ollie_driver.go +++ /dev/null @@ -1,481 +0,0 @@ -package ollie - -import ( - "bytes" - "encoding/binary" - "fmt" - "sync" - "time" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero" -) - -// Driver is the Gobot driver for the Sphero Ollie robot -type Driver struct { - name string - connection gobot.Connection - seq uint8 - mtx sync.Mutex - collisionResponse []uint8 - packetChannel chan *Packet - asyncBuffer []byte - asyncMessage []byte - locatorCallback func(p Point2D) - powerstateCallback func(p PowerStatePacket) - gobot.Eventer -} - -const ( - // bluetooth service IDs - // spheroBLEService = "22bb746f2bb075542d6f726568705327" - // robotControlService = "22bb746f2ba075542d6f726568705327" - - // BLE characteristic IDs - wakeCharacteristic = "22bb746f2bbf75542d6f726568705327" - txPowerCharacteristic = "22bb746f2bb275542d6f726568705327" - antiDosCharacteristic = "22bb746f2bbd75542d6f726568705327" - commandsCharacteristic = "22bb746f2ba175542d6f726568705327" - responseCharacteristic = "22bb746f2ba675542d6f726568705327" - - // SensorData event - SensorData = "sensordata" - - // Collision event - Collision = "collision" - - // Error event - Error = "error" - - // Packet header size - PacketHeaderSize = 5 - - // Response packet max size - ResponsePacketMaxSize = 20 - - // Collision Packet data size: The number of bytes following the DLEN field through the end of the packet - CollisionDataSize = 17 - - // Full size of the collision response - CollisionResponseSize = PacketHeaderSize + CollisionDataSize -) - -// MotorModes is used to configure the motor -type MotorModes uint8 - -// MotorModes required for SetRawMotorValues command -const ( - Off MotorModes = iota - Forward - Reverse - Brake - Ignore -) - -// Packet describes head, body and checksum for a data package to be sent to the sphero. -type Packet struct { - Header []uint8 - Body []uint8 - Checksum uint8 -} - -// Point2D represents a koordinate in 2-Dimensional space -type Point2D struct { - X int16 - Y int16 -} - -// NewDriver creates a Driver for a Sphero Ollie -func NewDriver(a ble.BLEConnector) *Driver { - n := &Driver{ - name: gobot.DefaultName("Ollie"), - connection: a, - Eventer: gobot.NewEventer(), - packetChannel: make(chan *Packet, 1024), - } - - n.AddEvent(Collision) - - return n -} - -// PacketChannel returns the channel for packets to be sent to the sp -func (b *Driver) PacketChannel() chan *Packet { return b.packetChannel } - -// Sequence returns the Sequence number of the current packet -func (b *Driver) Sequence() uint8 { return b.seq } - -// Connection returns the connection to this Ollie -func (b *Driver) Connection() gobot.Connection { return b.connection } - -// Name returns the name for the Driver -func (b *Driver) Name() string { return b.name } - -// SetName sets the Name for the Driver -func (b *Driver) SetName(n string) { b.name = n } - -// adaptor returns BLE adaptor -func (b *Driver) adaptor() ble.BLEConnector { - //nolint:forcetypeassert // ok here - return b.Connection().(ble.BLEConnector) -} - -// Start tells driver to get ready to do work -func (b *Driver) Start() error { - if err := b.Init(); err != nil { - return err - } - - // send commands - go func() { - for { - packet := <-b.packetChannel - err := b.write(packet) - if err != nil { - b.Publish(b.Event(Error), err) - } - } - }() - - go func() { - for { - if _, err := b.adaptor().ReadCharacteristic(responseCharacteristic); err != nil { - panic(err) - } - time.Sleep(100 * time.Millisecond) - } - }() - - b.ConfigureCollisionDetection(DefaultCollisionConfig()) - - return nil -} - -// Halt stops Ollie driver (void) -func (b *Driver) Halt() error { - b.Sleep() - time.Sleep(750 * time.Microsecond) - return nil -} - -// Init is used to initialize the Ollie -func (b *Driver) Init() error { - if err := b.AntiDOSOff(); err != nil { - return err - } - if err := b.SetTXPower(7); err != nil { - return err - } - if err := b.Wake(); err != nil { - return err - } - - // subscribe to Sphero response notifications - return b.adaptor().Subscribe(responseCharacteristic, b.HandleResponses) -} - -// AntiDOSOff turns off Anti-DOS code so we can control Ollie -func (b *Driver) AntiDOSOff() error { - str := "011i3" - buf := &bytes.Buffer{} - buf.WriteString(str) - - if err := b.adaptor().WriteCharacteristic(antiDosCharacteristic, buf.Bytes()); err != nil { - fmt.Println("AntiDOSOff error:", err) - return err - } - - return nil -} - -// Wake wakes Ollie up so we can play -func (b *Driver) Wake() error { - buf := []byte{0x01} - - if err := b.adaptor().WriteCharacteristic(wakeCharacteristic, buf); err != nil { - fmt.Println("Wake error:", err) - return err - } - - return nil -} - -// SetTXPower sets transmit level -func (b *Driver) SetTXPower(level int) error { - buf := []byte{byte(level)} - - if err := b.adaptor().WriteCharacteristic(txPowerCharacteristic, buf); err != nil { - fmt.Println("SetTXLevel error:", err) - return err - } - - return nil -} - -// HandleResponses handles responses returned from Ollie -func (b *Driver) HandleResponses(data []byte, e error) { - // since packets can only be 20 bytes long, we have to puzzle them together - newMessage := false - - // append message parts to existing - if len(data) > 0 && data[0] != 0xFF { - b.asyncBuffer = append(b.asyncBuffer, data...) - } - - // clear message when new one begins (first byte is always 0xFF) - if len(data) > 0 && data[0] == 0xFF { - b.asyncMessage = b.asyncBuffer - b.asyncBuffer = data - newMessage = true - } - - parts := b.asyncMessage - // 3 is the id of data streaming, located at index 2 byte - if newMessage && len(parts) > 2 && parts[2] == 3 { - b.handleDataStreaming(parts) - } - - // index 1 is the type of the message, 0xFF being a direct response, 0xFE an asynchronous message - if len(data) > 4 && data[1] == 0xFF && data[0] == 0xFF { - // locator request - if data[4] == 0x0B && len(data) == 16 { - b.handleLocatorDetected(data) - } - - if data[4] == 0x09 { - b.handlePowerStateDetected(data) - } - } - - b.handleCollisionDetected(data) -} - -// GetLocatorData calls the passed function with the data from the locator -func (b *Driver) GetLocatorData(f func(p Point2D)) { - // CID 0x15 is the code for the locator request - b.PacketChannel() <- b.craftPacket([]uint8{}, 0x02, 0x15) - b.locatorCallback = f -} - -// GetPowerState calls the passed function with the Power State information from the sphero -func (b *Driver) GetPowerState(f func(p PowerStatePacket)) { - // CID 0x20 is the code for the power state - b.PacketChannel() <- b.craftPacket([]uint8{}, 0x00, 0x20) - b.powerstateCallback = f -} - -func (b *Driver) handleDataStreaming(data []byte) { - // ensure data is the right length: - if len(data) != 88 { - return - } - - // data packet is the same as for the normal sphero, since the same communication api is used - // only difference in communication is that the "newer" spheros use BLE for communinations - var dataPacket DataStreamingPacket - buffer := bytes.NewBuffer(data[5:]) // skip header - if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { - panic(err) - } - - b.Publish(SensorData, dataPacket) -} - -// SetRGB sets the Ollie to the given r, g, and b values -func (b *Driver) SetRGB(r uint8, g uint8, bl uint8) { - b.packetChannel <- b.craftPacket([]uint8{r, g, bl, 0x01}, 0x02, 0x20) -} - -// Roll tells the Ollie to roll -func (b *Driver) Roll(speed uint8, heading uint16) { - b.packetChannel <- b.craftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x02, 0x30) -} - -// Boost executes the boost macro from within the SSB which takes a -// 1 byte parameter which is either 01h to begin boosting or 00h to stop. -func (b *Driver) Boost(state bool) { - s := uint8(0x01) - if !state { - s = 0x00 - } - b.packetChannel <- b.craftPacket([]uint8{s}, 0x02, 0x31) -} - -// SetStabilization enables or disables the built-in auto stabilizing features of the Ollie -func (b *Driver) SetStabilization(state bool) { - s := uint8(0x01) - if !state { - s = 0x00 - } - b.packetChannel <- b.craftPacket([]uint8{s}, 0x02, 0x02) -} - -// SetRotationRate allows you to control the rotation rate that Sphero will use to meet new -// heading commands. A value of 255 jumps to the maximum (currently 400 degrees/sec). -// A value of zero doesn't make much sense so it's interpreted as 1, the minimum. -func (b *Driver) SetRotationRate(speed uint8) { - b.packetChannel <- b.craftPacket([]uint8{speed}, 0x02, 0x03) -} - -// SetRawMotorValues allows you to take over one or both of the motor output values, -// instead of having the stabilization system control them. Each motor (left and right) -// requires a mode and a power value from 0-255 -func (b *Driver) SetRawMotorValues(lmode MotorModes, lpower uint8, rmode MotorModes, rpower uint8) { - b.packetChannel <- b.craftPacket([]uint8{uint8(lmode), lpower, uint8(rmode), rpower}, 0x02, 0x33) -} - -// SetBackLEDOutput allows you to control the brightness of the back(tail) LED. -func (b *Driver) SetBackLEDOutput(value uint8) { - b.packetChannel <- b.craftPacket([]uint8{value}, 0x02, 0x21) -} - -// Stop tells the Ollie to stop -func (b *Driver) Stop() { - b.Roll(0, 0) -} - -// Sleep says Go to sleep -func (b *Driver) Sleep() { - b.packetChannel <- b.craftPacket([]uint8{0x00, 0x00, 0x00, 0x00, 0x00}, 0x00, 0x22) -} - -// EnableStopOnDisconnect auto-sends a Stop command after losing the connection -func (b *Driver) EnableStopOnDisconnect() { - b.packetChannel <- b.craftPacket([]uint8{0x00, 0x00, 0x00, 0x01}, 0x02, 0x37) -} - -// ConfigureCollisionDetection configures the sensitivity of the detection. -func (b *Driver) ConfigureCollisionDetection(cc sphero.CollisionConfig) { - b.packetChannel <- b.craftPacket([]uint8{cc.Method, cc.Xt, cc.Yt, cc.Xs, cc.Ys, cc.Dead}, 0x02, 0x12) -} - -// SetDataStreamingConfig passes the config to the sphero to stream sensor data -func (b *Driver) SetDataStreamingConfig(d sphero.DataStreamingConfig) error { - buf := new(bytes.Buffer) - if err := binary.Write(buf, binary.BigEndian, d); err != nil { - return err - } - b.PacketChannel() <- b.craftPacket(buf.Bytes(), 0x02, 0x11) - return nil -} - -func (b *Driver) write(packet *Packet) error { - buf := append(packet.Header, packet.Body...) - buf = append(buf, packet.Checksum) - if err := b.adaptor().WriteCharacteristic(commandsCharacteristic, buf); err != nil { - fmt.Println("send command error:", err) - return err - } - - b.mtx.Lock() - defer b.mtx.Unlock() - b.seq++ - return nil -} - -func (b *Driver) craftPacket(body []uint8, did byte, cid byte) *Packet { - b.mtx.Lock() - defer b.mtx.Unlock() - - packet := new(Packet) - packet.Body = body - dlen := len(packet.Body) + 1 - packet.Header = []uint8{0xFF, 0xFF, did, cid, b.seq, uint8(dlen)} - packet.Checksum = b.calculateChecksum(packet) - return packet -} - -func (b *Driver) handlePowerStateDetected(data []uint8) { - var dataPacket PowerStatePacket - buffer := bytes.NewBuffer(data[5:]) // skip header - if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { - panic(err) - } - - b.powerstateCallback(dataPacket) -} - -func (b *Driver) handleLocatorDetected(data []uint8) { - // read the unsigned raw values - ux := binary.BigEndian.Uint16(data[5:7]) - uy := binary.BigEndian.Uint16(data[7:9]) - - // convert to signed values - var x, y int16 - - if ux > 32255 { - x = int16(ux - 65535) - } else { - x = int16(ux) - } - - if uy > 32255 { - y = int16(uy - 65535) - } else { - y = int16(uy) - } - - // create point obj - p := new(Point2D) - p.X = x - p.Y = y - - if b.locatorCallback != nil { - b.locatorCallback(*p) - } -} - -func (b *Driver) handleCollisionDetected(data []uint8) { - switch len(data) { - case ResponsePacketMaxSize: - // Check if this is the header of collision response. (i.e. first part of data) - // Collision response is 22 bytes long. (individual packet size is maxed at 20) - if data[1] == 0xFE && data[2] == 0x07 && len(b.collisionResponse) == 0 { - // response code 7 is for a detected collision - b.collisionResponse = append(b.collisionResponse, data...) - } - case CollisionResponseSize - ResponsePacketMaxSize: - // if this is the remaining part of the collision response, - // then make sure the header and first part of data is already received - if len(b.collisionResponse) == ResponsePacketMaxSize { - b.collisionResponse = append(b.collisionResponse, data...) - } - default: - return // not collision event - } - - // check expected sizes - if len(b.collisionResponse) != CollisionResponseSize || b.collisionResponse[4] != CollisionDataSize { - return - } - - // confirm checksum - size := len(b.collisionResponse) - chk := b.collisionResponse[size-1] // last byte is checksum - if chk != calculateChecksum(b.collisionResponse[2:size-1]) { - return - } - - var collision sphero.CollisionPacket - buffer := bytes.NewBuffer(b.collisionResponse[5:]) // skip header - if err := binary.Read(buffer, binary.BigEndian, &collision); err != nil { - panic(err) - } - b.collisionResponse = nil // clear the current response - - b.Publish(Collision, collision) -} - -func (b *Driver) calculateChecksum(packet *Packet) uint8 { - buf := append(packet.Header, packet.Body...) - return calculateChecksum(buf[2:]) -} - -func calculateChecksum(buf []byte) byte { - var calculatedChecksum uint16 - for i := range buf { - calculatedChecksum += uint16(buf[i]) - } - return uint8(^(calculatedChecksum % 256)) -} diff --git a/platforms/sphero/ollie/ollie_packets.go b/platforms/sphero/ollie/ollie_packets.go deleted file mode 100644 index 673c18954..000000000 --- a/platforms/sphero/ollie/ollie_packets.go +++ /dev/null @@ -1,115 +0,0 @@ -package ollie - -import "gobot.io/x/gobot/v2/platforms/sphero" - -// DefaultCollisionConfig returns a CollisionConfig with sensible collision defaults -func DefaultCollisionConfig() sphero.CollisionConfig { - return sphero.CollisionConfig{ - Method: 0x01, - Xt: 0x20, - Yt: 0x20, - Xs: 0x20, - Ys: 0x20, - Dead: 0x60, - } -} - -// PowerStatePacket contains all data relevant to the power state of the sphero -type PowerStatePacket struct { - // record Version Code - RecVer uint8 - // High-Level State of the Battery; 1=charging, 2=battery ok, 3=battery low, 4=battery critical - PowerState uint8 - // Battery Voltage, scaled in 100th of a Volt, 0x02EF would be 7.51 volts - BattVoltage uint16 - // Number of charges in the total lifetime of the sphero - NumCharges uint16 - // Seconds awake since last charge - TimeSinceChg uint16 -} - -// DataStreamingPacket represents the response from a Data Streaming event -type DataStreamingPacket struct { - // 8000 0000h accelerometer axis X, raw -2048 to 2047 4mG - RawAccX int16 - // 4000 0000h accelerometer axis Y, raw -2048 to 2047 4mG - RawAccY int16 - // 2000 0000h accelerometer axis Z, raw -2048 to 2047 4mG - RawAccZ int16 - // 1000 0000h gyro axis X, raw -32768 to 32767 0.068 degrees - RawGyroX int16 - // 0800 0000h gyro axis Y, raw -32768 to 32767 0.068 degrees - RawGyroY int16 - // 0400 0000h gyro axis Z, raw -32768 to 32767 0.068 degrees - RawGyroZ int16 - // 0200 0000h Reserved - Rsrv1 int16 - // 0100 0000h Reserved - Rsrv2 int16 - // 0080 0000h Reserved - Rsrv3 int16 - // 0040 0000h right motor back EMF, raw -32768 to 32767 22.5 cm - RawRMotorBack int16 - // 0020 0000h left motor back EMF, raw -32768 to 32767 22.5 cm - RawLMotorBack int16 - // 0010 0000h left motor, PWM, raw -2048 to 2047 duty cycle - RawLMotor int16 - // 0008 0000h right motor, PWM raw -2048 to 2047 duty cycle - RawRMotor int16 - // 0004 0000h IMU pitch angle, filtered -179 to 180 degrees - FiltPitch int16 - // 0002 0000h IMU roll angle, filtered -179 to 180 degrees - FiltRoll int16 - // 0001 0000h IMU yaw angle, filtered -179 to 180 degrees - FiltYaw int16 - // 0000 8000h accelerometer axis X, filtered -32768 to 32767 1/4096 G - FiltAccX int16 - // 0000 4000h accelerometer axis Y, filtered -32768 to 32767 1/4096 G - FiltAccY int16 - // 0000 2000h accelerometer axis Z, filtered -32768 to 32767 1/4096 G - FiltAccZ int16 - // 0000 1000h gyro axis X, filtered -20000 to 20000 0.1 dps - FiltGyroX int16 - // 0000 0800h gyro axis Y, filtered -20000 to 20000 0.1 dps - FiltGyroY int16 - // 0000 0400h gyro axis Z, filtered -20000 to 20000 0.1 dps - FiltGyroZ int16 - // 0000 0200h Reserved - Rsrv4 int16 - // 0000 0100h Reserved - Rsrv5 int16 - // 0000 0080h Reserved - Rsrv6 int16 - // 0000 0040h right motor back EMF, filtered -32768 to 32767 22.5 cm - FiltRMotorBack int16 - // 0000 0020h left motor back EMF, filtered -32768 to 32767 22.5 cm - FiltLMotorBack int16 - // 0000 0010h Reserved 1 - Rsrv7 int16 - // 0000 0008h Reserved 2 - Rsrv8 int16 - // // 0000 0004h Reserved 3 - // Rsrv9 int16 - // // 0000 0002h Reserved 4 - // Rsrv10 int16 - // // 0000 0001h Reserved 5 - // Rsrv11 int16 - // 8000 0000h Quaternion Q0 -10000 to 10000 1/10000 Q - Quat0 int16 - // 4000 0000h Quaternion Q1 -10000 to 10000 1/10000 Q - Quat1 int16 - // 2000 0000h Quaternion Q2 -10000 to 10000 1/10000 Q - Quat2 int16 - // 1000 0000h Quaternion Q3 -10000 to 10000 1/10000 Q - Quat3 int16 - // 0800 0000h Odometer X -32768 to 32767 cm - OdomX int16 - // 0400 0000h Odometer Y -32768 to 32767 cm - OdomY int16 - // 0200 0000h AccelOne 0 to 8000 1 mG - AccelOne int16 - // 0100 0000h Velocity X -32768 to 32767 mm/s - VeloX int16 - // 0080 0000h Velocity Y -32768 to 32767 mm/s - VeloY int16 -} diff --git a/platforms/sphero/sphero/LICENSE b/platforms/sphero/sphero/LICENSE new file mode 100644 index 000000000..09094bb5e --- /dev/null +++ b/platforms/sphero/sphero/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2013-2018 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/platforms/sphero/README.md b/platforms/sphero/sphero/README.md similarity index 77% rename from platforms/sphero/README.md rename to platforms/sphero/sphero/README.md index 9132c6368..e2cdb0087 100644 --- a/platforms/sphero/README.md +++ b/platforms/sphero/sphero/README.md @@ -2,9 +2,9 @@ Sphero is a sophisticated and programmable robot housed in a polycarbonate sphere shell. -The Gobot Sphero Adaptor & Driver makes it easy to interact with Sphero using Go. Once you have your Sphero setup and connected -to your computer you can start writing code to make Sphero move, change direction, speed and colors, or detect Sphero events -and execute some code when they occur. +The Gobot Serial Adaptor & Sphero Driver makes it easy to interact with Sphero using Go. Once you have your Sphero setup +and connected to your computer you can start writing code to make Sphero move, change direction, speed and colors, or +detect Sphero events and execute some code when they occur. Learn more about the Sphero robot go here: @@ -49,7 +49,8 @@ gort bluetooth connect
### Windows -You should be able to pair your Sphero using your normal system tray applet for Bluetooth, and then connect to the COM port that is bound to the device, such as `COM3`. +You should be able to pair your Sphero using your normal system tray applet for Bluetooth, and then connect to the COM +port that is bound to the device, such as `COM3`. ## How to Use @@ -63,12 +64,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/sphero" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { - adaptor := sphero.NewAdaptor("/dev/rfcomm0") - driver := sphero.NewSpheroDriver(adaptor) + adaptor := serialport.NewAdaptor("/dev/rfcomm0") + driver := serial.NewSpheroDriver(adaptor) work := func() { gobot.Every(3*time.Second, func() { diff --git a/platforms/sphero/sphero_driver.go b/platforms/sphero/sphero_driver.go deleted file mode 100644 index 81963422e..000000000 --- a/platforms/sphero/sphero_driver.go +++ /dev/null @@ -1,472 +0,0 @@ -package sphero - -import ( - "bytes" - "encoding/binary" - "errors" - "sync" - "time" - - "gobot.io/x/gobot/v2" -) - -const ( - // Error event when error encountered - Error = "error" - - // SensorData event when sensor data is received - SensorData = "sensordata" - - // Collision event when collision is detected - Collision = "collision" -) - -type packet struct { - header []uint8 - body []uint8 - checksum uint8 -} - -// SpheroDriver Represents a Sphero 2.0 -type SpheroDriver struct { - name string - connection gobot.Connection - mtx sync.Mutex - seq uint8 - asyncResponse [][]uint8 - syncResponse [][]uint8 - packetChannel chan *packet - responseChannel chan []uint8 - originalColor []uint8 // Only used for calibration. - gobot.Eventer - gobot.Commander -} - -// NewSpheroDriver returns a new SpheroDriver given a Sphero Adaptor. -// -// Adds the following API Commands: -// -// "ConfigureLocator" - See SpheroDriver.ConfigureLocator -// "Roll" - See SpheroDriver.Roll -// "Stop" - See SpheroDriver.Stop -// "GetRGB" - See SpheroDriver.GetRGB -// "ReadLocator" - See SpheroDriver.ReadLocator -// "SetBackLED" - See SpheroDriver.SetBackLED -// "SetHeading" - See SpheroDriver.SetHeading -// "SetStabilization" - See SpheroDriver.SetStabilization -// "SetDataStreaming" - See SpheroDriver.SetDataStreaming -// "SetRotationRate" - See SpheroDriver.SetRotationRate -func NewSpheroDriver(a *Adaptor) *SpheroDriver { - s := &SpheroDriver{ - name: gobot.DefaultName("Sphero"), - connection: a, - Eventer: gobot.NewEventer(), - Commander: gobot.NewCommander(), - packetChannel: make(chan *packet, 1024), - responseChannel: make(chan []uint8, 1024), - } - - s.AddEvent(Error) - s.AddEvent(Collision) - s.AddEvent(SensorData) - - //nolint:forcetypeassert // ok here - s.AddCommand("SetRGB", func(params map[string]interface{}) interface{} { - r := uint8(params["r"].(float64)) - g := uint8(params["g"].(float64)) - b := uint8(params["b"].(float64)) - s.SetRGB(r, g, b) - return nil - }) - - //nolint:forcetypeassert // ok here - s.AddCommand("Roll", func(params map[string]interface{}) interface{} { - speed := uint8(params["speed"].(float64)) - heading := uint16(params["heading"].(float64)) - s.Roll(speed, heading) - return nil - }) - - s.AddCommand("Stop", func(params map[string]interface{}) interface{} { - s.Stop() - return nil - }) - - s.AddCommand("GetRGB", func(params map[string]interface{}) interface{} { - return s.GetRGB() - }) - - s.AddCommand("ReadLocator", func(params map[string]interface{}) interface{} { - return s.ReadLocator() - }) - - //nolint:forcetypeassert // ok here - s.AddCommand("SetBackLED", func(params map[string]interface{}) interface{} { - level := uint8(params["level"].(float64)) - s.SetBackLED(level) - return nil - }) - //nolint:forcetypeassert // ok here - s.AddCommand("SetRotationRate", func(params map[string]interface{}) interface{} { - level := uint8(params["level"].(float64)) - s.SetRotationRate(level) - return nil - }) - //nolint:forcetypeassert // ok here - s.AddCommand("SetHeading", func(params map[string]interface{}) interface{} { - heading := uint16(params["heading"].(float64)) - s.SetHeading(heading) - return nil - }) - //nolint:forcetypeassert // ok here - s.AddCommand("SetStabilization", func(params map[string]interface{}) interface{} { - on := params["enable"].(bool) - s.SetStabilization(on) - return nil - }) - //nolint:forcetypeassert // ok here - s.AddCommand("SetDataStreaming", func(params map[string]interface{}) interface{} { - N := uint16(params["N"].(float64)) - M := uint16(params["M"].(float64)) - Mask := uint32(params["Mask"].(float64)) - Pcnt := uint8(params["Pcnt"].(float64)) - Mask2 := uint32(params["Mask2"].(float64)) - - s.SetDataStreaming(DataStreamingConfig{N: N, M: M, Mask2: Mask2, Pcnt: Pcnt, Mask: Mask}) - return nil - }) - //nolint:forcetypeassert // ok here - s.AddCommand("ConfigureLocator", func(params map[string]interface{}) interface{} { - Flags := uint8(params["Flags"].(float64)) - X := int16(params["X"].(float64)) - Y := int16(params["Y"].(float64)) - YawTare := int16(params["YawTare"].(float64)) - - s.ConfigureLocator(LocatorConfig{Flags: Flags, X: X, Y: Y, YawTare: YawTare}) - return nil - }) - - return s -} - -// Name returns the Driver Name -func (s *SpheroDriver) Name() string { return s.name } - -// SetName sets the Driver Name -func (s *SpheroDriver) SetName(n string) { s.name = n } - -// Connection returns the Driver's Connection -func (s *SpheroDriver) Connection() gobot.Connection { return s.connection } - -func (s *SpheroDriver) adaptor() *Adaptor { - //nolint:forcetypeassert // ok here - return s.Connection().(*Adaptor) -} - -// Start starts the SpheroDriver and enables Collision Detection. -// Returns true on successful start. -// -// Emits the Events: -// -// Collision sphero.CollisionPacket - On Collision Detected -// SensorData sphero.DataStreamingPacket - On Data Streaming event -// Error error- On error while processing asynchronous response -func (s *SpheroDriver) Start() error { - go func() { - for { - packet := <-s.packetChannel - err := s.write(packet) - if err != nil { - s.Publish(Error, err) - } - } - }() - - go func() { - for { - response := <-s.responseChannel - s.syncResponse = append(s.syncResponse, response) - } - }() - - go func() { - for { - header := s.readHeader() - if len(header) > 0 { - body := s.readBody(header[4]) - data := append(header, body...) - checksum := data[len(data)-1] - if checksum != calculateChecksum(data[2:len(data)-1]) { - continue - } - switch header[1] { - case 0xFE: - s.asyncResponse = append(s.asyncResponse, data) - case 0xFF: - s.responseChannel <- data - } - } - } - }() - - go func() { - for { - var evt []uint8 - for len(s.asyncResponse) != 0 { - evt, s.asyncResponse = s.asyncResponse[len(s.asyncResponse)-1], s.asyncResponse[:len(s.asyncResponse)-1] - if evt[2] == 0x07 { - s.handleCollisionDetected(evt) - } else if evt[2] == 0x03 { - s.handleDataStreaming(evt) - } - } - time.Sleep(100 * time.Millisecond) - } - }() - - s.ConfigureCollisionDetection(DefaultCollisionConfig()) - s.enableStopOnDisconnect() - - return nil -} - -// Halt halts the SpheroDriver and sends a SpheroDriver.Stop command to the Sphero. -// Returns true on successful halt. -func (s *SpheroDriver) Halt() error { - if s.adaptor().connected { - gobot.Every(10*time.Millisecond, func() { - s.Stop() - }) - time.Sleep(1 * time.Second) - } - return nil -} - -// SetRGB sets the Sphero to the given r, g, and b values -func (s *SpheroDriver) SetRGB(r uint8, g uint8, b uint8) { - s.packetChannel <- s.craftPacket([]uint8{r, g, b, 0x01}, 0x02, 0x20) -} - -// GetRGB returns the current r, g, b value of the Sphero -func (s *SpheroDriver) GetRGB() []uint8 { - buf := s.getSyncResponse(s.craftPacket([]uint8{}, 0x02, 0x22)) - if len(buf) == 9 { - return []uint8{buf[5], buf[6], buf[7]} - } - return []uint8{} -} - -// ReadLocator reads Sphero's current position (X,Y), component velocities and SOG (speed over ground). -func (s *SpheroDriver) ReadLocator() []int16 { - buf := s.getSyncResponse(s.craftPacket([]uint8{}, 0x02, 0x15)) - if len(buf) == 16 { - vals := make([]int16, 5) - _ = binary.Read(bytes.NewReader(buf[5:15]), binary.BigEndian, &vals) - return vals - } - return []int16{} -} - -// SetBackLED sets the Sphero Back LED to the specified brightness -func (s *SpheroDriver) SetBackLED(level uint8) { - s.packetChannel <- s.craftPacket([]uint8{level}, 0x02, 0x21) -} - -// SetRotationRate sets the Sphero rotation rate -// A value of 255 jumps to the maximum (currently 400 degrees/sec). -func (s *SpheroDriver) SetRotationRate(level uint8) { - s.packetChannel <- s.craftPacket([]uint8{level}, 0x02, 0x03) -} - -// SetHeading sets the heading of the Sphero -func (s *SpheroDriver) SetHeading(heading uint16) { - s.packetChannel <- s.craftPacket([]uint8{uint8(heading >> 8), uint8(heading & 0xFF)}, 0x02, 0x01) -} - -// SetStabilization enables or disables the built-in auto stabilizing features of the Sphero -func (s *SpheroDriver) SetStabilization(on bool) { - b := uint8(0x01) - if !on { - b = 0x00 - } - s.packetChannel <- s.craftPacket([]uint8{b}, 0x02, 0x02) -} - -// Roll sends a roll command to the Sphero gives a speed and heading -func (s *SpheroDriver) Roll(speed uint8, heading uint16) { - s.packetChannel <- s.craftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x02, 0x30) -} - -// ConfigureLocator configures and enables the Locator -func (s *SpheroDriver) ConfigureLocator(d LocatorConfig) { - buf := new(bytes.Buffer) - if err := binary.Write(buf, binary.BigEndian, d); err != nil { - panic(err) - } - - s.packetChannel <- s.craftPacket(buf.Bytes(), 0x02, 0x13) -} - -// SetDataStreaming enables sensor data streaming -func (s *SpheroDriver) SetDataStreaming(d DataStreamingConfig) { - buf := new(bytes.Buffer) - if err := binary.Write(buf, binary.BigEndian, d); err != nil { - panic(err) - } - - s.packetChannel <- s.craftPacket(buf.Bytes(), 0x02, 0x11) -} - -// Stop sets the Sphero to a roll speed of 0 -func (s *SpheroDriver) Stop() { - s.Roll(0, 0) -} - -// ConfigureCollisionDetection configures the sensitivity of the detection. -func (s *SpheroDriver) ConfigureCollisionDetection(cc CollisionConfig) { - s.packetChannel <- s.craftPacket([]uint8{cc.Method, cc.Xt, cc.Yt, cc.Xs, cc.Ys, cc.Dead}, 0x02, 0x12) -} - -// SetCalibration sets up Sphero for manual heading calibration. -// It does this by turning on the tail light (so you can tell where it's -// facing) and disabling stabilization (so you can adjust the heading). -// -// When done, call FinishCalibration to set the new heading, and re-enable -// stabilization. -func (s *SpheroDriver) StartCalibration() { - s.mtx.Lock() - s.originalColor = s.GetRGB() - s.SetRGB(0, 0, 0) - s.SetBackLED(127) - s.SetStabilization(false) - s.mtx.Unlock() -} - -// FinishCalibration ends Sphero's calibration mode, by setting -// the new heading as current, and re-enabling normal defaults. This is a NOP -// in case StartCalibration was not called. -func (s *SpheroDriver) FinishCalibration() { - s.mtx.Lock() - if s.originalColor == nil { - // Piggybacking on the original color being set to know if we are - // calibrating or not. - return - } - - s.SetHeading(0) - s.SetRGB(s.originalColor[0], s.originalColor[1], s.originalColor[2]) - s.SetBackLED(0) - s.SetStabilization(true) - s.originalColor = nil - s.mtx.Unlock() -} - -func (s *SpheroDriver) enableStopOnDisconnect() { - s.packetChannel <- s.craftPacket([]uint8{0x00, 0x00, 0x00, 0x01}, 0x02, 0x37) -} - -func (s *SpheroDriver) handleCollisionDetected(data []uint8) { - // ensure data is the right length: - if len(data) != 22 || data[4] != 17 { - return - } - var collision CollisionPacket - buffer := bytes.NewBuffer(data[5:]) // skip header - if err := binary.Read(buffer, binary.BigEndian, &collision); err != nil { - panic(err) - } - s.Publish(Collision, collision) -} - -func (s *SpheroDriver) handleDataStreaming(data []uint8) { - // ensure data is the right length: - if len(data) != 90 { - return - } - var dataPacket DataStreamingPacket - buffer := bytes.NewBuffer(data[5:]) // skip header - if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { - panic(err) - } - s.Publish(SensorData, dataPacket) -} - -func (s *SpheroDriver) getSyncResponse(packet *packet) []byte { - s.packetChannel <- packet - for i := 0; i < 500; i++ { - for key := range s.syncResponse { - if s.syncResponse[key][3] == packet.header[4] && len(s.syncResponse[key]) > 6 { - var response []byte - response, s.syncResponse = s.syncResponse[len(s.syncResponse)-1], s.syncResponse[:len(s.syncResponse)-1] - return response - } - } - time.Sleep(100 * time.Microsecond) - } - - return []byte{} -} - -func (s *SpheroDriver) craftPacket(body []uint8, did byte, cid byte) *packet { //nolint:unparam // keep did as parameter - s.mtx.Lock() - defer s.mtx.Unlock() - packet := new(packet) - packet.body = body - dlen := len(packet.body) + 1 - packet.header = []uint8{0xFF, 0xFF, did, cid, s.seq, uint8(dlen)} - packet.checksum = s.calculateChecksum(packet) - return packet -} - -func (s *SpheroDriver) write(packet *packet) error { - s.mtx.Lock() - defer s.mtx.Unlock() - buf := append(packet.header, packet.body...) - buf = append(buf, packet.checksum) - length, err := s.adaptor().sp.Write(buf) - if err != nil { - return err - } - - if length != len(buf) { - return errors.New("Not enough bytes written") - } - s.seq++ - return nil -} - -func (s *SpheroDriver) calculateChecksum(packet *packet) uint8 { - buf := append(packet.header, packet.body...) - return calculateChecksum(buf[2:]) -} - -func calculateChecksum(buf []byte) byte { - var calculatedChecksum uint16 - for i := range buf { - calculatedChecksum += uint16(buf[i]) - } - return uint8(^(calculatedChecksum % 256)) -} - -func (s *SpheroDriver) readHeader() []uint8 { - return s.readNextChunk(5) -} - -func (s *SpheroDriver) readBody(length uint8) []uint8 { - return s.readNextChunk(int(length)) -} - -func (s *SpheroDriver) readNextChunk(length int) []uint8 { - read := make([]uint8, length) - bytesRead := 0 - - for bytesRead < length { - time.Sleep(1 * time.Millisecond) - n, err := s.adaptor().sp.Read(read[bytesRead:]) - if err != nil { - return nil - } - bytesRead += n - } - return read -} diff --git a/platforms/sphero/sprkplus/README.md b/platforms/sphero/sprkplus/README.md index 64da9b203..87fcdb3c4 100644 --- a/platforms/sphero/sprkplus/README.md +++ b/platforms/sphero/sprkplus/README.md @@ -16,13 +16,13 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/sprkplus" + "gobot.io/x/gobot/v2/platforms/bleclient" + "gobot.io/x/gobot/v2/drivers/ble/sphero" ) func main() { - bleAdaptor := ble.NewClientAdaptor(os.Args[1]) - sprk := sprkplus.NewDriver(bleAdaptor) + bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + sprk := sphero.NewSPRKPlusDriver(bleAdaptor) work := func() { gobot.Every(1*time.Second, func() { diff --git a/platforms/sphero/sprkplus/doc.go b/platforms/sphero/sprkplus/doc.go deleted file mode 100644 index 93ed883d3..000000000 --- a/platforms/sphero/sprkplus/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -Package sprkplus contains the Gobot driver for the Sphero SPRK+. - -For more information refer to the sprkplus README: -https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/sprkplus/README.md -*/ -package sprkplus // import "gobot.io/x/gobot/v2/platforms/sphero/sprkplus" diff --git a/platforms/sphero/sprkplus/helpers_test.go b/platforms/sphero/sprkplus/helpers_test.go deleted file mode 100644 index b26be641e..000000000 --- a/platforms/sphero/sprkplus/helpers_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package sprkplus - -import ( - "sync" - - "gobot.io/x/gobot/v2/platforms/ble" -) - -var _ ble.BLEConnector = (*bleTestClientAdaptor)(nil) - -type bleTestClientAdaptor struct { - name string - address string - mtx sync.Mutex - withoutResponses bool - - testReadCharacteristic func(string) ([]byte, error) - testWriteCharacteristic func(string, []byte) error -} - -func (t *bleTestClientAdaptor) Connect() error { return nil } -func (t *bleTestClientAdaptor) Reconnect() error { return nil } -func (t *bleTestClientAdaptor) Disconnect() error { return nil } -func (t *bleTestClientAdaptor) Finalize() error { return nil } -func (t *bleTestClientAdaptor) Name() string { return t.name } -func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } -func (t *bleTestClientAdaptor) Address() string { return t.address } -func (t *bleTestClientAdaptor) WithoutResponses(use bool) { t.withoutResponses = use } - -func (t *bleTestClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testReadCharacteristic(cUUID) -} - -func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error { - t.mtx.Lock() - defer t.mtx.Unlock() - return t.testWriteCharacteristic(cUUID, data) -} - -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { - // TODO: implement this... - return nil -} - -func (t *bleTestClientAdaptor) TestReadCharacteristic(f func(cUUID string) (data []byte, err error)) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testReadCharacteristic = f -} - -func (t *bleTestClientAdaptor) TestWriteCharacteristic(f func(cUUID string, data []byte) error) { - t.mtx.Lock() - defer t.mtx.Unlock() - t.testWriteCharacteristic = f -} - -func NewBleTestAdaptor() *bleTestClientAdaptor { - return &bleTestClientAdaptor{ - address: "01:02:03:04:05:06", - testReadCharacteristic: func(cUUID string) ([]byte, error) { - return nil, nil - }, - testWriteCharacteristic: func(cUUID string, data []byte) error { - return nil - }, - } -} diff --git a/platforms/sphero/sprkplus/sprkplus_driver.go b/platforms/sphero/sprkplus/sprkplus_driver.go deleted file mode 100644 index 3f30bb89e..000000000 --- a/platforms/sphero/sprkplus/sprkplus_driver.go +++ /dev/null @@ -1,22 +0,0 @@ -package sprkplus - -import ( - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/ble" - "gobot.io/x/gobot/v2/platforms/sphero/ollie" -) - -// Driver represents a Sphero SPRK+ -type SPRKPlusDriver struct { - *ollie.Driver -} - -// NewDriver creates a Driver for a Sphero SPRK+ -func NewDriver(a ble.BLEConnector) *SPRKPlusDriver { - d := ollie.NewDriver(a) - d.SetName(gobot.DefaultName("SPRKPlus")) - - return &SPRKPlusDriver{ - Driver: d, - } -} diff --git a/platforms/sphero/sprkplus/sprkplus_driver_test.go b/platforms/sphero/sprkplus/sprkplus_driver_test.go deleted file mode 100644 index 67742a13a..000000000 --- a/platforms/sphero/sprkplus/sprkplus_driver_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package sprkplus - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" -) - -var _ gobot.Driver = (*SPRKPlusDriver)(nil) - -func initTestSPRKPlusDriver() *SPRKPlusDriver { - d := NewDriver(NewBleTestAdaptor()) - return d -} - -func TestSPRKPlusDriver(t *testing.T) { - d := initTestSPRKPlusDriver() - assert.True(t, strings.HasPrefix(d.Name(), "SPRK")) - d.SetName("NewName") - assert.Equal(t, "NewName", d.Name()) -} - -func TestSPRKPlusDriverStartAndHalt(t *testing.T) { - d := initTestSPRKPlusDriver() - require.NoError(t, d.Start()) - require.NoError(t, d.Halt()) -} diff --git a/platforms/sphero/sprkplus/sprkplus_packets.go b/platforms/sphero/sprkplus/sprkplus_packets.go deleted file mode 100644 index 7ffeb53a8..000000000 --- a/platforms/sphero/sprkplus/sprkplus_packets.go +++ /dev/null @@ -1,15 +0,0 @@ -package sprkplus - -import "gobot.io/x/gobot/v2/platforms/sphero" - -// DefaultCollisionConfig returns a CollisionConfig with sensible collision defaults -func DefaultCollisionConfig() sphero.CollisionConfig { - return sphero.CollisionConfig{ - Method: 0x01, - Xt: 0x20, - Yt: 0x20, - Xs: 0x20, - Ys: 0x20, - Dead: 0x01, - } -} From d96aa52fb9933401ca7849a5a736c6b026ee3e70 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sat, 10 Feb 2024 18:02:09 +0100 Subject: [PATCH 41/57] ble: add support for functional options, add tests (#1059) --- README.md | 3 +- adaptor.go | 2 +- doc.go | 3 +- driver.go | 2 +- drivers/MIGRATION.md | 38 ++++ drivers/ble/battery_driver.go | 12 +- drivers/ble/battery_driver_test.go | 23 ++- drivers/ble/ble_driver.go | 18 +- drivers/ble/ble_driver_test.go | 30 +++ drivers/ble/device_information_driver.go | 40 ++-- drivers/ble/device_information_driver_test.go | 50 ++++- drivers/ble/generic_access_driver.go | 21 +- drivers/ble/generic_access_driver_test.go | 30 ++- drivers/ble/microbit/accelerometer_driver.go | 6 +- .../ble/microbit/accelerometer_driver_test.go | 15 +- drivers/ble/microbit/button_driver.go | 8 +- drivers/ble/microbit/button_driver_test.go | 15 +- drivers/ble/microbit/io_pin_driver.go | 4 +- drivers/ble/microbit/io_pin_driver_test.go | 13 ++ drivers/ble/microbit/led_driver.go | 4 +- drivers/ble/microbit/led_driver_test.go | 13 ++ drivers/ble/microbit/magnetometer_driver.go | 6 +- .../ble/microbit/magnetometer_driver_test.go | 15 +- drivers/ble/microbit/temperature_driver.go | 6 +- .../ble/microbit/temperature_driver_test.go | 19 +- drivers/ble/parrot/minidrone_driver.go | 8 +- drivers/ble/parrot/minidrone_driver_test.go | 13 ++ drivers/ble/serial_port.go | 6 +- drivers/ble/serial_port_test.go | 190 +++++++++++++++++- drivers/ble/sphero/sphero_bb8_driver.go | 5 +- drivers/ble/sphero/sphero_bb8_driver_test.go | 13 ++ drivers/ble/sphero/sphero_ollie_driver.go | 13 +- .../ble/sphero/sphero_ollie_driver_test.go | 19 +- drivers/ble/sphero/sphero_sprkplus_driver.go | 5 +- .../ble/sphero/sphero_sprkplus_driver_test.go | 13 ++ drivers/ble/testutil/testutil.go | 52 ++++- drivers/serial/serial_driver.go | 8 +- drivers/serial/serial_driver_test.go | 15 ++ drivers/serial/sphero_driver.go | 4 +- drivers/serial/sphero_driver_test.go | 12 ++ examples/ble_battery.go | 6 +- examples/ble_device_info.go | 34 +++- examples/ble_generic_access.go | 13 +- examples/ble_multiple_generic.go | 13 +- examples/ble_multiple_info.go | 34 +++- examples/serial_sphero_conways.go | 3 +- examples/serial_sphero_multiple.go | 3 +- platforms/bleclient/README.md | 6 +- platforms/bleclient/ble_client_adaptor.go | 7 +- platforms/serialport/adaptor_test.go | 38 ++-- 50 files changed, 768 insertions(+), 161 deletions(-) diff --git a/README.md b/README.md index c8b524320..7970c30f5 100644 --- a/README.md +++ b/README.md @@ -174,8 +174,7 @@ import ( func NewSwarmBot(port string) *gobot.Robot { spheroAdaptor := serialport.NewAdaptor(port) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor) - spheroDriver.SetName("Sphero" + port) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero" + port)) work := func() { spheroDriver.Stop() diff --git a/adaptor.go b/adaptor.go index 6eedb50cb..cb66b8315 100644 --- a/adaptor.go +++ b/adaptor.go @@ -235,7 +235,7 @@ type BLEConnector interface { ReadCharacteristic(cUUID string) ([]byte, error) WriteCharacteristic(cUUID string, data []byte) error - Subscribe(cUUID string, f func([]byte, error)) error + Subscribe(cUUID string, f func(data []byte)) error WithoutResponses(use bool) } diff --git a/doc.go b/doc.go index 2f1eee92a..e20fe04e6 100644 --- a/doc.go +++ b/doc.go @@ -85,8 +85,7 @@ Finally, you can use Master Gobot to add the complete Gobot API or control swarm func NewSwarmBot(port string) *gobot.Robot { spheroAdaptor := serialport.NewAdaptor(port) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor) - spheroDriver.SetName("Sphero" + port) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero" + port)) work := func() { spheroDriver.Stop() diff --git a/driver.go b/driver.go index 7581f2826..650de09b3 100644 --- a/driver.go +++ b/driver.go @@ -5,7 +5,7 @@ type Driver interface { // Name returns the label for the Driver Name() string // SetName sets the label for the Driver. - // Please prefer to use options [gpio.WithName or aio.WithName] instead, if possible. + // Please use options [aio.WithName, ble.WithName, gpio.WithName or serial.WithName] instead. SetName(s string) // Start initiates the Driver Start() error diff --git a/drivers/MIGRATION.md b/drivers/MIGRATION.md index 2d80d434d..5f5cabdcf 100644 --- a/drivers/MIGRATION.md +++ b/drivers/MIGRATION.md @@ -39,6 +39,44 @@ import( ... ``` +### BLE client adaptor changed signature for Subscribe() + +Since introducing the usage of "github.com/muka/go-bluetooth" in 2020, the callback do not support the given error +parameter anymore. The switch to usage of "tinygo.org/x/bluetooth" has not changed this. Therefore it is removed now +from the function. + +### BLE generic drivers changed signature for Get*() functions + +All those functions log an error only or panic, so the caller gets no nice programmatic feedback. The error is now +returned instead and the log output needs to be done at caller side. + +```go +// old +... + devName := access.GetDeviceName() + appearance := access.GetAppearance() + modelNo := info.GetModelNumber() + fwRev := info.GetFirmwareRevision() + hwRev := info.GetHardwareRevision() + manuName := info.GetManufacturerName() + pid := info.GetPnPId() + level := battery.GetBatteryLevel() +... + +// new +... + devName, err := access.GetDeviceName() + if err != nil { + fmt.Println(err) + } + appearance, err := access.GetAppearance() + if err != nil { + fmt.Println(err) + } + ... +... +``` + ### Sphero adaptor split off The Serial Based Sphero adaptor was split off into a generic serial adaptor and the driver part. With this, the imports diff --git a/drivers/ble/battery_driver.go b/drivers/ble/battery_driver.go index f97ecafef..9ce222c9c 100644 --- a/drivers/ble/battery_driver.go +++ b/drivers/ble/battery_driver.go @@ -2,7 +2,6 @@ package ble import ( "bytes" - "log" "gobot.io/x/gobot/v2" ) @@ -16,9 +15,9 @@ type BatteryDriver struct { } // NewBatteryDriver creates a new driver -func NewBatteryDriver(a gobot.BLEConnector) *BatteryDriver { +func NewBatteryDriver(a gobot.BLEConnector, opts ...OptionApplier) *BatteryDriver { d := &BatteryDriver{ - Driver: NewDriver(a, "Battery", nil, nil), + Driver: NewDriver(a, "Battery", nil, nil, opts...), Eventer: gobot.NewEventer(), } @@ -26,14 +25,13 @@ func NewBatteryDriver(a gobot.BLEConnector) *BatteryDriver { } // GetBatteryLevel reads and returns the current battery level -func (d *BatteryDriver) GetBatteryLevel() uint8 { +func (d *BatteryDriver) GetBatteryLevel() (uint8, error) { c, err := d.Adaptor().ReadCharacteristic(batteryCharaShort) if err != nil { - log.Println(err) - return 0 + return 0, err } buf := bytes.NewBuffer(c) val, _ := buf.ReadByte() level := val - return level + return level, nil } diff --git a/drivers/ble/battery_driver_test.go b/drivers/ble/battery_driver_test.go index 6495317ff..9fe9f5f63 100644 --- a/drivers/ble/battery_driver_test.go +++ b/drivers/ble/battery_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble/testutil" @@ -13,12 +14,27 @@ import ( var _ gobot.Driver = (*BatteryDriver)(nil) func TestNewBatteryDriver(t *testing.T) { + // arrange d := NewBatteryDriver(testutil.NewBleTestAdaptor()) + // act & assert assert.True(t, strings.HasPrefix(d.Name(), "Battery")) assert.NotNil(t, d.Eventer) } +func TestNewBatteryDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewBatteryDriver(a, WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestBatteryDriverRead(t *testing.T) { + // arrange a := testutil.NewBleTestAdaptor() d := NewBatteryDriver(a) a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { @@ -28,6 +44,9 @@ func TestBatteryDriverRead(t *testing.T) { return nil, nil }) - - assert.Equal(t, uint8(20), d.GetBatteryLevel()) + // act + level, err := d.GetBatteryLevel() + // assert + require.NoError(t, err) + assert.Equal(t, uint8(20), level) } diff --git a/drivers/ble/ble_driver.go b/drivers/ble/ble_driver.go index e1b766b36..3634cbe8a 100644 --- a/drivers/ble/ble_driver.go +++ b/drivers/ble/ble_driver.go @@ -7,8 +7,8 @@ import ( "gobot.io/x/gobot/v2" ) -// optionApplier needs to be implemented by each configurable option type -type optionApplier interface { +// OptionApplier needs to be implemented by each configurable option type +type OptionApplier interface { apply(cfg *configuration) } @@ -31,7 +31,11 @@ type Driver struct { } // NewDriver creates a new basic BLE gobot driver. -func NewDriver(a interface{}, name string, afterStart func() error, beforeHalt func() error) *Driver { +func NewDriver( + a interface{}, name string, + afterStart func() error, beforeHalt func() error, + opts ...OptionApplier, +) *Driver { if afterStart == nil { afterStart = func() error { return nil } } @@ -49,11 +53,15 @@ func NewDriver(a interface{}, name string, afterStart func() error, beforeHalt f mutex: &sync.Mutex{}, } + for _, o := range opts { + o.apply(d.driverCfg) + } + return &d } // WithName is used to replace the default name of the driver. -func WithName(name string) optionApplier { +func WithName(name string) OptionApplier { return nameOption(name) } @@ -63,7 +71,7 @@ func (d *Driver) Name() string { } // SetName sets the name of the driver. -// Deprecated: Please use option [aio.WithName] instead. +// Deprecated: Please use option [ble.WithName] instead. func (d *Driver) SetName(name string) { WithName(name).apply(d.driverCfg) } diff --git a/drivers/ble/ble_driver_test.go b/drivers/ble/ble_driver_test.go index 5e40f313b..14cf1dbbd 100644 --- a/drivers/ble/ble_driver_test.go +++ b/drivers/ble/ble_driver_test.go @@ -37,6 +37,21 @@ func TestNewDriver(t *testing.T) { assert.NotNil(t, d.mutex) } +func TestNewDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + name = "mybot" + newName = "overwrite mybot" + ) + a := testutil.NewBleTestAdaptor() + // act + d := NewDriver(a, name, nil, nil, WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func Test_applyWithName(t *testing.T) { // arrange const name = "mybot" @@ -68,3 +83,18 @@ func TestHalt(t *testing.T) { // act, assert require.EqualError(t, d.Halt(), "before halt error") } + +func TestAdaptor(t *testing.T) { + wrongConnectorType := struct { + a uint32 + }{} + // arrange + a := testutil.NewBleTestAdaptor() + d := NewDriver(a, "BLE_BASIC", nil, nil) + // act, assert + assert.Equal(t, a, d.Adaptor()) + // arrange wrong connector type + d.connection = wrongConnectorType + // act, assert + assert.Nil(t, d.Adaptor()) +} diff --git a/drivers/ble/device_information_driver.go b/drivers/ble/device_information_driver.go index 8eca3c21b..ef6949df7 100644 --- a/drivers/ble/device_information_driver.go +++ b/drivers/ble/device_information_driver.go @@ -2,7 +2,6 @@ package ble import ( "bytes" - "log" "gobot.io/x/gobot/v2" ) @@ -22,9 +21,9 @@ type DeviceInformationDriver struct { } // NewDeviceInformationDriver creates a new driver -func NewDeviceInformationDriver(a gobot.BLEConnector) *DeviceInformationDriver { +func NewDeviceInformationDriver(a gobot.BLEConnector, opts ...OptionApplier) *DeviceInformationDriver { n := &DeviceInformationDriver{ - Driver: NewDriver(a, "DeviceInformation", nil, nil), + Driver: NewDriver(a, "DeviceInformation", nil, nil, opts...), Eventer: gobot.NewEventer(), } @@ -32,61 +31,56 @@ func NewDeviceInformationDriver(a gobot.BLEConnector) *DeviceInformationDriver { } // GetModelNumber returns the model number for the BLE Peripheral -func (d *DeviceInformationDriver) GetModelNumber() string { +func (d *DeviceInformationDriver) GetModelNumber() (string, error) { c, err := d.Adaptor().ReadCharacteristic(deviceInformationModelNumberCharaShort) if err != nil { - log.Println(err) - return "" + return "", err } buf := bytes.NewBuffer(c) model := buf.String() - return model + return model, nil } // GetFirmwareRevision returns the firmware revision for the BLE Peripheral -func (d *DeviceInformationDriver) GetFirmwareRevision() string { +func (d *DeviceInformationDriver) GetFirmwareRevision() (string, error) { c, err := d.Adaptor().ReadCharacteristic(deviceInformationFirmwareRevisionCharaShort) if err != nil { - log.Println(err) - return "" + return "", err } buf := bytes.NewBuffer(c) val := buf.String() - return val + return val, nil } // GetHardwareRevision returns the hardware revision for the BLE Peripheral -func (d *DeviceInformationDriver) GetHardwareRevision() string { +func (d *DeviceInformationDriver) GetHardwareRevision() (string, error) { c, err := d.Adaptor().ReadCharacteristic(deviceInformationHardwareRevisionCharaShort) if err != nil { - log.Println(err) - return "" + return "", err } buf := bytes.NewBuffer(c) val := buf.String() - return val + return val, nil } // GetManufacturerName returns the manufacturer name for the BLE Peripheral -func (d *DeviceInformationDriver) GetManufacturerName() string { +func (d *DeviceInformationDriver) GetManufacturerName() (string, error) { c, err := d.Adaptor().ReadCharacteristic(deviceInformationManufacturerNameCharaShort) if err != nil { - log.Println(err) - return "" + return "", err } buf := bytes.NewBuffer(c) val := buf.String() - return val + return val, nil } // GetPnPId returns the PnP ID for the BLE Peripheral -func (d *DeviceInformationDriver) GetPnPId() string { +func (d *DeviceInformationDriver) GetPnPId() (string, error) { c, err := d.Adaptor().ReadCharacteristic(deviceInformationPnPIdCharaShort) if err != nil { - log.Println(err) - return "" + return "", err } buf := bytes.NewBuffer(c) val := buf.String() - return val + return val, nil } diff --git a/drivers/ble/device_information_driver_test.go b/drivers/ble/device_information_driver_test.go index 976849e6c..38f362b5b 100644 --- a/drivers/ble/device_information_driver_test.go +++ b/drivers/ble/device_information_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble/testutil" @@ -13,32 +14,71 @@ import ( var _ gobot.Driver = (*DeviceInformationDriver)(nil) func TestNewDeviceInformationDriver(t *testing.T) { + // arrange d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) + // act & assert assert.True(t, strings.HasPrefix(d.Name(), "DeviceInformation")) assert.NotNil(t, d.Eventer) } +func TestNewDeviceInformationDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewDeviceInformationDriver(a, WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestDeviceInformationGetModelNumber(t *testing.T) { + // arrange d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) - assert.Equal(t, "2a24", d.GetModelNumber()) + // act + modelNo, err := d.GetModelNumber() + // assert + require.NoError(t, err) + assert.Equal(t, "2a24", modelNo) } func TestDeviceInformationGetFirmwareRevision(t *testing.T) { + // arrange d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) - assert.Equal(t, "2a26", d.GetFirmwareRevision()) + // act + fwRev, err := d.GetFirmwareRevision() + // assert + require.NoError(t, err) + assert.Equal(t, "2a26", fwRev) } func TestDeviceInformationGetHardwareRevision(t *testing.T) { + // arrange d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) - assert.Equal(t, "2a27", d.GetHardwareRevision()) + // act + hwRev, err := d.GetHardwareRevision() + // assert + require.NoError(t, err) + assert.Equal(t, "2a27", hwRev) } func TestDeviceInformationGetManufacturerName(t *testing.T) { + // arrange d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) - assert.Equal(t, "2a29", d.GetManufacturerName()) + // act + manuName, err := d.GetManufacturerName() + // assert + require.NoError(t, err) + assert.Equal(t, "2a29", manuName) } func TestDeviceInformationGetPnPId(t *testing.T) { + // arrange d := NewDeviceInformationDriver(testutil.NewBleTestAdaptor()) - assert.Equal(t, "2a50", d.GetPnPId()) + // act + pid, err := d.GetPnPId() + // assert + require.NoError(t, err) + assert.Equal(t, "2a50", pid) } diff --git a/drivers/ble/generic_access_driver.go b/drivers/ble/generic_access_driver.go index 776db09ce..cdf89a298 100644 --- a/drivers/ble/generic_access_driver.go +++ b/drivers/ble/generic_access_driver.go @@ -3,7 +3,6 @@ package ble import ( "bytes" "encoding/binary" - "log" "gobot.io/x/gobot/v2" ) @@ -20,9 +19,9 @@ type GenericAccessDriver struct { } // NewGenericAccessDriver creates a GenericAccessDriver -func NewGenericAccessDriver(a gobot.BLEConnector) *GenericAccessDriver { +func NewGenericAccessDriver(a gobot.BLEConnector, opts ...OptionApplier) *GenericAccessDriver { d := &GenericAccessDriver{ - Driver: NewDriver(a, "GenericAccess", nil, nil), + Driver: NewDriver(a, "GenericAccess", nil, nil, opts...), Eventer: gobot.NewEventer(), } @@ -30,33 +29,31 @@ func NewGenericAccessDriver(a gobot.BLEConnector) *GenericAccessDriver { } // GetDeviceName returns the device name for the BLE Peripheral -func (d *GenericAccessDriver) GetDeviceName() string { +func (d *GenericAccessDriver) GetDeviceName() (string, error) { c, err := d.Adaptor().ReadCharacteristic(genericAccessDeviceNameCharaShort) if err != nil { - log.Println(err) - return "" + return "", err } buf := bytes.NewBuffer(c) val := buf.String() - return val + return val, nil } // GetAppearance returns the appearance string for the BLE Peripheral -func (d *GenericAccessDriver) GetAppearance() string { +func (d *GenericAccessDriver) GetAppearance() (string, error) { c, err := d.Adaptor().ReadCharacteristic(genericAccessAppearanceCharaShort) if err != nil { - log.Println(err) - return "" + return "", err } buf := bytes.NewBuffer(c) var val uint16 if err := binary.Read(buf, binary.LittleEndian, &val); err != nil { - panic(err) + return "", err } - return appearances[val] + return appearances[val], nil } var appearances = map[uint16]string{ diff --git a/drivers/ble/generic_access_driver_test.go b/drivers/ble/generic_access_driver_test.go index 845cc5881..50d7a65c5 100644 --- a/drivers/ble/generic_access_driver_test.go +++ b/drivers/ble/generic_access_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble/testutil" @@ -13,17 +14,37 @@ import ( var _ gobot.Driver = (*GenericAccessDriver)(nil) func TestNewGenericAccessDriver(t *testing.T) { + // arrange d := NewGenericAccessDriver(testutil.NewBleTestAdaptor()) + // act assert.True(t, strings.HasPrefix(d.Name(), "GenericAccess")) assert.NotNil(t, d.Eventer) } +func TestNewGenericAccessDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewGenericAccessDriver(a, WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestGenericAccessDriverGetDeviceName(t *testing.T) { + // arrange d := NewGenericAccessDriver(testutil.NewBleTestAdaptor()) - assert.Equal(t, "2a00", d.GetDeviceName()) + // act + devName, err := d.GetDeviceName() + // assert + require.NoError(t, err) + assert.Equal(t, "2a00", devName) } func TestGenericAccessDriverGetAppearance(t *testing.T) { + // arrange a := testutil.NewBleTestAdaptor() d := NewGenericAccessDriver(a) a.SetReadCharacteristicTestFunc(func(cUUID string) ([]byte, error) { @@ -32,6 +53,9 @@ func TestGenericAccessDriverGetAppearance(t *testing.T) { } return nil, nil }) - - assert.Equal(t, "Generic Computer", d.GetAppearance()) + // act + app, err := d.GetAppearance() + // assert + require.NoError(t, err) + assert.Equal(t, "Generic Computer", app) } diff --git a/drivers/ble/microbit/accelerometer_driver.go b/drivers/ble/microbit/accelerometer_driver.go index 634bee816..9ffe4c732 100644 --- a/drivers/ble/microbit/accelerometer_driver.go +++ b/drivers/ble/microbit/accelerometer_driver.go @@ -28,11 +28,11 @@ type AccelerometerData struct { } // NewAccelerometerDriver creates a AccelerometerDriver -func NewAccelerometerDriver(a gobot.BLEConnector) *AccelerometerDriver { +func NewAccelerometerDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *AccelerometerDriver { d := &AccelerometerDriver{ Eventer: gobot.NewEventer(), } - d.Driver = ble.NewDriver(a, "Microbit Accelerometer", d.initialize, nil) + d.Driver = ble.NewDriver(a, "Microbit Accelerometer", d.initialize, nil, opts...) d.AddEvent(AccelerometerEvent) @@ -42,7 +42,7 @@ func NewAccelerometerDriver(a gobot.BLEConnector) *AccelerometerDriver { // initialize tells driver to get ready to do work func (d *AccelerometerDriver) initialize() error { // subscribe to accelerometer notifications - return d.Adaptor().Subscribe(accelerometerChara, func(data []byte, e error) { + return d.Adaptor().Subscribe(accelerometerChara, func(data []byte) { a := struct{ x, y, z int16 }{x: 0, y: 0, z: 0} buf := bytes.NewBuffer(data) diff --git a/drivers/ble/microbit/accelerometer_driver_test.go b/drivers/ble/microbit/accelerometer_driver_test.go index fd59c2528..f0db11a3d 100644 --- a/drivers/ble/microbit/accelerometer_driver_test.go +++ b/drivers/ble/microbit/accelerometer_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" ) @@ -22,6 +23,18 @@ func TestNewAccelerometerDriver(t *testing.T) { assert.NotNil(t, d.Eventer) } +func TestNewAccelerometerDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewAccelerometerDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestAccelerometerStartAndHalt(t *testing.T) { d := NewAccelerometerDriver(testutil.NewBleTestAdaptor()) require.NoError(t, d.Start()) @@ -43,7 +56,7 @@ func TestAccelerometerReadData(t *testing.T) { require.NoError(t, err) - a.SendTestDataToSubscriber([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, nil) + a.SendTestDataToSubscriber([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}) select { case <-sem: diff --git a/drivers/ble/microbit/button_driver.go b/drivers/ble/microbit/button_driver.go index a095f3828..e0b2c7bbb 100644 --- a/drivers/ble/microbit/button_driver.go +++ b/drivers/ble/microbit/button_driver.go @@ -21,12 +21,12 @@ type ButtonDriver struct { } // NewButtonDriver creates a new driver -func NewButtonDriver(a gobot.BLEConnector) *ButtonDriver { +func NewButtonDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *ButtonDriver { d := &ButtonDriver{ Eventer: gobot.NewEventer(), } - d.Driver = ble.NewDriver(a, "Microbit Button", d.initialize, nil) + d.Driver = ble.NewDriver(a, "Microbit Button", d.initialize, nil, opts...) d.AddEvent(ButtonAEvent) d.AddEvent(ButtonBEvent) @@ -37,14 +37,14 @@ func NewButtonDriver(a gobot.BLEConnector) *ButtonDriver { // initialize tells driver to get ready to do work func (d *ButtonDriver) initialize() error { // subscribe to button A notifications - if err := d.Adaptor().Subscribe(buttonAChara, func(data []byte, e error) { + if err := d.Adaptor().Subscribe(buttonAChara, func(data []byte) { d.Publish(d.Event(ButtonAEvent), data) }); err != nil { return err } // subscribe to button B notifications - return d.Adaptor().Subscribe(buttonBChara, func(data []byte, e error) { + return d.Adaptor().Subscribe(buttonBChara, func(data []byte) { d.Publish(d.Event(ButtonBEvent), data) }) } diff --git a/drivers/ble/microbit/button_driver_test.go b/drivers/ble/microbit/button_driver_test.go index 886bc05e9..0e6303511 100644 --- a/drivers/ble/microbit/button_driver_test.go +++ b/drivers/ble/microbit/button_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" ) @@ -21,6 +22,18 @@ func TestNewButtonDriver(t *testing.T) { assert.NotNil(t, d.Eventer) } +func TestNewButtonDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewButtonDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestButtonStartAndHalt(t *testing.T) { d := NewButtonDriver(testutil.NewBleTestAdaptor()) require.NoError(t, d.Start()) @@ -38,7 +51,7 @@ func TestButtonReadData(t *testing.T) { }) require.NoError(t, err) - a.SendTestDataToSubscriber([]byte{1}, nil) + a.SendTestDataToSubscriber([]byte{1}) select { case <-sem: diff --git a/drivers/ble/microbit/io_pin_driver.go b/drivers/ble/microbit/io_pin_driver.go index 883568fc3..d45b2d6c2 100644 --- a/drivers/ble/microbit/io_pin_driver.go +++ b/drivers/ble/microbit/io_pin_driver.go @@ -33,12 +33,12 @@ type pinData struct { } // NewIOPinDriver creates a new driver -func NewIOPinDriver(a gobot.BLEConnector) *IOPinDriver { +func NewIOPinDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *IOPinDriver { d := &IOPinDriver{ Eventer: gobot.NewEventer(), } - d.Driver = ble.NewDriver(a, "Microbit IO Pins", d.initialize, nil) + d.Driver = ble.NewDriver(a, "Microbit IO Pins", d.initialize, nil, opts...) return d } diff --git a/drivers/ble/microbit/io_pin_driver_test.go b/drivers/ble/microbit/io_pin_driver_test.go index f73c1d27e..3bdce9f1e 100644 --- a/drivers/ble/microbit/io_pin_driver_test.go +++ b/drivers/ble/microbit/io_pin_driver_test.go @@ -10,6 +10,7 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/aio" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" "gobot.io/x/gobot/v2/drivers/gpio" ) @@ -31,6 +32,18 @@ func TestNewIOPinDriver(t *testing.T) { assert.NotNil(t, d.Eventer) } +func TestNewIOPinDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewIOPinDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestIOPinStartAndHalt(t *testing.T) { a := testutil.NewBleTestAdaptor() d := NewIOPinDriver(a) diff --git a/drivers/ble/microbit/led_driver.go b/drivers/ble/microbit/led_driver.go index 3de8a5b30..7116c4671 100644 --- a/drivers/ble/microbit/led_driver.go +++ b/drivers/ble/microbit/led_driver.go @@ -19,12 +19,12 @@ type LEDDriver struct { } // NewLEDDriver creates a Microbit LEDDriver -func NewLEDDriver(a gobot.BLEConnector) *LEDDriver { +func NewLEDDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *LEDDriver { d := &LEDDriver{ Eventer: gobot.NewEventer(), } - d.Driver = ble.NewDriver(a, "Microbit LED", nil, nil) + d.Driver = ble.NewDriver(a, "Microbit LED", nil, nil, opts...) return d } diff --git a/drivers/ble/microbit/led_driver_test.go b/drivers/ble/microbit/led_driver_test.go index 18e09e7ef..a3ea15b55 100644 --- a/drivers/ble/microbit/led_driver_test.go +++ b/drivers/ble/microbit/led_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" ) @@ -25,6 +26,18 @@ func TestNewLEDDriver(t *testing.T) { assert.NotNil(t, d.Eventer) } +func TestNewLEDDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewLEDDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestLEDWriteMatrix(t *testing.T) { d := initTestLEDDriver() require.NoError(t, d.WriteMatrix([]byte{0x01, 0x02})) diff --git a/drivers/ble/microbit/magnetometer_driver.go b/drivers/ble/microbit/magnetometer_driver.go index 2fb8972e0..630762210 100644 --- a/drivers/ble/microbit/magnetometer_driver.go +++ b/drivers/ble/microbit/magnetometer_driver.go @@ -28,11 +28,11 @@ type MagnetometerData struct { } // NewMagnetometerDriver creates a Microbit MagnetometerDriver -func NewMagnetometerDriver(a gobot.BLEConnector) *MagnetometerDriver { +func NewMagnetometerDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *MagnetometerDriver { d := &MagnetometerDriver{ Eventer: gobot.NewEventer(), } - d.Driver = ble.NewDriver(a, "Microbit Magnetometer", d.initialize, nil) + d.Driver = ble.NewDriver(a, "Microbit Magnetometer", d.initialize, nil, opts...) d.AddEvent(MagnetometerEvent) @@ -42,7 +42,7 @@ func NewMagnetometerDriver(a gobot.BLEConnector) *MagnetometerDriver { // initialize tells driver to get ready to do work func (d *MagnetometerDriver) initialize() error { // subscribe to magnetometer notifications - return d.Adaptor().Subscribe(magnetometerChara, func(data []byte, e error) { + return d.Adaptor().Subscribe(magnetometerChara, func(data []byte) { a := struct{ x, y, z int16 }{x: 0, y: 0, z: 0} buf := bytes.NewBuffer(data) diff --git a/drivers/ble/microbit/magnetometer_driver_test.go b/drivers/ble/microbit/magnetometer_driver_test.go index 9cd098243..d2d8c6639 100644 --- a/drivers/ble/microbit/magnetometer_driver_test.go +++ b/drivers/ble/microbit/magnetometer_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" ) @@ -27,6 +28,18 @@ func TestMagnetometerDriver(t *testing.T) { assert.NotNil(t, d.Eventer) } +func TestNewMagnetometerDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewMagnetometerDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestMagnetometerStartAndHalt(t *testing.T) { d := initTestMagnetometerDriver() require.NoError(t, d.Start()) @@ -46,7 +59,7 @@ func TestMagnetometerReadData(t *testing.T) { }) require.NoError(t, err) - a.SendTestDataToSubscriber([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, nil) + a.SendTestDataToSubscriber([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}) select { case <-sem: diff --git a/drivers/ble/microbit/temperature_driver.go b/drivers/ble/microbit/temperature_driver.go index 6eb6ac373..5e86a3249 100644 --- a/drivers/ble/microbit/temperature_driver.go +++ b/drivers/ble/microbit/temperature_driver.go @@ -21,11 +21,11 @@ type TemperatureDriver struct { } // NewTemperatureDriver creates a Microbit TemperatureDriver -func NewTemperatureDriver(a gobot.BLEConnector) *TemperatureDriver { +func NewTemperatureDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *TemperatureDriver { d := &TemperatureDriver{ Eventer: gobot.NewEventer(), } - d.Driver = ble.NewDriver(a, "Microbit Temperature", d.initialize, nil) + d.Driver = ble.NewDriver(a, "Microbit Temperature", d.initialize, nil, opts...) d.AddEvent(TemperatureEvent) @@ -35,7 +35,7 @@ func NewTemperatureDriver(a gobot.BLEConnector) *TemperatureDriver { // initialize tells driver to get ready to do work func (d *TemperatureDriver) initialize() error { // subscribe to temperature notifications - return d.Adaptor().Subscribe(temperatureChara, func(data []byte, e error) { + return d.Adaptor().Subscribe(temperatureChara, func(data []byte) { var l int8 buf := bytes.NewBuffer(data) val, _ := buf.ReadByte() diff --git a/drivers/ble/microbit/temperature_driver_test.go b/drivers/ble/microbit/temperature_driver_test.go index 070537ddd..ea8984b4c 100644 --- a/drivers/ble/microbit/temperature_driver_test.go +++ b/drivers/ble/microbit/temperature_driver_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" ) @@ -19,13 +20,25 @@ func initTestTemperatureDriver() *TemperatureDriver { return d } -func TestTemperatureDriver(t *testing.T) { - d := initTestTemperatureDriver() +func TestNewTemperatureDriver(t *testing.T) { + d := NewTemperatureDriver(testutil.NewBleTestAdaptor()) assert.IsType(t, &TemperatureDriver{}, d) assert.True(t, strings.HasPrefix(d.Name(), "Microbit Temperature")) assert.NotNil(t, d.Eventer) } +func TestNewTemperatureDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewTemperatureDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestTemperatureStartAndHalt(t *testing.T) { d := initTestTemperatureDriver() require.NoError(t, d.Start()) @@ -43,7 +56,7 @@ func TestTemperatureReadData(t *testing.T) { }) require.NoError(t, err) - a.SendTestDataToSubscriber([]byte{0x22}, nil) + a.SendTestDataToSubscriber([]byte{0x22}) select { case <-sem: diff --git a/drivers/ble/parrot/minidrone_driver.go b/drivers/ble/parrot/minidrone_driver.go index f1fee75cb..e42f1f370 100644 --- a/drivers/ble/parrot/minidrone_driver.go +++ b/drivers/ble/parrot/minidrone_driver.go @@ -81,7 +81,7 @@ type Pcmd struct { } // NewDriver creates a Parrot Minidrone Driver -func NewMinidroneDriver(a gobot.BLEConnector) *MinidroneDriver { +func NewMinidroneDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *MinidroneDriver { d := &MinidroneDriver{ Pcmd: Pcmd{ Flag: 0, @@ -93,7 +93,7 @@ func NewMinidroneDriver(a gobot.BLEConnector) *MinidroneDriver { }, Eventer: gobot.NewEventer(), } - d.Driver = ble.NewDriver(a, "Minidrone", d.initialize, d.shutdown) + d.Driver = ble.NewDriver(a, "Minidrone", d.initialize, d.shutdown, opts...) d.AddEvent(BatteryEvent) d.AddEvent(FlightStatusEvent) @@ -349,14 +349,14 @@ func (d *MinidroneDriver) initialize() error { } // subscribe to battery notifications - if err := d.Adaptor().Subscribe(batteryChara, func(data []byte, e error) { + if err := d.Adaptor().Subscribe(batteryChara, func(data []byte) { d.Publish(d.Event(BatteryEvent), data[len(data)-1]) }); err != nil { return err } // subscribe to flying status notifications - if err := d.Adaptor().Subscribe(flightStatusChara, func(data []byte, e error) { + if err := d.Adaptor().Subscribe(flightStatusChara, func(data []byte) { d.processFlightStatus(data) }); err != nil { return err diff --git a/drivers/ble/parrot/minidrone_driver_test.go b/drivers/ble/parrot/minidrone_driver_test.go index bbae0c67e..add322d30 100644 --- a/drivers/ble/parrot/minidrone_driver_test.go +++ b/drivers/ble/parrot/minidrone_driver_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" ) @@ -27,6 +28,18 @@ func TestNewMinidroneDriver(t *testing.T) { assert.NotNil(t, d.Eventer) } +func TestNewMinidroneDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewMinidroneDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestMinidroneHalt(t *testing.T) { d := initTestMinidroneDriver() require.NoError(t, d.Halt()) diff --git a/drivers/ble/serial_port.go b/drivers/ble/serial_port.go index fbf7addcb..86aefe28c 100644 --- a/drivers/ble/serial_port.go +++ b/drivers/ble/serial_port.go @@ -18,9 +18,9 @@ type SerialPortDriver struct { } // NewSerialPortDriver returns a new serial over Bluetooth LE connection -func NewSerialPortDriver(a gobot.BLEConnector, rid string, tid string) *SerialPortDriver { +func NewSerialPortDriver(a gobot.BLEConnector, rid string, tid string, opts ...OptionApplier) *SerialPortDriver { d := &SerialPortDriver{ - Driver: NewDriver(a, "BleSerial", nil, nil), + Driver: NewDriver(a, "BleSerial", nil, nil, opts...), rid: rid, tid: tid, } @@ -35,7 +35,7 @@ func (p *SerialPortDriver) Open() error { } // subscribe to response notifications - return p.Adaptor().Subscribe(p.rid, func(data []byte, e error) { + return p.Adaptor().Subscribe(p.rid, func(data []byte) { p.responseMutex.Lock() defer p.responseMutex.Unlock() p.responseData = append(p.responseData, data...) diff --git a/drivers/ble/serial_port_test.go b/drivers/ble/serial_port_test.go index 1d045f3b1..9b2df6316 100644 --- a/drivers/ble/serial_port_test.go +++ b/drivers/ble/serial_port_test.go @@ -1,10 +1,12 @@ package ble import ( + "fmt" "io" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble/testutil" @@ -14,7 +16,193 @@ var _ gobot.Driver = (*SerialPortDriver)(nil) var _ io.ReadWriteCloser = (*SerialPortDriver)(nil) -func TestBLESerialPort(t *testing.T) { +func TestNewSerialPortDriver(t *testing.T) { d := NewSerialPortDriver(testutil.NewBleTestAdaptor(), "123", "456") assert.Equal(t, "01:02:03:0A:0B:0C", d.Address()) } + +func TestNewSerialPortDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewSerialPortDriver(a, "123", "456", WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + +func TestSerialPortOpen(t *testing.T) { + const receiveCharacteristicUUID = "123" + tests := map[string]struct { + simConnectErr bool + simSubscribeErr bool + wantErr string + }{ + "open_ok": {}, + "error_connect": { + simConnectErr: true, + wantErr: "connect error", + }, + "error_subscribe": { + simSubscribeErr: true, + wantErr: "subscribe error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := testutil.NewBleTestAdaptor() + a.SetSimulateConnectError(tc.simConnectErr) + a.SetSimulateSubscribeError(tc.simSubscribeErr) + d := NewSerialPortDriver(a, receiveCharacteristicUUID, "456") + // act + err := d.Open() + // assert + if tc.wantErr == "" { + require.NoError(t, err) + a.SendTestDataToSubscriber([]byte{3, 5, 7}) + assert.Equal(t, []byte{3, 5, 7}, d.responseData) + assert.Equal(t, receiveCharacteristicUUID, a.SubscribeCharaUUID()) + } else { + require.EqualError(t, err, tc.wantErr) + } + }) + } +} + +func TestSerialPortRead(t *testing.T) { + tests := map[string]struct { + availableData []byte + readDataBuffer []byte + wantCount int + wantData []byte + wantRemaining []byte + }{ + "no_data": { + availableData: []byte{}, + readDataBuffer: []byte{0, 0, 0}, + wantCount: 0, + wantData: []byte{0, 0, 0}, + wantRemaining: nil, + }, + "read_all": { + availableData: []byte{1, 2, 3}, + readDataBuffer: []byte{0, 0, 0}, + wantCount: 3, + wantData: []byte{1, 2, 3}, + wantRemaining: nil, + }, + "read_smaller": { + availableData: []byte{4, 6, 7}, + readDataBuffer: []byte{0, 0}, + wantCount: 2, + wantData: []byte{4, 6}, + wantRemaining: []byte{7}, + }, + "read_bigger": { + availableData: []byte{7, 8}, + readDataBuffer: []byte{0, 0, 0}, + wantCount: 2, + wantData: []byte{7, 8, 0}, + wantRemaining: nil, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + d := NewSerialPortDriver(testutil.NewBleTestAdaptor(), "123", "456") + d.responseData = append(d.responseData, tc.availableData...) + // act + gotCount, err := d.Read(tc.readDataBuffer) + // assert + require.NoError(t, err) + assert.Equal(t, tc.wantCount, gotCount) + assert.Equal(t, tc.wantData, tc.readDataBuffer) + assert.Equal(t, tc.wantRemaining, d.responseData) + }) + } +} + +func TestSerialPortWrite(t *testing.T) { + const transmitCharacteristicUUID = "456" + tests := map[string]struct { + writeData []byte + simError bool + wantCount int + wantData []byte + wantErr string + }{ + "write_ok": { + writeData: []byte{1, 2, 3}, + wantCount: 3, + wantData: []byte{1, 2, 3}, + }, + "error_write": { + writeData: []byte{1, 2, 3}, + simError: true, + wantCount: 3, + wantData: []byte{1, 2, 3}, + wantErr: "write error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := testutil.NewBleTestAdaptor() + var gotUUID string + var gotData []byte + a.SetWriteCharacteristicTestFunc(func(cUUID string, data []byte) error { + gotUUID = cUUID + gotData = append(gotData, data...) + if tc.simError { + return fmt.Errorf("write error") + } + return nil + }) + d := NewSerialPortDriver(a, "123", transmitCharacteristicUUID) + + // act + gotCount, err := d.Write(tc.writeData) + // assert + if tc.wantErr == "" { + require.NoError(t, err) + } else { + require.EqualError(t, err, tc.wantErr) + } + assert.Equal(t, tc.wantCount, gotCount) + assert.Equal(t, transmitCharacteristicUUID, gotUUID) + assert.Equal(t, tc.wantData, gotData) + }) + } +} + +func TestSerialPortClose(t *testing.T) { + tests := map[string]struct { + simDisconnectErr bool + wantErr string + }{ + "close_ok": {}, + "error_close": { + simDisconnectErr: true, + wantErr: "disconnect error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := testutil.NewBleTestAdaptor() + a.SetSimulateDisconnectError(tc.simDisconnectErr) + d := NewSerialPortDriver(a, "123", "456") + // act + err := d.Close() + // assert + if tc.wantErr == "" { + require.NoError(t, err) + } else { + require.EqualError(t, err, tc.wantErr) + } + }) + } +} diff --git a/drivers/ble/sphero/sphero_bb8_driver.go b/drivers/ble/sphero/sphero_bb8_driver.go index e1a459cbc..ee6f9088b 100644 --- a/drivers/ble/sphero/sphero_bb8_driver.go +++ b/drivers/ble/sphero/sphero_bb8_driver.go @@ -2,6 +2,7 @@ package sphero import ( "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/common/sphero" ) @@ -11,8 +12,8 @@ type BB8Driver struct { } // NewBB8Driver creates a driver for a Sphero BB-8 -func NewBB8Driver(a gobot.BLEConnector) *BB8Driver { - return &BB8Driver{OllieDriver: newOllieBaseDriver(a, "BB8", bb8DefaultCollisionConfig())} +func NewBB8Driver(a gobot.BLEConnector, opts ...ble.OptionApplier) *BB8Driver { + return &BB8Driver{OllieDriver: newOllieBaseDriver(a, "BB8", bb8DefaultCollisionConfig(), opts...)} } // bb8DefaultCollisionConfig returns a CollisionConfig with sensible collision defaults diff --git a/drivers/ble/sphero/sphero_bb8_driver_test.go b/drivers/ble/sphero/sphero_bb8_driver_test.go index 962239cc0..145c9c41e 100644 --- a/drivers/ble/sphero/sphero_bb8_driver_test.go +++ b/drivers/ble/sphero/sphero_bb8_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" ) @@ -19,3 +20,15 @@ func TestNewBB8Driver(t *testing.T) { assert.NotNil(t, d.OllieDriver) assert.Equal(t, d.defaultCollisionConfig, bb8DefaultCollisionConfig()) } + +func TestNewBB8DriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewBB8Driver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} diff --git a/drivers/ble/sphero/sphero_ollie_driver.go b/drivers/ble/sphero/sphero_ollie_driver.go index fffc4a008..81c2daf9b 100644 --- a/drivers/ble/sphero/sphero_ollie_driver.go +++ b/drivers/ble/sphero/sphero_ollie_driver.go @@ -74,17 +74,20 @@ type OllieDriver struct { } // NewOllieDriver creates a driver for a Sphero Ollie -func NewOllieDriver(a gobot.BLEConnector) *OllieDriver { - return newOllieBaseDriver(a, "Ollie", ollieDefaultCollisionConfig()) +func NewOllieDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *OllieDriver { + return newOllieBaseDriver(a, "Ollie", ollieDefaultCollisionConfig(), opts...) } -func newOllieBaseDriver(a gobot.BLEConnector, name string, dcc sphero.CollisionConfig) *OllieDriver { +func newOllieBaseDriver( + a gobot.BLEConnector, name string, + dcc sphero.CollisionConfig, opts ...ble.OptionApplier, +) *OllieDriver { d := &OllieDriver{ defaultCollisionConfig: dcc, Eventer: gobot.NewEventer(), packetChannel: make(chan *packet, 1024), } - d.Driver = ble.NewDriver(a, name, d.initialize, d.shutdown) + d.Driver = ble.NewDriver(a, name, d.initialize, d.shutdown, opts...) d.AddEvent(sphero.ErrorEvent) d.AddEvent(sphero.CollisionEvent) @@ -283,7 +286,7 @@ func (d *OllieDriver) shutdown() error { } // handleResponses handles responses returned from Ollie -func (d *OllieDriver) handleResponses(data []byte, e error) { +func (d *OllieDriver) handleResponses(data []byte) { // since packets can only be 20 bytes long, we have to puzzle them together newMessage := false diff --git a/drivers/ble/sphero/sphero_ollie_driver_test.go b/drivers/ble/sphero/sphero_ollie_driver_test.go index d4758c970..671cd1758 100644 --- a/drivers/ble/sphero/sphero_ollie_driver_test.go +++ b/drivers/ble/sphero/sphero_ollie_driver_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" "gobot.io/x/gobot/v2/drivers/common/sphero" ) @@ -29,6 +30,18 @@ func TestNewOllieDriver(t *testing.T) { assert.NotNil(t, d.packetChannel) } +func TestNewOllieDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewOllieDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestOllieStartAndHalt(t *testing.T) { d := initTestOllieDriver() require.NoError(t, d.Start()) @@ -62,7 +75,7 @@ func TestLocatorData(t *testing.T) { d.GetLocatorData(func(p Point2D) { assert.Equal(t, point.y, p.Y) }) - d.handleResponses(packet, nil) + d.handleResponses(packet) } } @@ -100,11 +113,11 @@ func TestDataStreaming(t *testing.T) { c := uint16(b) bytes = append(bytes, byte(c)) } - d.handleResponses(bytes, nil) + d.handleResponses(bytes) } // send empty packet to indicate start of next message - d.handleResponses([]byte{0xFF}, nil) + d.handleResponses([]byte{0xFF}) select { case <-responseChan: case <-time.After(10 * time.Millisecond): diff --git a/drivers/ble/sphero/sphero_sprkplus_driver.go b/drivers/ble/sphero/sphero_sprkplus_driver.go index 744d571c9..75af9f310 100644 --- a/drivers/ble/sphero/sphero_sprkplus_driver.go +++ b/drivers/ble/sphero/sphero_sprkplus_driver.go @@ -2,6 +2,7 @@ package sphero import ( "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/common/sphero" ) @@ -11,8 +12,8 @@ type SPRKPlusDriver struct { } // NewSPRKPlusDriver creates a driver for a Sphero SPRK+ -func NewSPRKPlusDriver(a gobot.BLEConnector) *SPRKPlusDriver { - return &SPRKPlusDriver{OllieDriver: newOllieBaseDriver(a, "SPRKPlus", sprkplusDefaultCollisionConfig())} +func NewSPRKPlusDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *SPRKPlusDriver { + return &SPRKPlusDriver{OllieDriver: newOllieBaseDriver(a, "SPRKPlus", sprkplusDefaultCollisionConfig(), opts...)} } // sprkplusDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults diff --git a/drivers/ble/sphero/sphero_sprkplus_driver_test.go b/drivers/ble/sphero/sphero_sprkplus_driver_test.go index 382c08ed0..ed74f2d85 100644 --- a/drivers/ble/sphero/sphero_sprkplus_driver_test.go +++ b/drivers/ble/sphero/sphero_sprkplus_driver_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" ) @@ -19,3 +20,15 @@ func TestNewSPRKPlusDriver(t *testing.T) { assert.NotNil(t, d.OllieDriver) assert.Equal(t, d.defaultCollisionConfig, sprkplusDefaultCollisionConfig()) } + +func TestNewSPRKPlusDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := testutil.NewBleTestAdaptor() + // act + d := NewSPRKPlusDriver(a, ble.WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} diff --git a/drivers/ble/testutil/testutil.go b/drivers/ble/testutil/testutil.go index 4724e5689..58f8e558e 100644 --- a/drivers/ble/testutil/testutil.go +++ b/drivers/ble/testutil/testutil.go @@ -1,6 +1,7 @@ package testutil import ( + "fmt" "sync" "gobot.io/x/gobot/v2" @@ -14,9 +15,13 @@ type bleTestClientAdaptor struct { mtx sync.Mutex withoutResponses bool + simulateConnectErr bool + simulateSubscribeErr bool + simulateDisconnectErr bool readCharacteristicFunc func(string) ([]byte, error) writeCharacteristicFunc func(string, []byte) error - subscribeFunc func([]byte, error) + subscribeFunc func([]byte) + subscribeCharaUUID string } func NewBleTestAdaptor() *bleTestClientAdaptor { @@ -31,6 +36,10 @@ func NewBleTestAdaptor() *bleTestClientAdaptor { } } +func (t *bleTestClientAdaptor) SubscribeCharaUUID() string { + return t.subscribeCharaUUID +} + func (t *bleTestClientAdaptor) SetReadCharacteristicTestFunc(f func(cUUID string) (data []byte, err error)) { t.mtx.Lock() defer t.mtx.Unlock() @@ -43,15 +52,40 @@ func (t *bleTestClientAdaptor) SetWriteCharacteristicTestFunc(f func(cUUID strin t.writeCharacteristicFunc = f } -func (t *bleTestClientAdaptor) SendTestDataToSubscriber(data []byte, err error) { +func (t *bleTestClientAdaptor) SetSimulateConnectError(val bool) { + t.simulateConnectErr = val +} + +func (t *bleTestClientAdaptor) SetSimulateSubscribeError(val bool) { + t.simulateSubscribeErr = val +} + +func (t *bleTestClientAdaptor) SetSimulateDisconnectError(val bool) { + t.simulateDisconnectErr = val +} + +func (t *bleTestClientAdaptor) SendTestDataToSubscriber(data []byte) { t.mtx.Lock() defer t.mtx.Unlock() - t.subscribeFunc(data, err) + t.subscribeFunc(data) +} + +func (t *bleTestClientAdaptor) Connect() error { + if t.simulateConnectErr { + return fmt.Errorf("connect error") + } + return nil +} + +func (t *bleTestClientAdaptor) Reconnect() error { return nil } + +func (t *bleTestClientAdaptor) Disconnect() error { + if t.simulateDisconnectErr { + return fmt.Errorf("disconnect error") + } + return nil } -func (t *bleTestClientAdaptor) Connect() error { return nil } -func (t *bleTestClientAdaptor) Reconnect() error { return nil } -func (t *bleTestClientAdaptor) Disconnect() error { return nil } func (t *bleTestClientAdaptor) Finalize() error { return nil } func (t *bleTestClientAdaptor) Name() string { return t.name } func (t *bleTestClientAdaptor) SetName(n string) { t.name = n } @@ -70,7 +104,11 @@ func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) er return t.writeCharacteristicFunc(cUUID, data) } -func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func([]byte, error)) error { +func (t *bleTestClientAdaptor) Subscribe(cUUID string, f func(data []byte)) error { + if t.simulateSubscribeErr { + return fmt.Errorf("subscribe error") + } + t.subscribeCharaUUID = cUUID t.subscribeFunc = f return nil } diff --git a/drivers/serial/serial_driver.go b/drivers/serial/serial_driver.go index 9b1aaf724..32e8ec7e7 100644 --- a/drivers/serial/serial_driver.go +++ b/drivers/serial/serial_driver.go @@ -39,7 +39,7 @@ type driver struct { } // newDriver creates a new basic serial gobot driver. -func newDriver(a interface{}, name string) *driver { +func newDriver(a interface{}, name string, opts ...optionApplier) *driver { d := driver{ Commander: gobot.NewCommander(), connection: a, @@ -49,6 +49,10 @@ func newDriver(a interface{}, name string) *driver { mutex: &sync.Mutex{}, } + for _, o := range opts { + o.apply(d.driverCfg) + } + return &d } @@ -63,7 +67,7 @@ func (d *driver) Name() string { } // SetName sets the name of the driver. -// Deprecated: Please use option [aio.WithName] instead. +// Deprecated: Please use option [serial.WithName] instead. func (d *driver) SetName(name string) { WithName(name).apply(d.driverCfg) } diff --git a/drivers/serial/serial_driver_test.go b/drivers/serial/serial_driver_test.go index b2dda80c6..7e965b609 100644 --- a/drivers/serial/serial_driver_test.go +++ b/drivers/serial/serial_driver_test.go @@ -36,6 +36,21 @@ func Test_newDriver(t *testing.T) { assert.NotNil(t, d.mutex) } +func Test_newDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const ( + name = "mybot" + newName = "overwrite mybot" + ) + a := newSerialTestAdaptor() + // act + d := newDriver(a, name, WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func Test_applyWithName(t *testing.T) { // arrange const name = "mybot" diff --git a/drivers/serial/sphero_driver.go b/drivers/serial/sphero_driver.go index b65c52f7b..6bdd969f5 100644 --- a/drivers/serial/sphero_driver.go +++ b/drivers/serial/sphero_driver.go @@ -51,9 +51,9 @@ type SpheroDriver struct { // "SetStabilization" - See SpheroDriver.SetStabilization // "SetDataStreaming" - See SpheroDriver.SetDataStreaming // "SetRotationRate" - See SpheroDriver.SetRotationRate -func NewSpheroDriver(a spheroSerialAdaptor) *SpheroDriver { +func NewSpheroDriver(a spheroSerialAdaptor, opts ...optionApplier) *SpheroDriver { d := &SpheroDriver{ - driver: newDriver(a, "Sphero"), + driver: newDriver(a, "Sphero", opts...), Eventer: gobot.NewEventer(), packetChannel: make(chan *packet, 1024), responseChannel: make(chan []uint8, 1024), diff --git a/drivers/serial/sphero_driver_test.go b/drivers/serial/sphero_driver_test.go index 417f474d0..55f57d23c 100644 --- a/drivers/serial/sphero_driver_test.go +++ b/drivers/serial/sphero_driver_test.go @@ -27,6 +27,18 @@ func TestNewSpheroDriver(t *testing.T) { assert.NotNil(t, d.Eventer) } +func TestNewSpheroDriverWithName(t *testing.T) { + // This is a general test, that options are applied in constructor by using the common WithName() option. Further + // tests for options can also be done by call of "WithOption(val).apply(cfg)". + // arrange + const newName = "new name" + a := newSerialTestAdaptor() + // act + d := NewSpheroDriver(a, WithName(newName)) + // assert + assert.Equal(t, newName, d.Name()) +} + func TestSpheroCommands(t *testing.T) { d := initTestSpheroDriver() var ret interface{} diff --git a/examples/ble_battery.go b/examples/ble_battery.go index 4656954fa..22276b2b6 100644 --- a/examples/ble_battery.go +++ b/examples/ble_battery.go @@ -31,7 +31,11 @@ func main() { work := func() { gobot.Every(5*time.Second, func() { - fmt.Println("Battery level:", battery.GetBatteryLevel()) + level, err := battery.GetBatteryLevel() + if err != nil { + fmt.Println(err) + } + fmt.Println("Battery level:", level) }) } diff --git a/examples/ble_device_info.go b/examples/ble_device_info.go index bff64e7e9..e463a8ccb 100644 --- a/examples/ble_device_info.go +++ b/examples/ble_device_info.go @@ -29,11 +29,35 @@ func main() { info := ble.NewDeviceInformationDriver(bleAdaptor) work := func() { - fmt.Println("Model number:", info.GetModelNumber()) - fmt.Println("Firmware rev:", info.GetFirmwareRevision()) - fmt.Println("Hardware rev:", info.GetHardwareRevision()) - fmt.Println("Manufacturer name:", info.GetManufacturerName()) - fmt.Println("PnPId:", info.GetPnPId()) + modelNo, err := info.GetModelNumber() + if err != nil { + fmt.Println(err) + } + fmt.Println("Model number:", modelNo) + + fwRev, err := info.GetFirmwareRevision() + if err != nil { + fmt.Println(err) + } + fmt.Println("Firmware rev:", fwRev) + + hwRev, err := info.GetHardwareRevision() + if err != nil { + fmt.Println(err) + } + fmt.Println("Hardware rev:", hwRev) + + manuName, err := info.GetManufacturerName() + if err != nil { + fmt.Println(err) + } + fmt.Println("Manufacturer name:", manuName) + + pid, err := info.GetPnPId() + if err != nil { + fmt.Println(err) + } + fmt.Println("PnPId:", pid) } robot := gobot.NewRobot("bleBot", diff --git a/examples/ble_generic_access.go b/examples/ble_generic_access.go index 416571206..aa77064a6 100644 --- a/examples/ble_generic_access.go +++ b/examples/ble_generic_access.go @@ -29,8 +29,17 @@ func main() { access := ble.NewGenericAccessDriver(bleAdaptor) work := func() { - fmt.Println("Device name:", access.GetDeviceName()) - fmt.Println("Appearance:", access.GetAppearance()) + devName, err := access.GetDeviceName() + if err != nil { + fmt.Println(err) + } + fmt.Println("Device name:", devName) + + appearance, err := access.GetAppearance() + if err != nil { + fmt.Println(err) + } + fmt.Println("Appearance:", appearance) } robot := gobot.NewRobot("bleBot", diff --git a/examples/ble_multiple_generic.go b/examples/ble_multiple_generic.go index bbce13d9e..ddc7d313f 100644 --- a/examples/ble_multiple_generic.go +++ b/examples/ble_multiple_generic.go @@ -30,8 +30,17 @@ func NewSwarmBot(port string) *gobot.Robot { access := ble.NewGenericAccessDriver(bleAdaptor) work := func() { - fmt.Println("Device name:", access.GetDeviceName()) - fmt.Println("Appearance:", access.GetAppearance()) + devName, err := access.GetDeviceName() + if err != nil { + fmt.Println(err) + } + fmt.Println("Device name:", devName) + + appearance, err := access.GetAppearance() + if err != nil { + fmt.Println(err) + } + fmt.Println("Appearance:", appearance) } robot := gobot.NewRobot("bot "+port, diff --git a/examples/ble_multiple_info.go b/examples/ble_multiple_info.go index 6155138b3..b4960e9a5 100644 --- a/examples/ble_multiple_info.go +++ b/examples/ble_multiple_info.go @@ -30,11 +30,35 @@ func NewSwarmBot(port string) *gobot.Robot { info := ble.NewDeviceInformationDriver(bleAdaptor) work := func() { - fmt.Println("Model number:", info.GetModelNumber()) - fmt.Println("Firmware rev:", info.GetFirmwareRevision()) - fmt.Println("Hardware rev:", info.GetHardwareRevision()) - fmt.Println("Manufacturer name:", info.GetManufacturerName()) - fmt.Println("PnPId:", info.GetPnPId()) + modelNo, err := info.GetModelNumber() + if err != nil { + fmt.Println(err) + } + fmt.Println("Model number:", modelNo) + + fwRev, err := info.GetFirmwareRevision() + if err != nil { + fmt.Println(err) + } + fmt.Println("Firmware rev:", fwRev) + + hwRev, err := info.GetHardwareRevision() + if err != nil { + fmt.Println(err) + } + fmt.Println("Hardware rev:", hwRev) + + manuName, err := info.GetManufacturerName() + if err != nil { + fmt.Println(err) + } + fmt.Println("Manufacturer name:", manuName) + + pid, err := info.GetPnPId() + if err != nil { + fmt.Println(err) + } + fmt.Println("PnPId:", pid) } robot := gobot.NewRobot("bot "+port, diff --git a/examples/serial_sphero_conways.go b/examples/serial_sphero_conways.go index 5113ab5a0..c03a0b2df 100644 --- a/examples/serial_sphero_conways.go +++ b/examples/serial_sphero_conways.go @@ -35,8 +35,7 @@ func main() { for _, port := range spheros { spheroAdaptor := serialport.NewAdaptor(port) - cell := serial.NewSpheroDriver(spheroAdaptor) - cell.SetName("Sphero" + port) + cell := serial.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero"+port)) work := func() { conway := new(conway) diff --git a/examples/serial_sphero_multiple.go b/examples/serial_sphero_multiple.go index c728ce9ff..a5ab95b02 100644 --- a/examples/serial_sphero_multiple.go +++ b/examples/serial_sphero_multiple.go @@ -19,8 +19,7 @@ import ( func NewSwarmBot(port string) *gobot.Robot { spheroAdaptor := serialport.NewAdaptor(port) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor) - spheroDriver.SetName("Sphero" + port) + spheroDriver := serial.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero"+port)) work := func() { spheroDriver.Stop() diff --git a/platforms/bleclient/README.md b/platforms/bleclient/README.md index c243cf7a7..271c93880 100644 --- a/platforms/bleclient/README.md +++ b/platforms/bleclient/README.md @@ -71,7 +71,11 @@ func main() { work := func() { gobot.Every(5*time.Second, func() { - fmt.Println("Battery level:", battery.GetBatteryLevel()) + level, err := battery.GetBatteryLevel() + if err != nil { + fmt.Println(err) + } + fmt.Println("Battery level:", level) }) } diff --git a/platforms/bleclient/ble_client_adaptor.go b/platforms/bleclient/ble_client_adaptor.go index f73605930..ffc09f155 100644 --- a/platforms/bleclient/ble_client_adaptor.go +++ b/platforms/bleclient/ble_client_adaptor.go @@ -181,7 +181,7 @@ func (a *Adaptor) WriteCharacteristic(cUUID string, data []byte) error { // Subscribe subscribes to notifications from the BLE device for the // requested service and characteristic -func (a *Adaptor) Subscribe(cUUID string, f func([]byte, error)) error { +func (a *Adaptor) Subscribe(cUUID string, f func([]byte)) error { if !a.connected { return fmt.Errorf("Cannot subscribe to BLE device until connected") } @@ -189,10 +189,7 @@ func (a *Adaptor) Subscribe(cUUID string, f func([]byte, error)) error { cUUID = convertUUID(cUUID) if char, ok := a.characteristics[cUUID]; ok { - fn := func(d []byte) { - f(d, nil) - } - return char.EnableNotifications(fn) + return char.EnableNotifications(f) } return fmt.Errorf("Unknown characteristic: %s", cUUID) diff --git a/platforms/serialport/adaptor_test.go b/platforms/serialport/adaptor_test.go index 65d7a4486..dd5321e8e 100644 --- a/platforms/serialport/adaptor_test.go +++ b/platforms/serialport/adaptor_test.go @@ -46,7 +46,7 @@ func NewNullReadWriteCloser() *nullReadWriteCloser { } } -func initTestSpheroAdaptor() (*Adaptor, *nullReadWriteCloser) { +func initTestAdaptor() (*Adaptor, *nullReadWriteCloser) { a := NewAdaptor("/dev/null") rwc := NewNullReadWriteCloser() @@ -56,34 +56,34 @@ func initTestSpheroAdaptor() (*Adaptor, *nullReadWriteCloser) { return a, rwc } -func TestSpheroAdaptorName(t *testing.T) { - a, _ := initTestSpheroAdaptor() +func TestNewAdaptor(t *testing.T) { + a := NewAdaptor("/dev/null") assert.True(t, strings.HasPrefix(a.Name(), "Serial")) - a.SetName("NewName") - assert.Equal(t, "NewName", a.Name()) + assert.Equal(t, "/dev/null", a.Port()) } -func TestSpheroAdaptor(t *testing.T) { - a, _ := initTestSpheroAdaptor() +func TestName(t *testing.T) { + a, _ := initTestAdaptor() assert.True(t, strings.HasPrefix(a.Name(), "Serial")) - assert.Equal(t, "/dev/null", a.Port()) + a.SetName("NewName") + assert.Equal(t, "NewName", a.Name()) } -func TestSpheroAdaptorReconnect(t *testing.T) { - a, _ := initTestSpheroAdaptor() - _ = a.Connect() +func TestReconnect(t *testing.T) { + a, _ := initTestAdaptor() + require.NoError(t, a.Connect()) assert.True(t, a.connected) - _ = a.Reconnect() + require.NoError(t, a.Reconnect()) assert.True(t, a.connected) - _ = a.Disconnect() + require.NoError(t, a.Disconnect()) assert.False(t, a.connected) - _ = a.Reconnect() + require.NoError(t, a.Reconnect()) assert.True(t, a.connected) } -func TestSpheroAdaptorFinalize(t *testing.T) { - a, rwc := initTestSpheroAdaptor() - _ = a.Connect() +func TestFinalize(t *testing.T) { + a, rwc := initTestAdaptor() + require.NoError(t, a.Connect()) require.NoError(t, a.Finalize()) rwc.testAdaptorClose = func() error { @@ -94,8 +94,8 @@ func TestSpheroAdaptorFinalize(t *testing.T) { require.ErrorContains(t, a.Finalize(), "close error") } -func TestSpheroAdaptorConnect(t *testing.T) { - a, _ := initTestSpheroAdaptor() +func TestConnect(t *testing.T) { + a, _ := initTestAdaptor() require.NoError(t, a.Connect()) a.connect = func(string) (io.ReadWriteCloser, error) { From d2b01b99e042a2707972e8df810a22cb2dbf41ad Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 11 Feb 2024 15:34:50 +0100 Subject: [PATCH 42/57] examples: fix missing checks of return values (#1060) --- .circleci/config.yml | 17 +++ Makefile | 8 +- README.md | 30 ++-- doc.go | 26 +++- drivers/MIGRATION.md | 4 +- examples/ardrone.go | 6 +- examples/ardrone_face_tracking.go | 6 +- examples/ardrone_ps3.go | 18 +-- examples/audio.go | 4 +- examples/batty.go | 4 +- examples/beaglebone_basic_direct_pin.go | 10 +- examples/beaglebone_blink.go | 9 +- examples/beaglebone_blink_usr_led.go | 9 +- examples/beaglebone_blinkm.go | 13 +- examples/beaglebone_button.go | 8 +- examples/beaglebone_direct_pin.go | 13 +- examples/beaglebone_grove_accelerometer.go | 4 +- examples/beaglebone_led_brightness.go | 9 +- ...lebone_led_brightness_with_analog_input.go | 10 +- examples/beaglebone_servo.go | 8 +- examples/bebop.go | 15 +- examples/bebop_ps3.go | 89 ++++++++---- examples/bebop_ps3_video.go | 108 +++++++++----- examples/bebop_rtp_video.go | 10 +- .../{ble_battery.go => bleclient_battery.go} | 4 +- ...ollision.go => bleclient_bb8-collision.go} | 6 +- examples/{ble_bb8.go => bleclient_bb8.go} | 4 +- ...evice_info.go => bleclient_device_info.go} | 4 +- ...ta_blink.go => bleclient_firmata_blink.go} | 9 +- ..._imu.go => bleclient_firmata_curie_imu.go} | 27 ++-- ..._access.go => bleclient_generic_access.go} | 4 +- ...go => bleclient_microbit_accelerometer.go} | 6 +- ...t_blink.go => bleclient_microbit_blink.go} | 9 +- ...ttons.go => bleclient_microbit_buttons.go} | 8 +- ....go => bleclient_microbit_buttons_leds.go} | 25 +++- ...ton.go => bleclient_microbit_io_button.go} | 17 ++- ...robit_led.go => bleclient_microbit_led.go} | 17 ++- ....go => bleclient_microbit_magnetometer.go} | 6 +- ...e.go => bleclient_microbit_temperature.go} | 6 +- .../{minidrone.go => bleclient_minidrone.go} | 13 +- ...vents.go => bleclient_minidrone_events.go} | 24 ++-- ...s3.go => bleclient_minidrone_mambo_ps3.go} | 97 +++++++++---- ...rone_ps3.go => bleclient_minidrone_ps3.go} | 93 ++++++++---- ...neric.go => bleclient_multiple_generic.go} | 4 +- ...ple_info.go => bleclient_multiple_info.go} | 4 +- examples/{ble_ollie.go => bleclient_ollie.go} | 4 +- ...llie_boost.go => bleclient_ollie_boost.go} | 4 +- ...llie_crazy.go => bleclient_ollie_crazy.go} | 4 +- ..._ollie_mqtt.go => bleclient_ollie_mqtt.go} | 14 +- ...ultiple.go => bleclient_ollie_multiple.go} | 4 +- ..._ollie_roll.go => bleclient_ollie_roll.go} | 4 +- ..._ollie_spin.go => bleclient_ollie_spin.go} | 4 +- ...{ble_sprkplus.go => bleclient_sprkplus.go} | 4 +- ...ion.go => bleclient_sprkplus_collision.go} | 6 +- examples/chip_blink.go | 9 +- examples/chip_blinkm.go | 13 +- examples/chip_button.go | 8 +- examples/chip_button_led.go | 18 ++- examples/chip_drv2605l.go | 13 +- examples/chip_grove_accelerometer.go | 4 +- examples/chip_grove_lcd.go | 46 ++++-- examples/chip_mpu6050.go | 8 +- examples/chip_tsl2561.go | 4 +- examples/chip_wiichuck.go | 12 +- examples/digispark_api.go | 4 +- examples/digispark_blink.go | 9 +- examples/digispark_blinkm.go | 14 +- examples/digispark_driver.go | 5 +- examples/digispark_led_brightness.go | 9 +- examples/digispark_mpl115a2.go | 5 +- examples/digispark_pca9501.go | 5 +- examples/digispark_servo.go | 8 +- examples/dragonboard_button.go | 8 +- examples/edison_blink.go | 9 +- ...dison_blink_without_all_gobot_framework.go | 13 +- examples/edison_blinkm.go | 13 +- examples/edison_bme280.go | 5 +- examples/edison_button.go | 18 ++- examples/edison_button_led.go | 18 ++- examples/edison_button_led_api.go | 21 ++- examples/edison_grove_accelerometer.go | 4 +- examples/edison_grove_blink.go | 9 +- examples/edison_grove_button.go | 8 +- examples/edison_grove_buzzer.go | 9 +- examples/edison_grove_lcd.go | 45 ++++-- examples/edison_grove_led.go | 9 +- examples/edison_grove_light_sensor.go | 6 +- 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 +- examples/edison_grove_touch.go | 8 +- examples/edison_led_brightness.go | 9 +- ...edison_led_brightness_with_analog_input.go | 10 +- .../edison_miniboard_grove_accelerometer.go | 4 +- examples/edison_rgb_led.go | 9 +- examples/every_done.go | 4 +- examples/firmata_adxl345.go | 4 +- examples/firmata_aip1640.go | 9 +- examples/firmata_blink.go | 9 +- examples/firmata_blink_api.go | 9 +- examples/firmata_blink_metal.go | 13 +- examples/firmata_blink_robot.go | 9 +- examples/firmata_blinkm.go | 13 +- examples/firmata_bme280.go | 4 +- examples/firmata_bmp180.go | 4 +- examples/firmata_bmp280.go | 4 +- examples/firmata_button.go | 17 ++- examples/firmata_buzzer.go | 9 +- examples/firmata_cat_toy.go | 14 +- examples/firmata_curie_imu.go | 33 +++-- examples/firmata_curie_imu_shock_detect.go | 15 +- examples/firmata_curie_imu_step_counter.go | 15 +- examples/firmata_curie_imu_tap_detect.go | 15 +- examples/firmata_direct_pin.go | 9 +- examples/firmata_gpio_max7219.go | 13 +- examples/firmata_grove_lcd.go | 45 ++++-- examples/firmata_grove_sound_sensor.go | 6 +- examples/firmata_hmc6352.go | 4 +- examples/firmata_integration.go | 26 ++-- examples/firmata_led_brightness.go | 9 +- ...irmata_led_brightness_with_analog_input.go | 10 +- examples/firmata_lidarlite.go | 4 +- examples/firmata_metal_button.go | 20 ++- examples/firmata_mma7660.go | 4 +- examples/firmata_motor.go | 9 +- examples/firmata_mpl115a2.go | 4 +- examples/firmata_mpu6050.go | 8 +- examples/firmata_pca9685.go | 16 ++- examples/firmata_pir_motion.go | 16 ++- examples/firmata_rgb_led.go | 9 +- examples/firmata_servo.go | 8 +- examples/firmata_ssd1306.go | 8 +- examples/firmata_temp36.go | 4 +- examples/firmata_tm1638.go | 25 +++- examples/firmata_travis.go | 24 +++- examples/firmata_wiichuck.go | 12 +- examples/gopigo3.go | 4 +- examples/gopigo3_grove_button.go | 16 ++- examples/gopigo3_grove_lcd.go | 35 +++-- examples/gopigo3_grove_light_sensor.go | 6 +- examples/gopigo3_led_brightness.go | 9 +- examples/gopigo3_servo.go | 8 +- examples/hello.go | 4 +- examples/hello_api.go | 4 +- examples/hello_api_auth.go | 4 +- examples/hello_api_custom.go | 12 +- examples/hello_api_video.go | 4 +- examples/holystone_hs200.go | 4 +- examples/jetson-nano_blink.go | 9 +- examples/jetson-nano_servo.go | 9 +- examples/joule_blink.go | 9 +- examples/joule_blinkm.go | 13 +- examples/joule_grove_lcd.go | 45 ++++-- examples/joule_grove_rotary_sensor.go | 6 +- examples/joule_led_brightness.go | 7 +- .../joule_led_brightness_with_analog_input.go | 10 +- examples/joule_leds.go | 37 +++-- examples/joule_rgb_led.go | 9 +- examples/joystick_ps3.go | 72 +++++----- examples/joystick_ps4.go | 76 +++++----- examples/joystick_ps5.go | 76 +++++----- examples/joystick_xbox360.go | 28 ++-- examples/joystick_xbox360_rock_band_drums.go | 32 +++-- examples/joystick_xboxone.go | 72 +++++----- examples/keyboard.go | 6 +- examples/keyboard_mqtt.go | 6 +- examples/leap_motion.go | 6 +- examples/leap_motion_gestures.go | 6 +- examples/leap_motion_hands.go | 6 +- examples/leap_servos.go | 48 +++++-- examples/leap_sphero.go | 6 +- examples/mavlink.go | 16 ++- examples/megapi_motor.go | 9 +- examples/metal_button.go | 27 ++-- examples/mqtt_driver_ping.go | 8 +- examples/mqtt_firmata_blink.go | 17 ++- examples/mqtt_ping.go | 8 +- examples/nanopi_direct_pin.go | 10 +- examples/nanopi_direct_pin_event.go | 10 +- examples/nanopi_led_brightness.go | 6 +- examples/nanopi_pca9533.go | 5 +- examples/nats.go | 4 +- examples/nats_driver_ping.go | 8 +- examples/neurosky.go | 18 +-- examples/opencv_face_detect.go | 4 +- examples/opencv_window.go | 4 +- examples/particle_api.go | 9 +- examples/particle_blink.go | 9 +- examples/particle_button.go | 17 ++- examples/particle_events.go | 4 +- examples/particle_function.go | 4 +- examples/particle_led_brightness.go | 9 +- examples/particle_variable.go | 4 +- examples/pebble.go | 8 +- examples/pebble_accelerometer.go | 6 +- examples/raspi_adafruit2327_servo.go | 13 +- examples/raspi_adafruit2348_dcmotor.go | 9 +- examples/raspi_adafruit2348_stepper.go | 17 ++- examples/raspi_ads1015.go | 4 +- examples/raspi_blink.go | 9 +- examples/raspi_blinkm.go | 13 +- examples/raspi_button.go | 16 ++- examples/raspi_ccs811.go | 10 +- examples/raspi_direct_pin.go | 10 +- examples/raspi_direct_pin_event.go | 10 +- examples/raspi_generic.go | 5 +- examples/raspi_grove_pi_blink.go | 9 +- examples/raspi_grove_pi_button.go | 16 ++- examples/raspi_grove_pi_dht.go | 4 +- examples/raspi_grove_pi_rotary.go | 6 +- examples/raspi_grove_pi_ultrasonic.go | 4 +- examples/raspi_grove_rotary_sensor.go | 6 +- examples/raspi_hcsr04.go | 2 +- examples/raspi_hmc5883l.go | 4 +- examples/raspi_ina3221.go | 4 +- examples/raspi_led_brightness.go | 9 +- examples/raspi_mcp3008.go | 4 +- examples/raspi_pca9533.go | 5 +- examples/raspi_sht2x.go | 4 +- examples/raspi_sht3x.go | 8 +- examples/raspi_ssd1306.go | 9 +- examples/raspi_ssd1306spi.go | 14 +- examples/raspi_stepper_move.go | 5 +- examples/serial_sphero.go | 8 +- examples/serial_sphero_api.go | 4 +- examples/serial_sphero_calibration.go | 6 +- examples/serial_sphero_conways.go | 6 +- examples/serial_sphero_dpad.go | 4 +- examples/serial_sphero_master.go | 4 +- examples/serial_sphero_multiple.go | 6 +- examples/square.go | 57 ++++++-- examples/square_fire.go | 57 ++++++-- examples/tello.go | 13 +- examples/tello_facetracker.go | 91 ++++++++---- examples/tello_keyboard.go | 84 ++++++++--- examples/tello_opencv.go | 20 ++- examples/tello_ps3.go | 96 +++++++++---- examples/tello_video.go | 20 ++- examples/tinkerboard_adafruit1109_lcd_keys.go | 136 ++++++++++++------ examples/tinkerboard_ads1115.go | 2 +- examples/tinkerboard_adxl345.go | 4 +- examples/tinkerboard_blink.go | 9 +- examples/tinkerboard_bme280.go | 5 +- examples/tinkerboard_bmp280.go | 5 +- examples/tinkerboard_direct_pin.go | 7 +- examples/tinkerboard_generic.go | 8 +- examples/tinkerboard_grove_lcd.go | 45 ++++-- examples/tinkerboard_hcsr04.go | 2 +- examples/tinkerboard_hmc5883l.go | 4 +- examples/tinkerboard_mfcrc522gpio.go | 4 +- examples/tinkerboard_mfcrc522spi.go | 4 +- examples/tinkerboard_mpl115a2.go | 5 +- examples/tinkerboard_mpu6050.go | 4 +- examples/tinkerboard_pca9533.go | 5 +- examples/tinkerboard_pcf8583_clock.go | 10 +- examples/tinkerboard_pcf8583_counter.go | 10 +- examples/tinkerboard_pcf8591.go | 4 +- examples/tinkerboard_yl40.go | 4 +- examples/up2_lcd.go | 45 ++++-- examples/up2_leds.go | 37 +++-- examples/wifi_firmata_analog_input.go | 6 +- examples/wifi_firmata_blink.go | 9 +- platforms/beaglebone/README.md | 16 ++- platforms/beaglebone/doc.go | 8 +- platforms/bleclient/README.md | 4 +- platforms/dexter/gopigo3/README.md | 4 +- platforms/digispark/README.md | 8 +- platforms/digispark/doc.go | 8 +- platforms/dji/tello/README.md | 4 +- platforms/firmata/README.md | 16 ++- platforms/firmata/client/examples/blink.go | 7 +- platforms/firmata/doc.go | 8 +- platforms/holystone/hs200/README.md | 4 +- platforms/intel-iot/curie/README.md | 14 +- platforms/intel-iot/edison/README.md | 8 +- platforms/intel-iot/joule/README.md | 8 +- platforms/jetson/README.md | 8 +- platforms/joystick/README.md | 44 +++--- platforms/joystick/doc.go | 20 +-- platforms/keyboard/README.md | 6 +- platforms/keyboard/doc.go | 6 +- platforms/leap/README.md | 4 +- platforms/leap/doc.go | 4 +- platforms/mavlink/README.md | 4 +- platforms/mavlink/doc.go | 4 +- platforms/megapi/README.md | 4 +- platforms/microbit/README.md | 24 +++- platforms/mqtt/README.md | 8 +- platforms/nats/README.md | 8 +- platforms/neurosky/README.md | 18 +-- platforms/neurosky/doc.go | 18 +-- platforms/opencv/README.md | 4 +- platforms/opencv/doc.go | 4 +- platforms/parrot/ardrone/README.md | 4 +- platforms/parrot/ardrone/doc.go | 4 +- platforms/parrot/bebop/README.md | 4 +- .../parrot/bebop/client/examples/takeoff.go | 5 +- platforms/parrot/minidrone/README.md | 4 +- platforms/particle/README.md | 8 +- platforms/particle/doc.go | 8 +- platforms/pebble/README.md | 4 +- platforms/pebble/doc.go | 4 +- platforms/raspi/README.md | 8 +- platforms/rockpi/README.md | 8 +- platforms/sphero/bb8/README.md | 5 +- platforms/sphero/ollie/README.md | 5 +- platforms/sphero/sphero/README.md | 4 +- platforms/sphero/sprkplus/README.md | 5 +- 309 files changed, 2915 insertions(+), 1294 deletions(-) rename examples/{ble_battery.go => bleclient_battery.go} (93%) rename examples/{ble_bb8-collision.go => bleclient_bb8-collision.go} (87%) rename examples/{ble_bb8.go => bleclient_bb8.go} (93%) rename examples/{ble_device_info.go => bleclient_device_info.go} (95%) rename examples/{ble_firmata_blink.go => bleclient_firmata_blink.go} (83%) rename examples/{ble_firmata_curie_imu.go => bleclient_firmata_curie_imu.go} (66%) rename examples/{ble_generic_access.go => bleclient_generic_access.go} (94%) rename examples/{microbit_accelerometer.go => bleclient_microbit_accelerometer.go} (89%) rename examples/{microbit_blink.go => bleclient_microbit_blink.go} (90%) rename examples/{microbit_buttons.go => bleclient_microbit_buttons.go} (85%) rename examples/{microbit_buttons_leds.go => bleclient_microbit_buttons_leds.go} (71%) rename examples/{microbit_io_button.go => bleclient_microbit_io_button.go} (81%) rename examples/{microbit_led.go => bleclient_microbit_led.go} (79%) rename examples/{microbit_magnetometer.go => bleclient_microbit_magnetometer.go} (89%) rename examples/{microbit_temperature.go => bleclient_microbit_temperature.go} (89%) rename examples/{minidrone.go => bleclient_minidrone.go} (77%) rename examples/{minidrone_events.go => bleclient_minidrone_events.go} (62%) rename examples/{minidrone_mambo_ps3.go => bleclient_minidrone_mambo_ps3.go} (51%) rename examples/{minidrone_ps3.go => bleclient_minidrone_ps3.go} (52%) rename examples/{ble_multiple_generic.go => bleclient_multiple_generic.go} (95%) rename examples/{ble_multiple_info.go => bleclient_multiple_info.go} (96%) rename examples/{ble_ollie.go => bleclient_ollie.go} (91%) rename examples/{ble_ollie_boost.go => bleclient_ollie_boost.go} (92%) rename examples/{ble_ollie_crazy.go => bleclient_ollie_crazy.go} (92%) rename examples/{ble_ollie_mqtt.go => bleclient_ollie_mqtt.go} (77%) rename examples/{ble_ollie_multiple.go => bleclient_ollie_multiple.go} (94%) rename examples/{ble_ollie_roll.go => bleclient_ollie_roll.go} (91%) rename examples/{ble_ollie_spin.go => bleclient_ollie_spin.go} (92%) rename examples/{ble_sprkplus.go => bleclient_sprkplus.go} (93%) rename examples/{ble_sprkplus_collision.go => bleclient_sprkplus_collision.go} (87%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 681dcbfa9..6ccfb5b0d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -59,6 +59,22 @@ jobs: SOME=$(grep -L 'digispark' $(grep -L 'gocv' ${ALL})) for e in ${SOME} ; do go vet "${e}" ; done + "fmt_check_examples": + docker: + - image: golangci/golangci-lint:v1.55.2 + steps: + - checkout + - run: + name: Debug linter version + command: golangci-lint --version + - run: + # digispark needs libusb, opencv needs opencv + name: Check examples for linter issues (except digispark, opencv) + command: | + ALL=$(grep -l -r --include "*.go" 'build example' ./) + SOME=$(grep -L 'digispark' $(grep -L 'gocv' ${ALL})) + for e in ${SOME} ; do golangci-lint run "${e}" --build-tags example --disable forcetypeassert --disable noctx ; done + workflows: version: 2 build: @@ -66,3 +82,4 @@ workflows: - "test_core_and_drivers_with_coverage" - "test_platforms" - "check_examples" + - "fmt_check_examples" diff --git a/Makefile b/Makefile index 0b95c4346..46f532518 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ EXAMPLES_NO_GOCV := $(shell grep -L 'gocv' $(ALL_EXAMPLES)) # used examples EXAMPLES := $(EXAMPLES_NO_GOCV) -.PHONY: test test_race test_cover robeaux version_check fmt_check fmt_fix examples examples_check $(EXAMPLES) +.PHONY: test test_race test_cover robeaux version_check fmt_check fmt_fix examples examples_check examples_fmt_fix $(EXAMPLES) # opencv platform currently skipped to prevent install of preconditions including_except := $(shell go list ./... | grep -v platforms/opencv) @@ -65,9 +65,15 @@ examples: $(EXAMPLES) examples_check: $(MAKE) CHECK=ON examples +examples_fmt_fix: + $(MAKE) CHECK=FMT examples + $(EXAMPLES): ifeq ($(CHECK),ON) go vet ./$@ +else ifeq ($(CHECK),FMT) + gofumpt -l -w ./$@ + golangci-lint run ./$@ --fix --build-tags example --disable forcetypeassert --disable noctx else go build -o /tmp/gobot_examples/$@ ./$@ endif diff --git a/README.md b/README.md index 7970c30f5..4d12f82bb 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -87,7 +89,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` @@ -121,7 +125,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` @@ -141,13 +147,19 @@ import ( func main() { e := edison.NewAdaptor() - e.Connect() + if err := e.Connect(); err != nil { + fmt.Println(err) + } led := gpio.NewLedDriver(e, "13") - led.Start() + if err := led.Start(); err != nil { + fmt.Println(err) + } for { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } time.Sleep(1000 * time.Millisecond) } } @@ -179,7 +191,7 @@ func NewSwarmBot(port string) *gobot.Robot { work := func() { spheroDriver.Stop() - spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { + _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { fmt.Println("Collision Detected!") }) @@ -218,7 +230,9 @@ func main() { master.AddRobot(NewSwarmBot(port)) } - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } ``` diff --git a/doc.go b/doc.go index e20fe04e6..25a8731ab 100644 --- a/doc.go +++ b/doc.go @@ -27,7 +27,9 @@ Here is a "Classic Gobot" program that blinks an LED using an Arduino: work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -37,7 +39,9 @@ Here is a "Classic Gobot" program that blinks an LED using an Arduino: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } # Metal Gobot @@ -55,13 +59,19 @@ pure idiomatic Golang code. For example: func main() { e := edison.NewAdaptor() - e.Connect() + if err := e.Connect(); err != nil { + fmt.Println(err) + } led := gpio.NewLedDriver(e, "13") - led.Start() + if err := led.Start(); err != nil { + fmt.Println(err) + } for { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } time.Sleep(1000 * time.Millisecond) } } @@ -90,7 +100,7 @@ Finally, you can use Master Gobot to add the complete Gobot API or control swarm work := func() { spheroDriver.Stop() - spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { + _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { fmt.Println("Collision Detected!") }) @@ -129,7 +139,9 @@ Finally, you can use Master Gobot to add the complete Gobot API or control swarm master.AddRobot(NewSwarmBot(port)) } - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } Copyright (c) 2013-2018 The Hybrid Group. Licensed under the Apache 2.0 license. diff --git a/drivers/MIGRATION.md b/drivers/MIGRATION.md index 5f5cabdcf..c0fa1a279 100644 --- a/drivers/MIGRATION.md +++ b/drivers/MIGRATION.md @@ -94,7 +94,7 @@ import( adaptor := sphero.NewAdaptor("/dev/rfcomm0") spheroDriver := sphero.NewSpheroDriver(adaptor) ... - spheroDriver.On(sphero.Collision, func(data interface{}) { + _ = spheroDriver.On(sphero.Collision, func(data interface{}) { ... // new @@ -109,7 +109,7 @@ import( adaptor := serialport.NewAdaptor("/dev/rfcomm0") spheroDriver := serial.NewSpheroDriver(adaptor) ... - spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { + _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { ... ``` diff --git a/examples/ardrone.go b/examples/ardrone.go index 74349c5be..db9a9850b 100644 --- a/examples/ardrone.go +++ b/examples/ardrone.go @@ -18,7 +18,7 @@ func main() { drone := ardrone.NewDriver(ardroneAdaptor) work := func() { - drone.On(ardrone.Flying, func(data interface{}) { + _ = drone.On(ardrone.Flying, func(data interface{}) { gobot.After(3*time.Second, func() { drone.Land() }) @@ -32,5 +32,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ardrone_face_tracking.go b/examples/ardrone_face_tracking.go index b0a70834c..92c358e85 100644 --- a/examples/ardrone_face_tracking.go +++ b/examples/ardrone_face_tracking.go @@ -41,7 +41,7 @@ func main() { window.WaitKey(1) } }) - drone.On(ardrone.Flying, func(data interface{}) { + _ = drone.On(ardrone.Flying, func(data interface{}) { gobot.After(1*time.Second, func() { drone.Up(0.2) }) gobot.After(2*time.Second, func() { drone.Hover() }) gobot.After(5*time.Second, func() { @@ -83,5 +83,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ardrone_ps3.go b/examples/ardrone_ps3.go index 37dd20131..f0067b173 100644 --- a/examples/ardrone_ps3.go +++ b/examples/ardrone_ps3.go @@ -37,34 +37,34 @@ func main() { rightY.Store(float64(0.0)) work := func() { - stick.On(joystick.SquarePress, func(data interface{}) { + _ = stick.On(joystick.SquarePress, func(data interface{}) { drone.TakeOff() }) - stick.On(joystick.TrianglePress, func(data interface{}) { + _ = stick.On(joystick.TrianglePress, func(data interface{}) { drone.Hover() }) - stick.On(joystick.XPress, func(data interface{}) { + _ = stick.On(joystick.XPress, func(data interface{}) { drone.Land() }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { val := float64(data.(int16)) leftX.Store(val) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { val := float64(data.(int16)) leftY.Store(val) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { val := float64(data.(int16)) rightX.Store(val) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { val := float64(data.(int16)) rightY.Store(val) }) @@ -120,7 +120,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func getLeftStick() pair { diff --git a/examples/audio.go b/examples/audio.go index dd7819560..4df44d4f8 100644 --- a/examples/audio.go +++ b/examples/audio.go @@ -29,5 +29,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/batty.go b/examples/batty.go index 7ea6aa7f4..b5237c9fe 100644 --- a/examples/batty.go +++ b/examples/batty.go @@ -42,7 +42,9 @@ func main() { }) gbot.AddRobot(r) - gbot.Start() + if err := gbot.Start(); err != nil { + fmt.Println(err) + } } var _ gobot.Adaptor = (*loopbackAdaptor)(nil) diff --git a/examples/beaglebone_basic_direct_pin.go b/examples/beaglebone_basic_direct_pin.go index 0bb2385b0..98b54d87c 100644 --- a/examples/beaglebone_basic_direct_pin.go +++ b/examples/beaglebone_basic_direct_pin.go @@ -7,6 +7,8 @@ package main import ( + "fmt" + "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/platforms/beaglebone" ) @@ -17,11 +19,15 @@ func main() { gpioPin := gpio.NewDirectPinDriver(beagleboneAdaptor, "P9_12") // Initialize the internal representation of the pinout - beagleboneAdaptor.Connect() + if err := beagleboneAdaptor.Connect(); err != nil { + fmt.Println(err) + } // Cast to byte because we are returning an int from a function // and not passing in an int literal. - gpioPin.DigitalWrite(byte(myStateFunction())) + if err := gpioPin.DigitalWrite(byte(myStateFunction())); err != nil { + fmt.Println(err) + } } // myStateFunction determines what the GPIO state should be diff --git a/examples/beaglebone_blink.go b/examples/beaglebone_blink.go index fbddafd7a..6325f5c78 100644 --- a/examples/beaglebone_blink.go +++ b/examples/beaglebone_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/beaglebone_blink_usr_led.go b/examples/beaglebone_blink_usr_led.go index ea50005c0..b9d7a3937 100644 --- a/examples/beaglebone_blink_usr_led.go +++ b/examples/beaglebone_blink_usr_led.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/beaglebone_blinkm.go b/examples/beaglebone_blinkm.go index 97c91e7f4..bdaf74dec 100644 --- a/examples/beaglebone_blinkm.go +++ b/examples/beaglebone_blinkm.go @@ -24,8 +24,13 @@ func main() { r := byte(gobot.Rand(255)) g := byte(gobot.Rand(255)) b := byte(gobot.Rand(255)) - blinkm.Rgb(r, g, b) - color, _ := blinkm.Color() + if err := blinkm.Rgb(r, g, b); err != nil { + fmt.Println(err) + } + color, err := blinkm.Color() + if err != nil { + fmt.Println(err) + } fmt.Println("color", color) }) } @@ -36,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/beaglebone_button.go b/examples/beaglebone_button.go index 2aa227120..3ee3cc10e 100644 --- a/examples/beaglebone_button.go +++ b/examples/beaglebone_button.go @@ -19,11 +19,11 @@ func main() { button := gpio.NewButtonDriver(beagleboneAdaptor, "P8_09") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { fmt.Println("button pressed") }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("button released") }) } @@ -34,5 +34,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/beaglebone_direct_pin.go b/examples/beaglebone_direct_pin.go index 40ce35445..48ea72907 100644 --- a/examples/beaglebone_direct_pin.go +++ b/examples/beaglebone_direct_pin.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -23,9 +24,13 @@ func main() { gobot.Every(500*time.Millisecond, func() { val, _ := button.DigitalRead() if val == 1 { - led.DigitalWrite(1) + if err := led.DigitalWrite(1); err != nil { + fmt.Println(err) + } } else { - led.DigitalWrite(0) + if err := led.DigitalWrite(0); err != nil { + fmt.Println(err) + } } }) } @@ -36,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/beaglebone_grove_accelerometer.go b/examples/beaglebone_grove_accelerometer.go index f7fff980a..ffe6d1b3e 100644 --- a/examples/beaglebone_grove_accelerometer.go +++ b/examples/beaglebone_grove_accelerometer.go @@ -36,5 +36,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/beaglebone_led_brightness.go b/examples/beaglebone_led_brightness.go index 8d84b4193..f95d90768 100644 --- a/examples/beaglebone_led_brightness.go +++ b/examples/beaglebone_led_brightness.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -23,7 +24,9 @@ func main() { fadeAmount := uint8(5) gobot.Every(100*time.Millisecond, func() { - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } brightness = brightness + fadeAmount if brightness == 0 || brightness == 255 { fadeAmount = -fadeAmount @@ -37,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/beaglebone_led_brightness_with_analog_input.go b/examples/beaglebone_led_brightness_with_analog_input.go index ddd8598fb..00b36e8f0 100644 --- a/examples/beaglebone_led_brightness_with_analog_input.go +++ b/examples/beaglebone_led_brightness_with_analog_input.go @@ -22,13 +22,15 @@ func main() { led := gpio.NewLedDriver(beagleboneAdaptor, "P9_14") work := func() { - sensor.On(sensor.Event("data"), func(data interface{}) { + _ = sensor.On(sensor.Event("data"), func(data interface{}) { brightness := uint8( gobot.ToScale(gobot.FromScale(float64(data.(int)), 0, 1024), 0, 255), ) fmt.Println("sensor", data) fmt.Println("brightness", brightness) - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } }) } @@ -38,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/beaglebone_servo.go b/examples/beaglebone_servo.go index 0172eb9cd..26fd68a5a 100644 --- a/examples/beaglebone_servo.go +++ b/examples/beaglebone_servo.go @@ -23,7 +23,9 @@ func main() { gobot.Every(1*time.Second, func() { i := uint8(gobot.Rand(180)) fmt.Println("Turning", i) - servo.Move(i) + if err := servo.Move(i); err != nil { + fmt.Println(err) + } }) } @@ -33,5 +35,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/bebop.go b/examples/bebop.go index 5af654ab5..368c71706 100644 --- a/examples/bebop.go +++ b/examples/bebop.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -18,13 +19,17 @@ func main() { drone := bebop.NewDriver(bebopAdaptor) work := func() { - drone.On(bebop.Flying, func(data interface{}) { + _ = drone.On(bebop.Flying, func(data interface{}) { gobot.After(10*time.Second, func() { - drone.Land() + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) }) - drone.HullProtection(true) + if err := drone.HullProtection(true); err != nil { + fmt.Println(err) + } drone.TakeOff() } @@ -34,5 +39,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/bebop_ps3.go b/examples/bebop_ps3.go index 743b7b0f2..5974b0569 100644 --- a/examples/bebop_ps3.go +++ b/examples/bebop_ps3.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "sync/atomic" "time" @@ -39,44 +40,54 @@ func main() { recording := false - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { if recording { - drone.StopRecording() + if err := drone.StopRecording(); err != nil { + fmt.Println(err) + } } else { - drone.StartRecording() + if err := drone.StartRecording(); err != nil { + fmt.Println(err) + } } recording = !recording }) - stick.On(joystick.SquarePress, func(data interface{}) { - drone.HullProtection(true) + _ = stick.On(joystick.SquarePress, func(data interface{}) { + if err := drone.HullProtection(true); err != nil { + fmt.Println(err) + } drone.TakeOff() }) - stick.On(joystick.TrianglePress, func(data interface{}) { - drone.Stop() + _ = stick.On(joystick.TrianglePress, func(data interface{}) { + if err := drone.Stop(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.XPress, func(data interface{}) { - drone.Land() + _ = stick.On(joystick.XPress, func(data interface{}) { + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { val := float64(data.(int16)) leftX.Store(val) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { val := float64(data.(int16)) leftY.Store(val) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { val := float64(data.(int16)) rightX.Store(val) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { val := float64(data.(int16)) rightY.Store(val) }) @@ -86,20 +97,32 @@ func main() { switch { case leftStick.y < -10: - drone.Forward(bebop.ValidatePitch(leftStick.y, offset)) + if err := drone.Forward(bebop.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } case leftStick.y > 10: - drone.Backward(bebop.ValidatePitch(leftStick.y, offset)) + if err := drone.Backward(bebop.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Forward(0) + if err := drone.Forward(0); err != nil { + fmt.Println(err) + } } switch { case leftStick.x > 10: - drone.Right(bebop.ValidatePitch(leftStick.x, offset)) + if err := drone.Right(bebop.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } case leftStick.x < -10: - drone.Left(bebop.ValidatePitch(leftStick.x, offset)) + if err := drone.Left(bebop.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Right(0) + if err := drone.Right(0); err != nil { + fmt.Println(err) + } } }) @@ -107,20 +130,32 @@ func main() { rightStick := getRightStick() switch { case rightStick.y < -10: - drone.Up(bebop.ValidatePitch(rightStick.y, offset)) + if err := drone.Up(bebop.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } case rightStick.y > 10: - drone.Down(bebop.ValidatePitch(rightStick.y, offset)) + if err := drone.Down(bebop.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Up(0) + if err := drone.Up(0); err != nil { + fmt.Println(err) + } } switch { case rightStick.x > 20: - drone.Clockwise(bebop.ValidatePitch(rightStick.x, offset)) + if err := drone.Clockwise(bebop.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } case rightStick.x < -20: - drone.CounterClockwise(bebop.ValidatePitch(rightStick.x, offset)) + if err := drone.CounterClockwise(bebop.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Clockwise(0) + if err := drone.Clockwise(0); err != nil { + fmt.Println(err) + } } }) } @@ -131,7 +166,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func getLeftStick() pair { diff --git a/examples/bebop_ps3_video.go b/examples/bebop_ps3_video.go index 007e782e3..307b4dd55 100644 --- a/examples/bebop_ps3_video.go +++ b/examples/bebop_ps3_video.go @@ -48,23 +48,21 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 -func ffmpeg() (stdin io.WriteCloser, stderr io.ReadCloser, err error) { +func ffmpeg() (io.WriteCloser, io.ReadCloser, error) { ffmpeg := exec.Command("ffmpeg", "-i", "pipe:0", "http://localhost:8090/bebop.ffm") - stderr, err = ffmpeg.StderrPipe() - + stderr, err := ffmpeg.StderrPipe() if err != nil { - return + return nil, stderr, err } - stdin, err = ffmpeg.StdinPipe() - + stdin, err := ffmpeg.StdinPipe() if err != nil { - return + return stdin, stderr, err } - if err = ffmpeg.Start(); err != nil { - return + if err := ffmpeg.Start(); err != nil { + return stdin, stderr, err } go func() { @@ -90,7 +88,9 @@ func main() { drone := bebop.NewDriver(bebopAdaptor) work := func() { - drone.VideoEnable(true) + if err := drone.VideoEnable(true); err != nil { + fmt.Println(err) + } video, _, _ := ffmpeg() go func() { @@ -109,41 +109,51 @@ func main() { recording := false - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { if recording { - drone.StopRecording() + if err := drone.StopRecording(); err != nil { + fmt.Println(err) + } } else { - drone.StartRecording() + if err := drone.StartRecording(); err != nil { + fmt.Println(err) + } } recording = !recording }) - stick.On(joystick.SquarePress, func(data interface{}) { - drone.HullProtection(true) + _ = stick.On(joystick.SquarePress, func(data interface{}) { + if err := drone.HullProtection(true); err != nil { + fmt.Println(err) + } drone.TakeOff() }) - stick.On(joystick.TrianglePress, func(data interface{}) { - drone.Stop() + _ = stick.On(joystick.TrianglePress, func(data interface{}) { + if err := drone.Stop(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.XPress, func(data interface{}) { - drone.Land() + _ = stick.On(joystick.XPress, func(data interface{}) { + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { val := float64(data.(int16)) leftX.Store(val) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { val := float64(data.(int16)) leftY.Store(val) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { val := float64(data.(int16)) rightX.Store(val) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { val := float64(data.(int16)) rightY.Store(val) }) @@ -153,20 +163,32 @@ func main() { switch { case leftStick.y < -10: - drone.Forward(bebop.ValidatePitch(leftStick.y, offset)) + if err := drone.Forward(bebop.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } case leftStick.y > 10: - drone.Backward(bebop.ValidatePitch(leftStick.y, offset)) + if err := drone.Backward(bebop.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Forward(0) + if err := drone.Forward(0); err != nil { + fmt.Println(err) + } } switch { case leftStick.x > 10: - drone.Right(bebop.ValidatePitch(leftStick.x, offset)) + if err := drone.Right(bebop.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } case leftStick.x < -10: - drone.Left(bebop.ValidatePitch(leftStick.x, offset)) + if err := drone.Left(bebop.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Right(0) + if err := drone.Right(0); err != nil { + fmt.Println(err) + } } }) @@ -174,20 +196,32 @@ func main() { rightStick := getRightStick() switch { case rightStick.y < -10: - drone.Up(bebop.ValidatePitch(rightStick.y, offset)) + if err := drone.Up(bebop.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } case rightStick.y > 10: - drone.Down(bebop.ValidatePitch(rightStick.y, offset)) + if err := drone.Down(bebop.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Up(0) + if err := drone.Up(0); err != nil { + fmt.Println(err) + } } switch { case rightStick.x > 20: - drone.Clockwise(bebop.ValidatePitch(rightStick.x, offset)) + if err := drone.Clockwise(bebop.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } case rightStick.x < -20: - drone.CounterClockwise(bebop.ValidatePitch(rightStick.x, offset)) + if err := drone.CounterClockwise(bebop.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Clockwise(0) + if err := drone.Clockwise(0); err != nil { + fmt.Println(err) + } } }) } @@ -198,7 +232,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func getLeftStick() pair { diff --git a/examples/bebop_rtp_video.go b/examples/bebop_rtp_video.go index df3afbe9b..725f0b289 100644 --- a/examples/bebop_rtp_video.go +++ b/examples/bebop_rtp_video.go @@ -23,6 +23,8 @@ http://localhost:8090/bebop.mjpeg in a web browser. package main import ( + "fmt" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/platforms/parrot/bebop" ) @@ -32,7 +34,9 @@ func main() { drone := bebop.NewDriver(bebopAdaptor) work := func() { - drone.VideoEnable(true) + if err := drone.VideoEnable(true); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("drone", @@ -41,5 +45,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_battery.go b/examples/bleclient_battery.go similarity index 93% rename from examples/ble_battery.go rename to examples/bleclient_battery.go index 22276b2b6..f0a179954 100644 --- a/examples/ble_battery.go +++ b/examples/bleclient_battery.go @@ -45,5 +45,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_bb8-collision.go b/examples/bleclient_bb8-collision.go similarity index 87% rename from examples/ble_bb8-collision.go rename to examples/bleclient_bb8-collision.go index 6d00daaea..d5573a574 100644 --- a/examples/ble_bb8-collision.go +++ b/examples/bleclient_bb8-collision.go @@ -29,7 +29,7 @@ func main() { bb := sphero.NewBB8Driver(bleAdaptor) work := func() { - bb.On("collision", func(data interface{}) { + _ = bb.On("collision", func(data interface{}) { fmt.Printf("collision detected = %+v \n", data) bb.SetRGB(255, 0, 0) }) @@ -44,5 +44,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_bb8.go b/examples/bleclient_bb8.go similarity index 93% rename from examples/ble_bb8.go rename to examples/bleclient_bb8.go index 24d082d37..f22a4db1e 100644 --- a/examples/ble_bb8.go +++ b/examples/bleclient_bb8.go @@ -43,5 +43,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_device_info.go b/examples/bleclient_device_info.go similarity index 95% rename from examples/ble_device_info.go rename to examples/bleclient_device_info.go index e463a8ccb..69f8c997b 100644 --- a/examples/ble_device_info.go +++ b/examples/bleclient_device_info.go @@ -66,5 +66,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_firmata_blink.go b/examples/bleclient_firmata_blink.go similarity index 83% rename from examples/ble_firmata_blink.go rename to examples/bleclient_firmata_blink.go index b63860e1f..f74849fd4 100644 --- a/examples/ble_firmata_blink.go +++ b/examples/bleclient_firmata_blink.go @@ -16,6 +16,7 @@ package main import ( + "fmt" "os" "time" @@ -30,7 +31,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -40,5 +43,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_firmata_curie_imu.go b/examples/bleclient_firmata_curie_imu.go similarity index 66% rename from examples/ble_firmata_curie_imu.go rename to examples/bleclient_firmata_curie_imu.go index 184a9f9fc..0f6e136f6 100644 --- a/examples/ble_firmata_curie_imu.go +++ b/examples/bleclient_firmata_curie_imu.go @@ -16,6 +16,7 @@ package main import ( + "fmt" "log" "os" "time" @@ -33,26 +34,34 @@ func main() { imu := curie.NewIMUDriver(firmataAdaptor) work := func() { - imu.On("Accelerometer", func(data interface{}) { + _ = imu.On("Accelerometer", func(data interface{}) { log.Println("Accelerometer", data) }) - imu.On("Gyroscope", func(data interface{}) { + _ = imu.On("Gyroscope", func(data interface{}) { log.Println("Gyroscope", data) }) - imu.On("Temperature", func(data interface{}) { + _ = imu.On("Temperature", func(data interface{}) { log.Println("Temperature", data) }) gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(100*time.Millisecond, func() { - imu.ReadAccelerometer() - imu.ReadGyroscope() - imu.ReadTemperature() + if err := imu.ReadAccelerometer(); err != nil { + fmt.Println(err) + } + if err := imu.ReadGyroscope(); err != nil { + fmt.Println(err) + } + if err := imu.ReadTemperature(); err != nil { + fmt.Println(err) + } }) } @@ -62,5 +71,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_generic_access.go b/examples/bleclient_generic_access.go similarity index 94% rename from examples/ble_generic_access.go rename to examples/bleclient_generic_access.go index aa77064a6..47e7842fb 100644 --- a/examples/ble_generic_access.go +++ b/examples/bleclient_generic_access.go @@ -48,5 +48,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/microbit_accelerometer.go b/examples/bleclient_microbit_accelerometer.go similarity index 89% rename from examples/microbit_accelerometer.go rename to examples/bleclient_microbit_accelerometer.go index 55fbc5350..1a7b301e6 100644 --- a/examples/microbit_accelerometer.go +++ b/examples/bleclient_microbit_accelerometer.go @@ -40,7 +40,7 @@ func main() { ubit := microbit.NewAccelerometerDriver(bleAdaptor) work := func() { - ubit.On(microbit.AccelerometerEvent, func(data interface{}) { + _ = ubit.On(microbit.AccelerometerEvent, func(data interface{}) { fmt.Println("Accelerometer", data) }) } @@ -51,5 +51,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/microbit_blink.go b/examples/bleclient_microbit_blink.go similarity index 90% rename from examples/microbit_blink.go rename to examples/bleclient_microbit_blink.go index c384c68dc..6b4d92b9d 100644 --- a/examples/microbit_blink.go +++ b/examples/bleclient_microbit_blink.go @@ -30,6 +30,7 @@ package main import ( + "fmt" "os" "time" @@ -47,7 +48,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -57,5 +60,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/microbit_buttons.go b/examples/bleclient_microbit_buttons.go similarity index 85% rename from examples/microbit_buttons.go rename to examples/bleclient_microbit_buttons.go index 54123a456..c7b1d5d7a 100644 --- a/examples/microbit_buttons.go +++ b/examples/bleclient_microbit_buttons.go @@ -38,11 +38,11 @@ func main() { ubit := microbit.NewButtonDriver(bleAdaptor) work := func() { - ubit.On(microbit.ButtonAEvent, func(data interface{}) { + _ = ubit.On(microbit.ButtonAEvent, func(data interface{}) { fmt.Println("button A", data) }) - ubit.On(microbit.ButtonBEvent, func(data interface{}) { + _ = ubit.On(microbit.ButtonBEvent, func(data interface{}) { fmt.Println("button B", data) }) } @@ -53,5 +53,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/microbit_buttons_leds.go b/examples/bleclient_microbit_buttons_leds.go similarity index 71% rename from examples/microbit_buttons_leds.go rename to examples/bleclient_microbit_buttons_leds.go index 222ee9d11..b9f5ebb49 100644 --- a/examples/microbit_buttons_leds.go +++ b/examples/bleclient_microbit_buttons_leds.go @@ -27,6 +27,7 @@ package main import ( + "fmt" "os" "gobot.io/x/gobot/v2" @@ -40,22 +41,30 @@ func main() { leds := microbit.NewLEDDriver(bleAdaptor) work := func() { - buttons.On(microbit.ButtonAEvent, func(data interface{}) { + _ = buttons.On(microbit.ButtonAEvent, func(data interface{}) { if data.([]byte)[0] == 1 { - leds.UpLeftArrow() + if err := leds.UpLeftArrow(); err != nil { + fmt.Println(err) + } return } - leds.Blank() + if err := leds.Blank(); err != nil { + fmt.Println(err) + } }) - buttons.On(microbit.ButtonBEvent, func(data interface{}) { + _ = buttons.On(microbit.ButtonBEvent, func(data interface{}) { if data.([]byte)[0] == 1 { - leds.UpRightArrow() + if err := leds.UpRightArrow(); err != nil { + fmt.Println(err) + } return } - leds.Blank() + if err := leds.Blank(); err != nil { + fmt.Println(err) + } }) } @@ -65,5 +74,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/microbit_io_button.go b/examples/bleclient_microbit_io_button.go similarity index 81% rename from examples/microbit_io_button.go rename to examples/bleclient_microbit_io_button.go index c1e80be36..c203a7d65 100644 --- a/examples/microbit_io_button.go +++ b/examples/bleclient_microbit_io_button.go @@ -31,6 +31,7 @@ package main import ( + "fmt" "os" "gobot.io/x/gobot/v2" @@ -47,11 +48,15 @@ func main() { led := gpio.NewLedDriver(ubit, "1") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - led.On() + _ = button.On(gpio.ButtonPush, func(data interface{}) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { - led.Off() + _ = button.On(gpio.ButtonRelease, func(data interface{}) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -61,5 +66,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/microbit_led.go b/examples/bleclient_microbit_led.go similarity index 79% rename from examples/microbit_led.go rename to examples/bleclient_microbit_led.go index 99586dd27..4d203750c 100644 --- a/examples/microbit_led.go +++ b/examples/bleclient_microbit_led.go @@ -27,6 +27,7 @@ package main import ( + "fmt" "os" "time" @@ -40,12 +41,18 @@ func main() { ubit := microbit.NewLEDDriver(bleAdaptor) work := func() { - ubit.Blank() + if err := ubit.Blank(); err != nil { + fmt.Println(err) + } gobot.After(1*time.Second, func() { - ubit.WriteText("Hello") + if err := ubit.WriteText("Hello"); err != nil { + fmt.Println(err) + } }) gobot.After(7*time.Second, func() { - ubit.Smile() + if err := ubit.Smile(); err != nil { + fmt.Println(err) + } }) } @@ -55,5 +62,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/microbit_magnetometer.go b/examples/bleclient_microbit_magnetometer.go similarity index 89% rename from examples/microbit_magnetometer.go rename to examples/bleclient_microbit_magnetometer.go index 8e78bbbff..90c13637e 100644 --- a/examples/microbit_magnetometer.go +++ b/examples/bleclient_microbit_magnetometer.go @@ -40,7 +40,7 @@ func main() { ubit := microbit.NewMagnetometerDriver(bleAdaptor) work := func() { - ubit.On(microbit.MagnetometerEvent, func(data interface{}) { + _ = ubit.On(microbit.MagnetometerEvent, func(data interface{}) { fmt.Println("Magnetometer", data) }) } @@ -51,5 +51,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/microbit_temperature.go b/examples/bleclient_microbit_temperature.go similarity index 89% rename from examples/microbit_temperature.go rename to examples/bleclient_microbit_temperature.go index a27109768..7b21e0443 100644 --- a/examples/microbit_temperature.go +++ b/examples/bleclient_microbit_temperature.go @@ -40,7 +40,7 @@ func main() { ubit := microbit.NewTemperatureDriver(bleAdaptor) work := func() { - ubit.On(microbit.TemperatureEvent, func(data interface{}) { + _ = ubit.On(microbit.TemperatureEvent, func(data interface{}) { fmt.Println("Temperature", data) }) } @@ -51,5 +51,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/minidrone.go b/examples/bleclient_minidrone.go similarity index 77% rename from examples/minidrone.go rename to examples/bleclient_minidrone.go index 17519d84b..4832f8e1e 100644 --- a/examples/minidrone.go +++ b/examples/bleclient_minidrone.go @@ -16,6 +16,7 @@ package main import ( + "fmt" "os" "time" @@ -29,10 +30,14 @@ func main() { drone := parrot.NewMinidroneDriver(bleAdaptor) work := func() { - drone.TakeOff() + if err := drone.TakeOff(); err != nil { + fmt.Println(err) + } gobot.After(5*time.Second, func() { - drone.Land() + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) } @@ -42,5 +47,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/minidrone_events.go b/examples/bleclient_minidrone_events.go similarity index 62% rename from examples/minidrone_events.go rename to examples/bleclient_minidrone_events.go index b95eb10a6..305ed3eaa 100644 --- a/examples/minidrone_events.go +++ b/examples/bleclient_minidrone_events.go @@ -30,35 +30,39 @@ func main() { drone := parrot.NewMinidroneDriver(bleAdaptor) work := func() { - drone.On(parrot.BatteryEvent, func(data interface{}) { + _ = drone.On(parrot.BatteryEvent, func(data interface{}) { fmt.Printf("battery: %d\n", data) }) - drone.On(parrot.FlightStatusEvent, func(data interface{}) { + _ = drone.On(parrot.FlightStatusEvent, func(data interface{}) { fmt.Printf("flight status: %d\n", data) }) - drone.On(parrot.TakeoffEvent, func(data interface{}) { + _ = drone.On(parrot.TakeoffEvent, func(data interface{}) { fmt.Println("taking off...") }) - drone.On(parrot.HoveringEvent, func(data interface{}) { + _ = drone.On(parrot.HoveringEvent, func(data interface{}) { fmt.Println("hovering!") gobot.After(5*time.Second, func() { - drone.Land() + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) }) - drone.On(parrot.LandingEvent, func(data interface{}) { + _ = drone.On(parrot.LandingEvent, func(data interface{}) { fmt.Println("landing...") }) - drone.On(parrot.LandedEvent, func(data interface{}) { + _ = drone.On(parrot.LandedEvent, func(data interface{}) { fmt.Println("landed.") }) time.Sleep(1000 * time.Millisecond) - drone.TakeOff() + if err := drone.TakeOff(); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("minidrone", @@ -67,5 +71,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/minidrone_mambo_ps3.go b/examples/bleclient_minidrone_mambo_ps3.go similarity index 51% rename from examples/minidrone_mambo_ps3.go rename to examples/bleclient_minidrone_mambo_ps3.go index b1b443a72..a977b89ab 100644 --- a/examples/minidrone_mambo_ps3.go +++ b/examples/bleclient_minidrone_mambo_ps3.go @@ -23,6 +23,7 @@ package main import ( + "fmt" "os" "sync/atomic" "time" @@ -59,51 +60,65 @@ func main() { clawOpen := false - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { if clawOpen { - drone.ClawControl(0, parrot.ClawClosed) + if err := drone.ClawControl(0, parrot.ClawClosed); err != nil { + fmt.Println(err) + } clawOpen = false } else { - drone.ClawControl(0, parrot.ClawOpen) + if err := drone.ClawControl(0, parrot.ClawOpen); err != nil { + fmt.Println(err) + } clawOpen = true } }) - stick.On(joystick.R2Press, func(data interface{}) { + _ = stick.On(joystick.R2Press, func(data interface{}) { if clawOpen { - drone.ClawControl(0, parrot.ClawClosed) + if err := drone.ClawControl(0, parrot.ClawClosed); err != nil { + fmt.Println(err) + } clawOpen = false } else { - drone.ClawControl(0, parrot.ClawOpen) + if err := drone.ClawControl(0, parrot.ClawOpen); err != nil { + fmt.Println(err) + } clawOpen = true } }) - stick.On(joystick.TrianglePress, func(data interface{}) { - drone.HullProtection(true) - drone.TakeOff() + _ = stick.On(joystick.TrianglePress, func(data interface{}) { + if err := drone.HullProtection(true); err != nil { + fmt.Println(err) + } + if err := drone.TakeOff(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.XPress, func(data interface{}) { - drone.Land() + _ = stick.On(joystick.XPress, func(data interface{}) { + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { val := float64(data.(int16)) leftX.Store(val) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { val := float64(data.(int16)) leftY.Store(val) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { val := float64(data.(int16)) rightX.Store(val) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { val := float64(data.(int16)) rightY.Store(val) }) @@ -113,20 +128,32 @@ func main() { switch { case rightStick.y < -10: - drone.Forward(parrot.ValidatePitch(rightStick.y, offset)) + if err := drone.Forward(parrot.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } case rightStick.y > 10: - drone.Backward(parrot.ValidatePitch(rightStick.y, offset)) + if err := drone.Backward(parrot.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Forward(0) + if err := drone.Forward(0); err != nil { + fmt.Println(err) + } } switch { case rightStick.x > 10: - drone.Right(parrot.ValidatePitch(rightStick.x, offset)) + if err := drone.Right(parrot.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } case rightStick.x < -10: - drone.Left(parrot.ValidatePitch(rightStick.x, offset)) + if err := drone.Left(parrot.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Right(0) + if err := drone.Right(0); err != nil { + fmt.Println(err) + } } }) @@ -134,20 +161,32 @@ func main() { leftStick := getLeftStick() switch { case leftStick.y < -10: - drone.Up(parrot.ValidatePitch(leftStick.y, offset)) + if err := drone.Up(parrot.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } case leftStick.y > 10: - drone.Down(parrot.ValidatePitch(leftStick.y, offset)) + if err := drone.Down(parrot.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Up(0) + if err := drone.Up(0); err != nil { + fmt.Println(err) + } } switch { case leftStick.x > 20: - drone.Clockwise(parrot.ValidatePitch(leftStick.x, offset)) + if err := drone.Clockwise(parrot.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } case leftStick.x < -20: - drone.CounterClockwise(parrot.ValidatePitch(leftStick.x, offset)) + if err := drone.CounterClockwise(parrot.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Clockwise(0) + if err := drone.Clockwise(0); err != nil { + fmt.Println(err) + } } }) } @@ -158,7 +197,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func getLeftStick() pair { diff --git a/examples/minidrone_ps3.go b/examples/bleclient_minidrone_ps3.go similarity index 52% rename from examples/minidrone_ps3.go rename to examples/bleclient_minidrone_ps3.go index a316a3d52..409c24865 100644 --- a/examples/minidrone_ps3.go +++ b/examples/bleclient_minidrone_ps3.go @@ -23,6 +23,7 @@ package main import ( + "fmt" "os" "sync/atomic" "time" @@ -57,44 +58,56 @@ func main() { recording := false - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { if recording { - drone.StopRecording() + if err := drone.StopRecording(); err != nil { + fmt.Println(err) + } } else { - drone.StartRecording() + if err := drone.StartRecording(); err != nil { + fmt.Println(err) + } } recording = !recording }) - stick.On(joystick.SquarePress, func(data interface{}) { - drone.Stop() + _ = stick.On(joystick.SquarePress, func(data interface{}) { + if err := drone.Stop(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.TrianglePress, func(data interface{}) { - drone.HullProtection(true) - drone.TakeOff() + _ = stick.On(joystick.TrianglePress, func(data interface{}) { + if err := drone.HullProtection(true); err != nil { + fmt.Println(err) + } + if err := drone.TakeOff(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.XPress, func(data interface{}) { - drone.Land() + _ = stick.On(joystick.XPress, func(data interface{}) { + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { val := float64(data.(int16)) leftX.Store(val) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { val := float64(data.(int16)) leftY.Store(val) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { val := float64(data.(int16)) rightX.Store(val) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { val := float64(data.(int16)) rightY.Store(val) }) @@ -104,20 +117,32 @@ func main() { switch { case rightStick.y < -10: - drone.Forward(parrot.ValidatePitch(rightStick.y, offset)) + if err := drone.Forward(parrot.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } case rightStick.y > 10: - drone.Backward(parrot.ValidatePitch(rightStick.y, offset)) + if err := drone.Backward(parrot.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Forward(0) + if err := drone.Forward(0); err != nil { + fmt.Println(err) + } } switch { case rightStick.x > 10: - drone.Right(parrot.ValidatePitch(rightStick.x, offset)) + if err := drone.Right(parrot.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } case rightStick.x < -10: - drone.Left(parrot.ValidatePitch(rightStick.x, offset)) + if err := drone.Left(parrot.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Right(0) + if err := drone.Right(0); err != nil { + fmt.Println(err) + } } }) @@ -125,20 +150,32 @@ func main() { leftStick := getLeftStick() switch { case leftStick.y < -10: - drone.Up(parrot.ValidatePitch(leftStick.y, offset)) + if err := drone.Up(parrot.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } case leftStick.y > 10: - drone.Down(parrot.ValidatePitch(leftStick.y, offset)) + if err := drone.Down(parrot.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Up(0) + if err := drone.Up(0); err != nil { + fmt.Println(err) + } } switch { case leftStick.x > 20: - drone.Clockwise(parrot.ValidatePitch(leftStick.x, offset)) + if err := drone.Clockwise(parrot.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } case leftStick.x < -20: - drone.CounterClockwise(parrot.ValidatePitch(leftStick.x, offset)) + if err := drone.CounterClockwise(parrot.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Clockwise(0) + if err := drone.Clockwise(0); err != nil { + fmt.Println(err) + } } }) } @@ -149,7 +186,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func getLeftStick() pair { diff --git a/examples/ble_multiple_generic.go b/examples/bleclient_multiple_generic.go similarity index 95% rename from examples/ble_multiple_generic.go rename to examples/bleclient_multiple_generic.go index ddc7d313f..c09b4e3ec 100644 --- a/examples/ble_multiple_generic.go +++ b/examples/bleclient_multiple_generic.go @@ -61,5 +61,7 @@ func main() { master.AddRobot(bot) } - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_multiple_info.go b/examples/bleclient_multiple_info.go similarity index 96% rename from examples/ble_multiple_info.go rename to examples/bleclient_multiple_info.go index b4960e9a5..f76f5b0ae 100644 --- a/examples/ble_multiple_info.go +++ b/examples/bleclient_multiple_info.go @@ -79,5 +79,7 @@ func main() { master.AddRobot(bot) } - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_ollie.go b/examples/bleclient_ollie.go similarity index 91% rename from examples/ble_ollie.go rename to examples/bleclient_ollie.go index a2dfe8e19..82f91762c 100644 --- a/examples/ble_ollie.go +++ b/examples/bleclient_ollie.go @@ -34,5 +34,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_ollie_boost.go b/examples/bleclient_ollie_boost.go similarity index 92% rename from examples/ble_ollie_boost.go rename to examples/bleclient_ollie_boost.go index ba1859f17..b4a10bf8c 100644 --- a/examples/ble_ollie_boost.go +++ b/examples/bleclient_ollie_boost.go @@ -37,5 +37,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_ollie_crazy.go b/examples/bleclient_ollie_crazy.go similarity index 92% rename from examples/ble_ollie_crazy.go rename to examples/bleclient_ollie_crazy.go index cef96f22d..4d2566b5a 100644 --- a/examples/ble_ollie_crazy.go +++ b/examples/bleclient_ollie_crazy.go @@ -33,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_ollie_mqtt.go b/examples/bleclient_ollie_mqtt.go similarity index 77% rename from examples/ble_ollie_mqtt.go rename to examples/bleclient_ollie_mqtt.go index 2d9c07977..cfd9a4e48 100644 --- a/examples/ble_ollie_mqtt.go +++ b/examples/bleclient_ollie_mqtt.go @@ -33,7 +33,7 @@ func main() { work := func() { ollie.SetRGB(255, 0, 255) - mqttAdaptor.On("sensores/dial", func(msg mqtt.Message) { + _ = mqttAdaptor.On("sensors/dial", func(msg mqtt.Message) { val, _ := strconv.Atoi(string(msg.Payload())) if val > 2000 { @@ -47,28 +47,28 @@ func main() { ollie.SetRGB(255, 0, 0) }) - mqttAdaptor.On("rover/frente", func(msg mqtt.Message) { + _ = mqttAdaptor.On("rover/frente", func(msg mqtt.Message) { ollie.Roll(40, FRENTE) gobot.After(1*time.Second, func() { ollie.Stop() }) }) - mqttAdaptor.On("rover/derecha", func(msg mqtt.Message) { + _ = mqttAdaptor.On("rover/derecha", func(msg mqtt.Message) { ollie.Roll(40, DERECHA) gobot.After(1*time.Second, func() { ollie.Stop() }) }) - mqttAdaptor.On("rover/atras", func(msg mqtt.Message) { + _ = mqttAdaptor.On("rover/atras", func(msg mqtt.Message) { ollie.Roll(40, ATRAS) gobot.After(1*time.Second, func() { ollie.Stop() }) }) - mqttAdaptor.On("rover/izquierda", func(msg mqtt.Message) { + _ = mqttAdaptor.On("rover/izquierda", func(msg mqtt.Message) { ollie.Roll(40, IZQUIERDA) gobot.After(1*time.Second, func() { ollie.Stop() @@ -82,5 +82,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_ollie_multiple.go b/examples/bleclient_ollie_multiple.go similarity index 94% rename from examples/ble_ollie_multiple.go rename to examples/bleclient_ollie_multiple.go index a80f1d413..90a06d714 100644 --- a/examples/ble_ollie_multiple.go +++ b/examples/bleclient_ollie_multiple.go @@ -55,5 +55,7 @@ func main() { master.AddRobot(bot) } - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_ollie_roll.go b/examples/bleclient_ollie_roll.go similarity index 91% rename from examples/ble_ollie_roll.go rename to examples/bleclient_ollie_roll.go index bf07d7e36..7bcba8401 100644 --- a/examples/ble_ollie_roll.go +++ b/examples/bleclient_ollie_roll.go @@ -32,5 +32,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_ollie_spin.go b/examples/bleclient_ollie_spin.go similarity index 92% rename from examples/ble_ollie_spin.go rename to examples/bleclient_ollie_spin.go index 027328f79..4851826c2 100644 --- a/examples/ble_ollie_spin.go +++ b/examples/bleclient_ollie_spin.go @@ -33,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_sprkplus.go b/examples/bleclient_sprkplus.go similarity index 93% rename from examples/ble_sprkplus.go rename to examples/bleclient_sprkplus.go index ad85eb50e..36c5d1914 100644 --- a/examples/ble_sprkplus.go +++ b/examples/bleclient_sprkplus.go @@ -43,5 +43,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/ble_sprkplus_collision.go b/examples/bleclient_sprkplus_collision.go similarity index 87% rename from examples/ble_sprkplus_collision.go rename to examples/bleclient_sprkplus_collision.go index c053c2893..44b09890b 100644 --- a/examples/ble_sprkplus_collision.go +++ b/examples/bleclient_sprkplus_collision.go @@ -29,7 +29,7 @@ func main() { ball := sphero.NewSPRKPlusDriver(bleAdaptor) work := func() { - ball.On("collision", func(data interface{}) { + _ = ball.On("collision", func(data interface{}) { fmt.Printf("collision detected = %+v \n", data) ball.SetRGB(255, 0, 0) }) @@ -44,5 +44,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_blink.go b/examples/chip_blink.go index 528e41f5d..cd54f2fd9 100644 --- a/examples/chip_blink.go +++ b/examples/chip_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_blinkm.go b/examples/chip_blinkm.go index 85bbc816e..ca53a29a3 100644 --- a/examples/chip_blinkm.go +++ b/examples/chip_blinkm.go @@ -24,8 +24,13 @@ func main() { r := byte(gobot.Rand(255)) g := byte(gobot.Rand(255)) b := byte(gobot.Rand(255)) - blinkm.Rgb(r, g, b) - color, _ := blinkm.Color() + if err := blinkm.Rgb(r, g, b); err != nil { + fmt.Println(err) + } + color, err := blinkm.Color() + if err != nil { + fmt.Println(err) + } fmt.Println("color", color) }) } @@ -36,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_button.go b/examples/chip_button.go index bc1a6d600..06d3b1d4b 100644 --- a/examples/chip_button.go +++ b/examples/chip_button.go @@ -19,11 +19,11 @@ func main() { button := gpio.NewButtonDriver(chipAdaptor, "XIO-P0") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { fmt.Println("button pressed") }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("button released") }) } @@ -34,5 +34,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_button_led.go b/examples/chip_button_led.go index d011a58b9..c450550dc 100644 --- a/examples/chip_button_led.go +++ b/examples/chip_button_led.go @@ -7,6 +7,8 @@ package main import ( + "fmt" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/platforms/chip" @@ -18,12 +20,16 @@ func main() { led := gpio.NewLedDriver(chipAdaptor, "XIO-P7") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - led.On() + _ = button.On(gpio.ButtonPush, func(data interface{}) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { - led.Off() + _ = button.On(gpio.ButtonRelease, func(data interface{}) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -33,5 +39,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_drv2605l.go b/examples/chip_drv2605l.go index 12fad0981..847f82441 100644 --- a/examples/chip_drv2605l.go +++ b/examples/chip_drv2605l.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -21,8 +22,12 @@ func main() { work := func() { gobot.Every(3*time.Second, func() { pause := haptic.GetPauseWaveform(50) - haptic.SetSequence([]byte{1, pause, 1, pause, 1}) - haptic.Go() + if err := haptic.SetSequence([]byte{1, pause, 1, pause, 1}); err != nil { + fmt.Println(err) + } + if err := haptic.Go(); err != nil { + fmt.Println(err) + } }) } @@ -32,5 +37,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_grove_accelerometer.go b/examples/chip_grove_accelerometer.go index 7030724a2..ba0994926 100644 --- a/examples/chip_grove_accelerometer.go +++ b/examples/chip_grove_accelerometer.go @@ -36,5 +36,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_grove_lcd.go b/examples/chip_grove_lcd.go index 513147682..401c50337 100644 --- a/examples/chip_grove_lcd.go +++ b/examples/chip_grove_lcd.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -19,26 +20,47 @@ func main() { screen := i2c.NewGroveLcdDriver(board) work := func() { - screen.Write("hello") + if err := screen.Write("hello"); err != nil { + fmt.Println(err) + } - screen.SetRGB(255, 0, 0) + if err := screen.SetRGB(255, 0, 0); err != nil { + fmt.Println(err) + } gobot.After(5*time.Second, func() { - screen.Clear() - screen.Home() - screen.SetRGB(0, 255, 0) + if err := screen.Clear(); err != nil { + fmt.Println(err) + } + if err := screen.Home(); err != nil { + fmt.Println(err) + } + if err := screen.SetRGB(0, 255, 0); err != nil { + fmt.Println(err) + } // set a custom character in the first position - screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]) + if err := screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]); err != nil { + fmt.Println(err) + } // add the custom character at the end of the string - screen.Write("goodbye\nhave a nice day " + string(byte(0))) + if err := screen.Write("goodbye\nhave a nice day " + string(byte(0))); err != nil { + fmt.Println(err) + } + gobot.Every(500*time.Millisecond, func() { - screen.Scroll(false) + if err := screen.Scroll(false); err != nil { + fmt.Println(err) + } }) }) - screen.Home() + if err := screen.Home(); err != nil { + fmt.Println(err) + } time.Sleep(1 * time.Second) - screen.SetRGB(0, 0, 255) + if err := screen.SetRGB(0, 0, 255); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("screenBot", @@ -47,5 +69,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_mpu6050.go b/examples/chip_mpu6050.go index 6238f220a..887b41d55 100644 --- a/examples/chip_mpu6050.go +++ b/examples/chip_mpu6050.go @@ -21,7 +21,9 @@ func main() { work := func() { gobot.Every(100*time.Millisecond, func() { - mpu6050.GetData() + if err := mpu6050.GetData(); err != nil { + fmt.Println(err) + } fmt.Println("Accelerometer", mpu6050.Accelerometer) fmt.Println("Gyroscope", mpu6050.Gyroscope) @@ -35,5 +37,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_tsl2561.go b/examples/chip_tsl2561.go index 9f7ba1b72..10d6fdbf3 100644 --- a/examples/chip_tsl2561.go +++ b/examples/chip_tsl2561.go @@ -38,5 +38,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/chip_wiichuck.go b/examples/chip_wiichuck.go index 120f82c85..bf546951d 100644 --- a/examples/chip_wiichuck.go +++ b/examples/chip_wiichuck.go @@ -19,18 +19,18 @@ func main() { wiichuck := i2c.NewWiichuckDriver(chipAdaptor) work := func() { - wiichuck.On(wiichuck.Event("joystick"), func(data interface{}) { + _ = wiichuck.On(wiichuck.Event("joystick"), func(data interface{}) { fmt.Println("joystick", data) }) - wiichuck.On(wiichuck.Event("c"), func(data interface{}) { + _ = wiichuck.On(wiichuck.Event("c"), func(data interface{}) { fmt.Println("c") }) - wiichuck.On(wiichuck.Event("z"), func(data interface{}) { + _ = wiichuck.On(wiichuck.Event("z"), func(data interface{}) { fmt.Println("z") }) - wiichuck.On(wiichuck.Event("error"), func(data interface{}) { + _ = wiichuck.On(wiichuck.Event("error"), func(data interface{}) { fmt.Println("Wiichuck error:", data) }) } @@ -41,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/digispark_api.go b/examples/digispark_api.go index 8614f783e..b409ba8f5 100644 --- a/examples/digispark_api.go +++ b/examples/digispark_api.go @@ -27,5 +27,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/digispark_blink.go b/examples/digispark_blink.go index dc500d2de..dc7120d62 100644 --- a/examples/digispark_blink.go +++ b/examples/digispark_blink.go @@ -21,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -31,8 +33,7 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/digispark_blinkm.go b/examples/digispark_blinkm.go index b64c693b5..d7c39a551 100644 --- a/examples/digispark_blinkm.go +++ b/examples/digispark_blinkm.go @@ -24,8 +24,13 @@ func main() { r := byte(gobot.Rand(255)) g := byte(gobot.Rand(255)) b := byte(gobot.Rand(255)) - blinkm.Rgb(r, g, b) - color, _ := blinkm.Color() + if err := blinkm.Rgb(r, g, b); err != nil { + fmt.Println(err) + } + color, err := blinkm.Color() + if err != nil { + fmt.Println(err) + } fmt.Println("color", color) }) } @@ -36,8 +41,7 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/digispark_driver.go b/examples/digispark_driver.go index 369449b7e..9ccf5a51f 100644 --- a/examples/digispark_driver.go +++ b/examples/digispark_driver.go @@ -72,8 +72,7 @@ func main() { work, ) - err = robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/digispark_led_brightness.go b/examples/digispark_led_brightness.go index e52cfe17c..cc0348313 100644 --- a/examples/digispark_led_brightness.go +++ b/examples/digispark_led_brightness.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -23,7 +24,9 @@ func main() { fadeAmount := uint8(15) gobot.Every(100*time.Millisecond, func() { - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } brightness = brightness + fadeAmount if brightness == 0 || brightness == 255 { fadeAmount = -fadeAmount @@ -37,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/digispark_mpl115a2.go b/examples/digispark_mpl115a2.go index b4bd8ea68..b31134353 100644 --- a/examples/digispark_mpl115a2.go +++ b/examples/digispark_mpl115a2.go @@ -35,8 +35,7 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/digispark_pca9501.go b/examples/digispark_pca9501.go index 81ae873e4..7023d8190 100644 --- a/examples/digispark_pca9501.go +++ b/examples/digispark_pca9501.go @@ -83,8 +83,7 @@ func main() { work, ) - err = robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/digispark_servo.go b/examples/digispark_servo.go index 7968b5ed4..4a6fd4d95 100644 --- a/examples/digispark_servo.go +++ b/examples/digispark_servo.go @@ -23,7 +23,9 @@ func main() { gobot.Every(1*time.Second, func() { i := uint8(gobot.Rand(180)) fmt.Println("Turning", i) - servo.Move(i) + if err := servo.Move(i); err != nil { + fmt.Println(err) + } }) } @@ -33,5 +35,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/dragonboard_button.go b/examples/dragonboard_button.go index 1a7f01fff..520f3965c 100644 --- a/examples/dragonboard_button.go +++ b/examples/dragonboard_button.go @@ -19,11 +19,11 @@ func main() { button := gpio.NewButtonDriver(dragonAdaptor, "GPIO_A") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { fmt.Println("button pressed") }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("button released") }) } @@ -34,5 +34,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_blink.go b/examples/edison_blink.go index 7d3dd1d9b..b30ee3269 100644 --- a/examples/edison_blink.go +++ b/examples/edison_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -22,7 +23,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -32,5 +35,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_blink_without_all_gobot_framework.go b/examples/edison_blink_without_all_gobot_framework.go index 935e1840c..b65e0b088 100644 --- a/examples/edison_blink_without_all_gobot_framework.go +++ b/examples/edison_blink_without_all_gobot_framework.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2/drivers/gpio" @@ -19,13 +20,19 @@ import ( // golang library to interact with sensors and other devices. func main() { e := edison.NewAdaptor() - e.Connect() + if err := e.Connect(); err != nil { + fmt.Println(err) + } led := gpio.NewLedDriver(e, "13") - led.Start() + if err := led.Start(); err != nil { + fmt.Println(err) + } for { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } time.Sleep(1000 * time.Millisecond) } } diff --git a/examples/edison_blinkm.go b/examples/edison_blinkm.go index 4b75e34af..390d4c710 100644 --- a/examples/edison_blinkm.go +++ b/examples/edison_blinkm.go @@ -24,8 +24,13 @@ func main() { r := byte(gobot.Rand(255)) g := byte(gobot.Rand(255)) b := byte(gobot.Rand(255)) - blinkm.Rgb(r, g, b) - color, _ := blinkm.Color() + if err := blinkm.Rgb(r, g, b); err != nil { + fmt.Println(err) + } + color, err := blinkm.Color() + if err != nil { + fmt.Println(err) + } fmt.Println("color", color) }) } @@ -36,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_bme280.go b/examples/edison_bme280.go index ec16959cc..0b0652981 100644 --- a/examples/edison_bme280.go +++ b/examples/edison_bme280.go @@ -53,8 +53,7 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/edison_button.go b/examples/edison_button.go index 022eedccb..34bc4ce85 100644 --- a/examples/edison_button.go +++ b/examples/edison_button.go @@ -7,6 +7,8 @@ package main import ( + "fmt" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/platforms/intel-iot/edison" @@ -19,11 +21,15 @@ func main() { led := gpio.NewLedDriver(e, "13") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - led.On() + _ = button.On(gpio.ButtonPush, func(data interface{}) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { - led.Off() + _ = button.On(gpio.ButtonRelease, func(data interface{}) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -33,5 +39,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_button_led.go b/examples/edison_button_led.go index 74e0456db..28356ca23 100644 --- a/examples/edison_button_led.go +++ b/examples/edison_button_led.go @@ -7,6 +7,8 @@ package main import ( + "fmt" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/platforms/intel-iot/edison" @@ -19,11 +21,15 @@ func main() { led := gpio.NewLedDriver(e, "4") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - led.On() + _ = button.On(gpio.ButtonPush, func(data interface{}) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { - led.Off() + _ = button.On(gpio.ButtonRelease, func(data interface{}) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -33,5 +39,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_button_led_api.go b/examples/edison_button_led_api.go index 7884d3aac..70dad36df 100644 --- a/examples/edison_button_led_api.go +++ b/examples/edison_button_led_api.go @@ -7,11 +7,12 @@ package main import ( + "fmt" + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/api" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/platforms/intel-iot/edison" - - "gobot.io/x/gobot/v2/api" ) func main() { @@ -24,11 +25,15 @@ func main() { led := gpio.NewLedDriver(e, "4") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - led.On() + _ = button.On(gpio.ButtonPush, func(data interface{}) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { - led.Off() + _ = button.On(gpio.ButtonRelease, func(data interface{}) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -40,5 +45,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_accelerometer.go b/examples/edison_grove_accelerometer.go index 845d89d19..c4b551530 100644 --- a/examples/edison_grove_accelerometer.go +++ b/examples/edison_grove_accelerometer.go @@ -36,5 +36,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_blink.go b/examples/edison_grove_blink.go index f390ef6b1..54617b10a 100644 --- a/examples/edison_grove_blink.go +++ b/examples/edison_grove_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_button.go b/examples/edison_grove_button.go index af5459400..7a86dc963 100644 --- a/examples/edison_grove_button.go +++ b/examples/edison_grove_button.go @@ -19,11 +19,11 @@ func main() { button := gpio.NewButtonDriver(e, "2") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { fmt.Println("On!") }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("Off!") }) } @@ -34,5 +34,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_buzzer.go b/examples/edison_grove_buzzer.go index 2721dc938..cb00294ab 100644 --- a/examples/edison_grove_buzzer.go +++ b/examples/edison_grove_buzzer.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -42,7 +43,9 @@ func main() { } for _, val := range song { - buzzer.Tone(val.tone, val.duration) + if err := buzzer.Tone(val.tone, val.duration); err != nil { + fmt.Println(err) + } time.Sleep(10 * time.Millisecond) } } @@ -53,5 +56,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_lcd.go b/examples/edison_grove_lcd.go index 040a927bb..6c4fc8cc3 100644 --- a/examples/edison_grove_lcd.go +++ b/examples/edison_grove_lcd.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -19,26 +20,46 @@ func main() { screen := i2c.NewGroveLcdDriver(board) work := func() { - screen.Write("hello") + if err := screen.Write("hello"); err != nil { + fmt.Println(err) + } - screen.SetRGB(255, 0, 0) + if err := screen.SetRGB(255, 0, 0); err != nil { + fmt.Println(err) + } gobot.After(5*time.Second, func() { - screen.Clear() - screen.Home() - screen.SetRGB(0, 255, 0) + if err := screen.Clear(); err != nil { + fmt.Println(err) + } + if err := screen.Home(); err != nil { + fmt.Println(err) + } + if err := screen.SetRGB(0, 255, 0); err != nil { + fmt.Println(err) + } // set a custom character in the first position - screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]) + if err := screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]); err != nil { + fmt.Println(err) + } // add the custom character at the end of the string - screen.Write("goodbye\nhave a nice day " + string(byte(0))) + if err := screen.Write("goodbye\nhave a nice day " + string(byte(0))); err != nil { + fmt.Println(err) + } gobot.Every(500*time.Millisecond, func() { - screen.Scroll(false) + if err := screen.Scroll(false); err != nil { + fmt.Println(err) + } }) }) - screen.Home() + if err := screen.Home(); err != nil { + fmt.Println(err) + } time.Sleep(1 * time.Second) - screen.SetRGB(0, 0, 255) + if err := screen.SetRGB(0, 0, 255); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("screenBot", @@ -47,5 +68,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_led.go b/examples/edison_grove_led.go index 440f58012..2c11fadbf 100644 --- a/examples/edison_grove_led.go +++ b/examples/edison_grove_led.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_light_sensor.go b/examples/edison_grove_light_sensor.go index 68f08784f..08a2b74ec 100644 --- a/examples/edison_grove_light_sensor.go +++ b/examples/edison_grove_light_sensor.go @@ -20,7 +20,7 @@ func main() { sensor := aio.NewGroveLightSensorDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(sensor.Event("data"), func(data interface{}) { + _ = sensor.On(sensor.Event("data"), func(data interface{}) { fmt.Println("sensor", data) }) } @@ -31,5 +31,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_piezo_vibration.go b/examples/edison_grove_piezo_vibration.go index ea30c7e5b..7a0a5739c 100644 --- a/examples/edison_grove_piezo_vibration.go +++ b/examples/edison_grove_piezo_vibration.go @@ -20,7 +20,7 @@ func main() { sensor := aio.NewGrovePiezoVibrationSensorDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(aio.Vibration, func(data interface{}) { + _ = sensor.On(aio.Vibration, func(data interface{}) { fmt.Println("got one!") }) } @@ -31,5 +31,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_rotary_sensor.go b/examples/edison_grove_rotary_sensor.go index 6fbde9e86..ac04ced35 100644 --- a/examples/edison_grove_rotary_sensor.go +++ b/examples/edison_grove_rotary_sensor.go @@ -20,7 +20,7 @@ func main() { sensor := aio.NewGroveRotaryDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } @@ -31,5 +31,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_sound_sensor.go b/examples/edison_grove_sound_sensor.go index 794355297..9cec7fe95 100644 --- a/examples/edison_grove_sound_sensor.go +++ b/examples/edison_grove_sound_sensor.go @@ -20,7 +20,7 @@ func main() { sensor := aio.NewGroveSoundSensorDriver(board, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } @@ -31,5 +31,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_temperature_sensor.go b/examples/edison_grove_temperature_sensor.go index 6886f6093..0d6c2bf69 100644 --- a/examples/edison_grove_temperature_sensor.go +++ b/examples/edison_grove_temperature_sensor.go @@ -31,5 +31,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_grove_touch.go b/examples/edison_grove_touch.go index 3e9696730..c8b7f7632 100644 --- a/examples/edison_grove_touch.go +++ b/examples/edison_grove_touch.go @@ -19,11 +19,11 @@ func main() { touch := gpio.NewButtonDriver(e, "2") work := func() { - touch.On(gpio.ButtonPush, func(data interface{}) { + _ = touch.On(gpio.ButtonPush, func(data interface{}) { fmt.Println("On!") }) - touch.On(gpio.ButtonRelease, func(data interface{}) { + _ = touch.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("Off!") }) } @@ -34,5 +34,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_led_brightness.go b/examples/edison_led_brightness.go index 11537e0c4..6fe99158f 100644 --- a/examples/edison_led_brightness.go +++ b/examples/edison_led_brightness.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -23,7 +24,9 @@ func main() { fadeAmount := uint8(15) gobot.Every(100*time.Millisecond, func() { - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } brightness = brightness + fadeAmount if brightness == 0 || brightness == 255 { fadeAmount = -fadeAmount @@ -37,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_led_brightness_with_analog_input.go b/examples/edison_led_brightness_with_analog_input.go index 9b82fefae..134e9f8d3 100644 --- a/examples/edison_led_brightness_with_analog_input.go +++ b/examples/edison_led_brightness_with_analog_input.go @@ -22,13 +22,15 @@ func main() { led := gpio.NewLedDriver(e, "3") work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { brightness := uint8( gobot.ToScale(gobot.FromScale(float64(data.(int)), 0, 4096), 0, 255), ) fmt.Println("sensor", data) fmt.Println("brightness", brightness) - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } }) } @@ -38,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_miniboard_grove_accelerometer.go b/examples/edison_miniboard_grove_accelerometer.go index b20c511d2..4b86bd4f3 100644 --- a/examples/edison_miniboard_grove_accelerometer.go +++ b/examples/edison_miniboard_grove_accelerometer.go @@ -37,5 +37,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/edison_rgb_led.go b/examples/edison_rgb_led.go index 427a26c3e..966887dc1 100644 --- a/examples/edison_rgb_led.go +++ b/examples/edison_rgb_led.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -23,7 +24,9 @@ func main() { r := uint8(gobot.Rand(255)) g := uint8(gobot.Rand(255)) b := uint8(gobot.Rand(255)) - led.SetRGB(r, g, b) + if err := led.SetRGB(r, g, b); err != nil { + fmt.Println(err) + } }) } @@ -33,5 +36,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/every_done.go b/examples/every_done.go index 607f50738..987dbe79b 100644 --- a/examples/every_done.go +++ b/examples/every_done.go @@ -28,5 +28,7 @@ func main() { }, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_adxl345.go b/examples/firmata_adxl345.go index a791c2bb9..a8a7e67a9 100644 --- a/examples/firmata_adxl345.go +++ b/examples/firmata_adxl345.go @@ -41,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_aip1640.go b/examples/firmata_aip1640.go index a2e4527f6..95f57a1eb 100644 --- a/examples/firmata_aip1640.go +++ b/examples/firmata_aip1640.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -38,7 +39,9 @@ func main() { aip1640.Clear() gobot.Every(600*time.Millisecond, func() { aip1640.DrawMatrix(smiles[s]) - aip1640.Display() + if err := aip1640.Display(); err != nil { + fmt.Println(err) + } s++ if s > 2 { s = 0 @@ -52,5 +55,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_blink.go b/examples/firmata_blink.go index ee7ab54fb..badde5f15 100644 --- a/examples/firmata_blink.go +++ b/examples/firmata_blink.go @@ -29,7 +29,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -39,8 +41,7 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/firmata_blink_api.go b/examples/firmata_blink_api.go index 35a6db397..9d8c027c1 100644 --- a/examples/firmata_blink_api.go +++ b/examples/firmata_blink_api.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -25,7 +26,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -37,5 +40,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_blink_metal.go b/examples/firmata_blink_metal.go index 72136f317..60d73ea06 100644 --- a/examples/firmata_blink_metal.go +++ b/examples/firmata_blink_metal.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2/drivers/gpio" @@ -19,13 +20,19 @@ import ( // golang library to interact with sensors and other devices. func main() { f := firmata.NewAdaptor("/dev/ttyACM0") - f.Connect() + if err := f.Connect(); err != nil { + fmt.Println(err) + } led := gpio.NewLedDriver(f, "13") - led.Start() + if err := led.Start(); err != nil { + fmt.Println(err) + } for { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } time.Sleep(1000 * time.Millisecond) } } diff --git a/examples/firmata_blink_robot.go b/examples/firmata_blink_robot.go index 76c276a84..aa83119f1 100644 --- a/examples/firmata_blink_robot.go +++ b/examples/firmata_blink_robot.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_blinkm.go b/examples/firmata_blinkm.go index e86c6e549..c1d9653e6 100644 --- a/examples/firmata_blinkm.go +++ b/examples/firmata_blinkm.go @@ -32,8 +32,13 @@ func main() { r := byte(gobot.Rand(255)) g := byte(gobot.Rand(255)) b := byte(gobot.Rand(255)) - blinkm.Rgb(r, g, b) - color, _ := blinkm.Color() + if err := blinkm.Rgb(r, g, b); err != nil { + fmt.Println(err) + } + color, err := blinkm.Color() + if err != nil { + fmt.Println(err) + } fmt.Println("color", color) }) } @@ -44,5 +49,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_bme280.go b/examples/firmata_bme280.go index e9e84ed0f..1cb47ecc3 100644 --- a/examples/firmata_bme280.go +++ b/examples/firmata_bme280.go @@ -42,5 +42,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_bmp180.go b/examples/firmata_bmp180.go index 78980e630..43932dc3f 100644 --- a/examples/firmata_bmp180.go +++ b/examples/firmata_bmp180.go @@ -36,5 +36,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_bmp280.go b/examples/firmata_bmp280.go index ff649a6e5..f11327294 100644 --- a/examples/firmata_bmp280.go +++ b/examples/firmata_bmp280.go @@ -39,5 +39,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_button.go b/examples/firmata_button.go index 0844b18c6..783cd7bb8 100644 --- a/examples/firmata_button.go +++ b/examples/firmata_button.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "gobot.io/x/gobot/v2" @@ -28,11 +29,15 @@ func main() { led := gpio.NewLedDriver(firmataAdaptor, "3") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - led.On() + _ = button.On(gpio.ButtonPush, func(data interface{}) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { - led.Off() + _ = button.On(gpio.ButtonRelease, func(data interface{}) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -42,5 +47,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_buzzer.go b/examples/firmata_buzzer.go index 2a406c95e..6089ffdc2 100644 --- a/examples/firmata_buzzer.go +++ b/examples/firmata_buzzer.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -50,7 +51,9 @@ func main() { } for _, val := range song { - buzzer.Tone(val.tone, val.duration) + if err := buzzer.Tone(val.tone, val.duration); err != nil { + fmt.Println(err) + } time.Sleep(10 * time.Millisecond) } } @@ -61,5 +64,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_cat_toy.go b/examples/firmata_cat_toy.go index e80f40c05..89f818300 100644 --- a/examples/firmata_cat_toy.go +++ b/examples/firmata_cat_toy.go @@ -35,7 +35,7 @@ func main() { work := func() { x := 90.0 z := 90.0 - leapDriver.On(leap.MessageEvent, func(data interface{}) { + _ = leapDriver.On(leap.MessageEvent, func(data interface{}) { if len(data.(leap.Frame).Hands) > 0 { hand := data.(leap.Frame).Hands[0] x = gobot.ToScale(gobot.FromScale(hand.X(), -300, 300), 30, 150) @@ -43,8 +43,12 @@ func main() { } }) gobot.Every(10*time.Millisecond, func() { - servo1.Move(uint8(x)) - servo2.Move(uint8(z)) + if err := servo1.Move(uint8(x)); err != nil { + fmt.Println(err) + } + if err := servo2.Move(uint8(z)); err != nil { + fmt.Println(err) + } fmt.Println("Current Angle: ", servo1.Angle(), ",", servo2.Angle()) }) } @@ -55,5 +59,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_curie_imu.go b/examples/firmata_curie_imu.go index f9f53e4bf..084d80d51 100644 --- a/examples/firmata_curie_imu.go +++ b/examples/firmata_curie_imu.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "log" "os" "time" @@ -30,31 +31,41 @@ func main() { imu := curie.NewIMUDriver(firmataAdaptor) work := func() { - imu.On("Accelerometer", func(data interface{}) { + _ = imu.On("Accelerometer", func(data interface{}) { log.Println("Accelerometer", data) }) - imu.On("Gyroscope", func(data interface{}) { + _ = imu.On("Gyroscope", func(data interface{}) { log.Println("Gyroscope", data) }) - imu.On("Temperature", func(data interface{}) { + _ = imu.On("Temperature", func(data interface{}) { log.Println("Temperature", data) }) - imu.On("Motion", func(data interface{}) { + _ = imu.On("Motion", func(data interface{}) { log.Println("Motion", data) }) gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(100*time.Millisecond, func() { - imu.ReadAccelerometer() - imu.ReadGyroscope() - imu.ReadTemperature() - imu.ReadMotion() + if err := imu.ReadAccelerometer(); err != nil { + fmt.Println(err) + } + if err := imu.ReadGyroscope(); err != nil { + fmt.Println(err) + } + if err := imu.ReadTemperature(); err != nil { + fmt.Println(err) + } + if err := imu.ReadMotion(); err != nil { + fmt.Println(err) + } }) } @@ -64,5 +75,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_curie_imu_shock_detect.go b/examples/firmata_curie_imu_shock_detect.go index bbc09abbf..2c212a299 100644 --- a/examples/firmata_curie_imu_shock_detect.go +++ b/examples/firmata_curie_imu_shock_detect.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "log" "os" "time" @@ -30,15 +31,19 @@ func main() { imu := curie.NewIMUDriver(firmataAdaptor) work := func() { - imu.On("Shock", func(data interface{}) { + _ = imu.On("Shock", func(data interface{}) { log.Println("Shock", data) }) gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) - imu.EnableShockDetection(true) + if err := imu.EnableShockDetection(true); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("curieBot", @@ -47,5 +52,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_curie_imu_step_counter.go b/examples/firmata_curie_imu_step_counter.go index a6797586f..8cfea03c4 100644 --- a/examples/firmata_curie_imu_step_counter.go +++ b/examples/firmata_curie_imu_step_counter.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "log" "os" "time" @@ -30,15 +31,19 @@ func main() { imu := curie.NewIMUDriver(firmataAdaptor) work := func() { - imu.On("Steps", func(data interface{}) { + _ = imu.On("Steps", func(data interface{}) { log.Println("Steps", data) }) gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) - imu.EnableStepCounter(true) + if err := imu.EnableStepCounter(true); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("curieBot", @@ -47,5 +52,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_curie_imu_tap_detect.go b/examples/firmata_curie_imu_tap_detect.go index 501711b0a..8aedc380f 100644 --- a/examples/firmata_curie_imu_tap_detect.go +++ b/examples/firmata_curie_imu_tap_detect.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "log" "os" "time" @@ -30,15 +31,19 @@ func main() { imu := curie.NewIMUDriver(firmataAdaptor) work := func() { - imu.On("Tap", func(data interface{}) { + _ = imu.On("Tap", func(data interface{}) { log.Println("Tap", data) }) gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) - imu.EnableTapDetection(true) + if err := imu.EnableTapDetection(true); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("curieBot", @@ -47,5 +52,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_direct_pin.go b/examples/firmata_direct_pin.go index 2ba80f25d..351ce2d34 100644 --- a/examples/firmata_direct_pin.go +++ b/examples/firmata_direct_pin.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -30,7 +31,9 @@ func main() { level := byte(1) gobot.Every(1*time.Second, func() { - pin.DigitalWrite(level) + if err := pin.DigitalWrite(level); err != nil { + fmt.Println(err) + } if level == 1 { level = 0 } else { @@ -45,5 +48,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_gpio_max7219.go b/examples/firmata_gpio_max7219.go index d77865c64..87f3b7682 100644 --- a/examples/firmata_gpio_max7219.go +++ b/examples/firmata_gpio_max7219.go @@ -18,6 +18,7 @@ package main import ( + "fmt" "os" "time" @@ -37,8 +38,12 @@ func main() { work := func() { gobot.Every(100*time.Millisecond, func() { - max.ClearAll() - max.One(module, digit, bits) + if err := max.ClearAll(); err != nil { + fmt.Println(err) + } + if err := max.One(module, digit, bits); err != nil { + fmt.Println(err) + } bits = bits << 1 count++ @@ -64,5 +69,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_grove_lcd.go b/examples/firmata_grove_lcd.go index 4cf6287ba..821e8fba6 100644 --- a/examples/firmata_grove_lcd.go +++ b/examples/firmata_grove_lcd.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "os" "time" @@ -20,26 +21,46 @@ func main() { screen := i2c.NewGroveLcdDriver(board) work := func() { - screen.Write("hello") + if err := screen.Write("hello"); err != nil { + fmt.Println(err) + } - screen.SetRGB(255, 0, 0) + if err := screen.SetRGB(255, 0, 0); err != nil { + fmt.Println(err) + } gobot.After(5*time.Second, func() { - screen.Clear() - screen.Home() - screen.SetRGB(0, 255, 0) + if err := screen.Clear(); err != nil { + fmt.Println(err) + } + if err := screen.Home(); err != nil { + fmt.Println(err) + } + if err := screen.SetRGB(0, 255, 0); err != nil { + fmt.Println(err) + } // set a custom character in the first position - screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]) + if err := screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]); err != nil { + fmt.Println(err) + } // add the custom character at the end of the string - screen.Write("goodbye\nhave a nice day " + string(byte(0))) + if err := screen.Write("goodbye\nhave a nice day " + string(byte(0))); err != nil { + fmt.Println(err) + } gobot.Every(500*time.Millisecond, func() { - screen.Scroll(false) + if err := screen.Scroll(false); err != nil { + fmt.Println(err) + } }) }) - screen.Home() + if err := screen.Home(); err != nil { + fmt.Println(err) + } time.Sleep(1 * time.Second) - screen.SetRGB(0, 0, 255) + if err := screen.SetRGB(0, 0, 255); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("screenBot", @@ -48,5 +69,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_grove_sound_sensor.go b/examples/firmata_grove_sound_sensor.go index d118c7a52..1038126e6 100644 --- a/examples/firmata_grove_sound_sensor.go +++ b/examples/firmata_grove_sound_sensor.go @@ -21,7 +21,7 @@ func main() { sensor := aio.NewGroveSoundSensorDriver(board, "3", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } @@ -32,5 +32,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_hmc6352.go b/examples/firmata_hmc6352.go index 74c307c26..90031127d 100644 --- a/examples/firmata_hmc6352.go +++ b/examples/firmata_hmc6352.go @@ -40,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_integration.go b/examples/firmata_integration.go index eafbddbc9..9b1917482 100644 --- a/examples/firmata_integration.go +++ b/examples/firmata_integration.go @@ -33,18 +33,26 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led1.Toggle() + if err := led1.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(2*time.Second, func() { - led2.Toggle() + if err := led2.Toggle(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonPush, func(data interface{}) { - led2.On() + _ = button.On(gpio.ButtonPush, func(data interface{}) { + if err := led2.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { - led2.Off() + _ = button.On(gpio.ButtonRelease, func(data interface{}) { + if err := led2.Off(); err != nil { + fmt.Println(err) + } }) - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } @@ -55,5 +63,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_led_brightness.go b/examples/firmata_led_brightness.go index 970093a02..08ef5cdd7 100644 --- a/examples/firmata_led_brightness.go +++ b/examples/firmata_led_brightness.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -31,7 +32,9 @@ func main() { fadeAmount := uint8(15) gobot.Every(100*time.Millisecond, func() { - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } brightness = brightness + fadeAmount if brightness == 0 || brightness == 255 { fadeAmount = -fadeAmount @@ -45,5 +48,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_led_brightness_with_analog_input.go b/examples/firmata_led_brightness_with_analog_input.go index 3c86ae375..177e66d2e 100644 --- a/examples/firmata_led_brightness_with_analog_input.go +++ b/examples/firmata_led_brightness_with_analog_input.go @@ -30,13 +30,15 @@ func main() { led := gpio.NewLedDriver(firmataAdaptor, "3") work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { brightness := uint8( gobot.ToScale(gobot.FromScale(float64(data.(int)), 0, 1024), 0, 255), ) fmt.Println("sensor", data) fmt.Println("brightness", brightness) - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } }) } @@ -46,5 +48,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_lidarlite.go b/examples/firmata_lidarlite.go index ff6a1ced9..eba2c217b 100644 --- a/examples/firmata_lidarlite.go +++ b/examples/firmata_lidarlite.go @@ -40,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_metal_button.go b/examples/firmata_metal_button.go index 003d34c7d..d5cd9d79e 100644 --- a/examples/firmata_metal_button.go +++ b/examples/firmata_metal_button.go @@ -23,20 +23,30 @@ import ( func main() { f := firmata.NewAdaptor(os.Args[1]) - f.Connect() + if err := f.Connect(); err != nil { + fmt.Println(err) + } led := gpio.NewLedDriver(f, "2") - led.Start() - led.Off() + if err := led.Start(); err != nil { + fmt.Println(err) + } + if err := led.Off(); err != nil { + fmt.Println(err) + } button := gpio.NewButtonDriver(f, "3") - button.Start() + if err := button.Start(); err != nil { + fmt.Println(err) + } buttonEvents := button.Subscribe() for event := range buttonEvents { fmt.Println("Event:", event.Name, event.Data) if event.Name == gpio.ButtonPush { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } } } } diff --git a/examples/firmata_mma7660.go b/examples/firmata_mma7660.go index 4e9c804e3..db4f19a76 100644 --- a/examples/firmata_mma7660.go +++ b/examples/firmata_mma7660.go @@ -44,5 +44,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_motor.go b/examples/firmata_motor.go index f3abbf200..590ae7322 100644 --- a/examples/firmata_motor.go +++ b/examples/firmata_motor.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -31,7 +32,9 @@ func main() { fadeAmount := byte(15) gobot.Every(100*time.Millisecond, func() { - motor.SetSpeed(speed) + if err := motor.SetSpeed(speed); err != nil { + fmt.Println(err) + } speed = speed + fadeAmount if speed == 0 || speed == 255 { fadeAmount = -fadeAmount @@ -45,5 +48,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_mpl115a2.go b/examples/firmata_mpl115a2.go index 20e943fba..ae1f8ba5d 100644 --- a/examples/firmata_mpl115a2.go +++ b/examples/firmata_mpl115a2.go @@ -43,5 +43,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_mpu6050.go b/examples/firmata_mpu6050.go index 231a6eadc..2bdf25c11 100644 --- a/examples/firmata_mpu6050.go +++ b/examples/firmata_mpu6050.go @@ -29,7 +29,9 @@ func main() { work := func() { gobot.Every(100*time.Millisecond, func() { - mpu6050.GetData() + if err := mpu6050.GetData(); err != nil { + fmt.Println(err) + } fmt.Println("Accelerometer", mpu6050.Accelerometer) fmt.Println("Gyroscope", mpu6050.Gyroscope) @@ -43,5 +45,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_pca9685.go b/examples/firmata_pca9685.go index 658b96e98..05e56c766 100644 --- a/examples/firmata_pca9685.go +++ b/examples/firmata_pca9685.go @@ -30,17 +30,23 @@ func main() { servo := gpio.NewServoDriver(pca9685, "15") work := func() { - pca9685.SetPWMFreq(60) + if err := pca9685.SetPWMFreq(60); err != nil { + fmt.Println(err) + } for i := 10; i < 150; i += 10 { fmt.Println("Turning", i) - servo.Move(uint8(i)) + if err := servo.Move(uint8(i)); err != nil { + fmt.Println(err) + } time.Sleep(1 * time.Second) } for i := 150; i > 10; i -= 10 { fmt.Println("Turning", i) - servo.Move(uint8(i)) + if err := servo.Move(uint8(i)); err != nil { + fmt.Println(err) + } time.Sleep(1 * time.Second) } } @@ -51,5 +57,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_pir_motion.go b/examples/firmata_pir_motion.go index ceb4fd0d2..d67d6a63e 100644 --- a/examples/firmata_pir_motion.go +++ b/examples/firmata_pir_motion.go @@ -29,13 +29,17 @@ func main() { led := gpio.NewLedDriver(firmataAdaptor, "13") work := func() { - sensor.On(gpio.MotionDetected, func(data interface{}) { + _ = sensor.On(gpio.MotionDetected, func(data interface{}) { fmt.Println(gpio.MotionDetected) - led.On() + if err := led.On(); err != nil { + fmt.Println(err) + } }) - sensor.On(gpio.MotionStopped, func(data interface{}) { + _ = sensor.On(gpio.MotionStopped, func(data interface{}) { fmt.Println(gpio.MotionStopped) - led.Off() + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -45,5 +49,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_rgb_led.go b/examples/firmata_rgb_led.go index e9cd613bc..8a246b66d 100644 --- a/examples/firmata_rgb_led.go +++ b/examples/firmata_rgb_led.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -31,7 +32,9 @@ func main() { r := uint8(gobot.Rand(255)) g := uint8(gobot.Rand(255)) b := uint8(gobot.Rand(255)) - led.SetRGB(r, g, b) + if err := led.SetRGB(r, g, b); err != nil { + fmt.Println(err) + } }) } @@ -41,5 +44,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_servo.go b/examples/firmata_servo.go index c55a0b35e..ed1cbb07d 100644 --- a/examples/firmata_servo.go +++ b/examples/firmata_servo.go @@ -31,7 +31,9 @@ func main() { gobot.Every(1*time.Second, func() { i := uint8(gobot.Rand(180)) fmt.Println("Turning", i) - servo.Move(i) + if err := servo.Move(i); err != nil { + fmt.Println(err) + } }) } @@ -41,5 +43,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_ssd1306.go b/examples/firmata_ssd1306.go index 14ad349db..2b50b7c1c 100644 --- a/examples/firmata_ssd1306.go +++ b/examples/firmata_ssd1306.go @@ -37,7 +37,9 @@ func main() { } } stage = !stage - oled.Display() + if err := oled.Display(); err != nil { + fmt.Println(err) + } }) } @@ -47,5 +49,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_temp36.go b/examples/firmata_temp36.go index 94fca35a4..d42494c78 100644 --- a/examples/firmata_temp36.go +++ b/examples/firmata_temp36.go @@ -48,5 +48,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_tm1638.go b/examples/firmata_tm1638.go index 0d80c9c01..b64143b50 100644 --- a/examples/firmata_tm1638.go +++ b/examples/firmata_tm1638.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -46,10 +47,18 @@ func main() { work := func() { gobot.Every(400*time.Millisecond, func() { // Enable and change the color of the LEDs - modules[0].SetLED(color, ledInt) - modules[1].SetLED(color, ledInt) - modules[2].SetLED(color, ledInt) - modules[3].SetLED(color, ledInt) + if err := modules[0].SetLED(color, ledInt); err != nil { + fmt.Println(err) + } + if err := modules[1].SetLED(color, ledInt); err != nil { + fmt.Println(err) + } + if err := modules[2].SetLED(color, ledInt); err != nil { + fmt.Println(err) + } + if err := modules[3].SetLED(color, ledInt); err != nil { + fmt.Println(err) + } ledInt++ if ledInt > 7 { @@ -62,7 +71,9 @@ func main() { // Scroll the text for i := 0; i < 4; i++ { - modules[i].SetDisplayText(text[offset+8*i : offset+8*i+8]) + if err := modules[i].SetDisplayText(text[offset+8*i : offset+8*i+8]); err != nil { + fmt.Println(err) + } } offset++ if offset >= len(showText) { @@ -77,5 +88,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_travis.go b/examples/firmata_travis.go index 51862ff9b..c8f16ff83 100644 --- a/examples/firmata_travis.go +++ b/examples/firmata_travis.go @@ -42,13 +42,21 @@ type TravisResponse struct { } func turnOn(robot *gobot.Robot, device string) { - robot.Device(device).(*gpio.LedDriver).On() + if err := robot.Device(device).(*gpio.LedDriver).On(); err != nil { + fmt.Println(err) + } } func resetLeds(robot *gobot.Robot) { - robot.Device("red").(*gpio.LedDriver).Off() - robot.Device("green").(*gpio.LedDriver).Off() - robot.Device("blue").(*gpio.LedDriver).Off() + if err := robot.Device("red").(*gpio.LedDriver).Off(); err != nil { + fmt.Println(err) + } + if err := robot.Device("green").(*gpio.LedDriver).Off(); err != nil { + fmt.Println(err) + } + if err := robot.Device("blue").(*gpio.LedDriver).Off(); err != nil { + fmt.Println(err) + } } func checkTravis(robot *gobot.Robot) { @@ -68,7 +76,9 @@ func checkTravis(robot *gobot.Robot) { panic(err) } var travis TravisResponse - json.Unmarshal(body, &travis) + if err := json.Unmarshal(body, &travis); err != nil { + fmt.Println(err) + } resetLeds(robot) if travis.LastBuildStatus == 0 { turnOn(robot, "green") @@ -98,5 +108,7 @@ func main() { ) master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/firmata_wiichuck.go b/examples/firmata_wiichuck.go index dff3c3ccd..22819ded2 100644 --- a/examples/firmata_wiichuck.go +++ b/examples/firmata_wiichuck.go @@ -27,19 +27,19 @@ func main() { wiichuck := i2c.NewWiichuckDriver(firmataAdaptor) work := func() { - wiichuck.On(wiichuck.Event("joystick"), func(data interface{}) { + _ = wiichuck.On(wiichuck.Event("joystick"), func(data interface{}) { fmt.Println("joystick", data) }) - wiichuck.On(wiichuck.Event("c"), func(data interface{}) { + _ = wiichuck.On(wiichuck.Event("c"), func(data interface{}) { fmt.Println("c") }) - wiichuck.On(wiichuck.Event("z"), func(data interface{}) { + _ = wiichuck.On(wiichuck.Event("z"), func(data interface{}) { fmt.Println("z") }) - wiichuck.On(wiichuck.Event("error"), func(data interface{}) { + _ = wiichuck.On(wiichuck.Event("error"), func(data interface{}) { fmt.Println("Wiichuck error:", data) }) } @@ -50,5 +50,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/gopigo3.go b/examples/gopigo3.go index 338cced0b..cca5ebfac 100644 --- a/examples/gopigo3.go +++ b/examples/gopigo3.go @@ -40,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/gopigo3_grove_button.go b/examples/gopigo3_grove_button.go index f1e376130..6ce4f3a20 100644 --- a/examples/gopigo3_grove_button.go +++ b/examples/gopigo3_grove_button.go @@ -22,13 +22,17 @@ func main() { button := gpio.NewButtonDriver(gpg3, "AD_2_1") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { fmt.Println("On!") - led.On() + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("Off!") - led.Off() + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -38,5 +42,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/gopigo3_grove_lcd.go b/examples/gopigo3_grove_lcd.go index 3423400db..bc3e2be14 100644 --- a/examples/gopigo3_grove_lcd.go +++ b/examples/gopigo3_grove_lcd.go @@ -7,6 +7,8 @@ package main import ( + "fmt" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/i2c" "gobot.io/x/gobot/v2/platforms/dexter/gopigo3" @@ -19,17 +21,24 @@ func main() { screen := i2c.NewGroveLcdDriver(raspiAdaptor) work := func() { - manufacturerName := "" - boardName := "" - hardwareVersion := "" - manufacturerName, _ = gpg3.GetManufacturerName() - boardName, _ = gpg3.GetBoardName() - hardwareVersion, _ = gpg3.GetHardwareVersion() - screen.Write(manufacturerName[0:15]) - screen.SetPosition(16) - screen.Write(boardName + " " + hardwareVersion) - screen.SetRGB(0, 0, 255) - screen.Home() + manufacturerName, _ := gpg3.GetManufacturerName() + boardName, _ := gpg3.GetBoardName() + hardwareVersion, _ := gpg3.GetHardwareVersion() + if err := screen.Write(manufacturerName[0:15]); err != nil { + fmt.Println(err) + } + if err := screen.SetPosition(16); err != nil { + fmt.Println(err) + } + if err := screen.Write(boardName + " " + hardwareVersion); err != nil { + fmt.Println(err) + } + if err := screen.SetRGB(0, 0, 255); err != nil { + fmt.Println(err) + } + if err := screen.Home(); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("gopigo3lcd", @@ -38,5 +47,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/gopigo3_grove_light_sensor.go b/examples/gopigo3_grove_light_sensor.go index 8454f96fc..ae99fb191 100644 --- a/examples/gopigo3_grove_light_sensor.go +++ b/examples/gopigo3_grove_light_sensor.go @@ -22,7 +22,7 @@ func main() { sensor := aio.NewGroveLightSensorDriver(gpg3, "AD_1_1", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(sensor.Event("data"), func(data interface{}) { + _ = sensor.On(sensor.Event("data"), func(data interface{}) { fmt.Println("sensor", data) }) } @@ -33,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/gopigo3_led_brightness.go b/examples/gopigo3_led_brightness.go index 62a57e556..417363f35 100644 --- a/examples/gopigo3_led_brightness.go +++ b/examples/gopigo3_led_brightness.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -25,7 +26,9 @@ func main() { fadeAmount := uint8(15) gobot.Every(100*time.Millisecond, func() { - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } brightness = brightness + fadeAmount if brightness == 0 || brightness == 255 { fadeAmount = -fadeAmount @@ -39,5 +42,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/gopigo3_servo.go b/examples/gopigo3_servo.go index dbb943cb8..04e50bfdf 100644 --- a/examples/gopigo3_servo.go +++ b/examples/gopigo3_servo.go @@ -25,7 +25,9 @@ func main() { gobot.Every(1*time.Second, func() { i := uint8(gobot.Rand(180)) fmt.Println("Turning", i) - servo.Move(i) + if err := servo.Move(i); err != nil { + fmt.Println(err) + } }) } @@ -35,5 +37,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/hello.go b/examples/hello.go index 6f1503675..88ef3bd55 100644 --- a/examples/hello.go +++ b/examples/hello.go @@ -20,5 +20,7 @@ func main() { }, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/hello_api.go b/examples/hello_api.go index 5707720c3..9079343b8 100644 --- a/examples/hello_api.go +++ b/examples/hello_api.go @@ -36,5 +36,7 @@ func main() { return fmt.Sprintf("This command is attached to the robot %v", hello.Name) }) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/hello_api_auth.go b/examples/hello_api_auth.go index 04da9e86b..a4fa3249e 100644 --- a/examples/hello_api_auth.go +++ b/examples/hello_api_auth.go @@ -38,5 +38,7 @@ func main() { return fmt.Sprintf("This command is attached to the robot %v", hello.Name) }) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/hello_api_custom.go b/examples/hello_api_custom.go index 7fddff341..895165ecb 100644 --- a/examples/hello_api_custom.go +++ b/examples/hello_api_custom.go @@ -21,11 +21,15 @@ func main() { // creates routes/handlers for the custom API a.Get("/", func(res http.ResponseWriter, req *http.Request) { - res.Write([]byte("OK")) + if _, err := res.Write([]byte("OK")); err != nil { + fmt.Println(err) + } }) a.Get("/api/hello", func(res http.ResponseWriter, req *http.Request) { msg := fmt.Sprintf("This command is attached to the robot %v", master.Robot("hello").Name) - res.Write([]byte(msg)) + if _, err := res.Write([]byte(msg)); err != nil { + fmt.Println(err) + } }) // starts the API without the default C2PIO API and Robeaux web interface. @@ -33,5 +37,7 @@ func main() { master.AddRobot(gobot.NewRobot("hello")) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/hello_api_video.go b/examples/hello_api_video.go index 3d63fe046..dbcf73e1d 100644 --- a/examples/hello_api_video.go +++ b/examples/hello_api_video.go @@ -61,7 +61,9 @@ func main() { // start capturing go mjpegCapture() - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } func mjpegCapture() { diff --git a/examples/holystone_hs200.go b/examples/holystone_hs200.go index 7d9473b8d..db5ccb890 100644 --- a/examples/holystone_hs200.go +++ b/examples/holystone_hs200.go @@ -36,5 +36,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/jetson-nano_blink.go b/examples/jetson-nano_blink.go index cd5632e49..c6b29ce94 100644 --- a/examples/jetson-nano_blink.go +++ b/examples/jetson-nano_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/jetson-nano_servo.go b/examples/jetson-nano_servo.go index 064589ffc..5eaafe92b 100644 --- a/examples/jetson-nano_servo.go +++ b/examples/jetson-nano_servo.go @@ -12,6 +12,7 @@ package main // 2. if end pin configure, reboot Jetson nano. // 3. run gobot import ( + "fmt" "log" "time" @@ -29,7 +30,9 @@ func main() { work := func() { gobot.Every(100*time.Millisecond, func() { log.Println("Turning", counter) - servo.Move(uint8(counter)) + if err := servo.Move(uint8(counter)); err != nil { + fmt.Println(err) + } if counter == 140 { flg = false } else if counter == 30 { @@ -50,5 +53,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joule_blink.go b/examples/joule_blink.go index 875529205..560237827 100644 --- a/examples/joule_blink.go +++ b/examples/joule_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joule_blinkm.go b/examples/joule_blinkm.go index cc6ac5ae6..97676ebaa 100644 --- a/examples/joule_blinkm.go +++ b/examples/joule_blinkm.go @@ -24,8 +24,13 @@ func main() { r := byte(gobot.Rand(255)) g := byte(gobot.Rand(255)) b := byte(gobot.Rand(255)) - blinkm.Rgb(r, g, b) - color, _ := blinkm.Color() + if err := blinkm.Rgb(r, g, b); err != nil { + fmt.Println(err) + } + color, err := blinkm.Color() + if err != nil { + fmt.Println(err) + } fmt.Println("color", color) }) } @@ -36,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joule_grove_lcd.go b/examples/joule_grove_lcd.go index ec2afd3b8..929f181a0 100644 --- a/examples/joule_grove_lcd.go +++ b/examples/joule_grove_lcd.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -19,26 +20,46 @@ func main() { screen := i2c.NewGroveLcdDriver(board) work := func() { - screen.Write("hello") + if err := screen.Write("hello"); err != nil { + fmt.Println(err) + } - screen.SetRGB(255, 0, 0) + if err := screen.SetRGB(255, 0, 0); err != nil { + fmt.Println(err) + } gobot.After(5*time.Second, func() { - screen.Clear() - screen.Home() - screen.SetRGB(0, 255, 0) + if err := screen.Clear(); err != nil { + fmt.Println(err) + } + if err := screen.Home(); err != nil { + fmt.Println(err) + } + if err := screen.SetRGB(0, 255, 0); err != nil { + fmt.Println(err) + } // set a custom character in the first position - screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]) + if err := screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]); err != nil { + fmt.Println(err) + } // add the custom character at the end of the string - screen.Write("goodbye\nhave a nice day " + string(byte(0))) + if err := screen.Write("goodbye\nhave a nice day " + string(byte(0))); err != nil { + fmt.Println(err) + } gobot.Every(500*time.Millisecond, func() { - screen.Scroll(false) + if err := screen.Scroll(false); err != nil { + fmt.Println(err) + } }) }) - screen.Home() + if err := screen.Home(); err != nil { + fmt.Println(err) + } time.Sleep(1 * time.Second) - screen.SetRGB(0, 0, 255) + if err := screen.SetRGB(0, 0, 255); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("screenBot", @@ -47,5 +68,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joule_grove_rotary_sensor.go b/examples/joule_grove_rotary_sensor.go index bd1e7cbc6..afe9a78ef 100644 --- a/examples/joule_grove_rotary_sensor.go +++ b/examples/joule_grove_rotary_sensor.go @@ -22,7 +22,7 @@ func main() { sensor := aio.NewGroveRotaryDriver(ads1015, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } @@ -33,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joule_led_brightness.go b/examples/joule_led_brightness.go index 0fec54b7d..46a7793e3 100644 --- a/examples/joule_led_brightness.go +++ b/examples/joule_led_brightness.go @@ -24,8 +24,7 @@ func main() { fadeAmount := uint8(15) gobot.Every(100*time.Millisecond, func() { - err := led.Brightness(brightness) - if err != nil { + if err := led.Brightness(brightness); err != nil { fmt.Println(err) } brightness = brightness + fadeAmount @@ -41,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joule_led_brightness_with_analog_input.go b/examples/joule_led_brightness_with_analog_input.go index 167e3210a..277c3a242 100644 --- a/examples/joule_led_brightness_with_analog_input.go +++ b/examples/joule_led_brightness_with_analog_input.go @@ -24,11 +24,13 @@ func main() { led := gpio.NewLedDriver(e, "J12_26") work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { brightness := uint8(gobot.ToScale(gobot.FromScale(float64(data.(int)), 0, 1023), 0, 255)) fmt.Println("sensor", data) fmt.Println("brightness", brightness) - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } }) } @@ -38,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joule_leds.go b/examples/joule_leds.go index ec34e2159..4f68cd6f9 100644 --- a/examples/joule_leds.go +++ b/examples/joule_leds.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -22,22 +23,38 @@ func main() { led3 := gpio.NewLedDriver(e, "GP103") work := func() { - led0.Off() - led1.Off() - led2.Off() - led3.Off() + if err := led0.Off(); err != nil { + fmt.Println(err) + } + if err := led1.Off(); err != nil { + fmt.Println(err) + } + if err := led2.Off(); err != nil { + fmt.Println(err) + } + if err := led3.Off(); err != nil { + fmt.Println(err) + } gobot.Every(1*time.Second, func() { - led0.Toggle() + if err := led0.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(2*time.Second, func() { - led1.Toggle() + if err := led1.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(4*time.Second, func() { - led2.Toggle() + if err := led2.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(8*time.Second, func() { - led3.Toggle() + if err := led3.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -47,5 +64,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joule_rgb_led.go b/examples/joule_rgb_led.go index b94e9fc28..6f008969a 100644 --- a/examples/joule_rgb_led.go +++ b/examples/joule_rgb_led.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -23,7 +24,9 @@ func main() { r := uint8(gobot.Rand(255)) g := uint8(gobot.Rand(255)) b := uint8(gobot.Rand(255)) - led.SetRGB(r, g, b) + if err := led.SetRGB(r, g, b); err != nil { + fmt.Println(err) + } }) } @@ -33,5 +36,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joystick_ps3.go b/examples/joystick_ps3.go index 1d2f3a2ce..422f5c06a 100644 --- a/examples/joystick_ps3.go +++ b/examples/joystick_ps3.go @@ -19,110 +19,110 @@ func main() { work := func() { // buttons - stick.On(joystick.SquarePress, func(data interface{}) { + _ = stick.On(joystick.SquarePress, func(data interface{}) { fmt.Println("square_press") }) - stick.On(joystick.SquareRelease, func(data interface{}) { + _ = stick.On(joystick.SquareRelease, func(data interface{}) { fmt.Println("square_release") }) - stick.On(joystick.TrianglePress, func(data interface{}) { + _ = stick.On(joystick.TrianglePress, func(data interface{}) { fmt.Println("triangle_press") }) - stick.On(joystick.TriangleRelease, func(data interface{}) { + _ = stick.On(joystick.TriangleRelease, func(data interface{}) { fmt.Println("triangle_release") }) - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { fmt.Println("circle_press") }) - stick.On(joystick.CircleRelease, func(data interface{}) { + _ = stick.On(joystick.CircleRelease, func(data interface{}) { fmt.Println("circle_release") }) - stick.On(joystick.XPress, func(data interface{}) { + _ = stick.On(joystick.XPress, func(data interface{}) { fmt.Println("x_press") }) - stick.On(joystick.XRelease, func(data interface{}) { + _ = stick.On(joystick.XRelease, func(data interface{}) { fmt.Println("x_release") }) - stick.On(joystick.StartPress, func(data interface{}) { + _ = stick.On(joystick.StartPress, func(data interface{}) { fmt.Println("start_press") }) - stick.On(joystick.StartRelease, func(data interface{}) { + _ = stick.On(joystick.StartRelease, func(data interface{}) { fmt.Println("start_release") }) - stick.On(joystick.SelectPress, func(data interface{}) { + _ = stick.On(joystick.SelectPress, func(data interface{}) { fmt.Println("select_press") }) - stick.On(joystick.SelectRelease, func(data interface{}) { + _ = stick.On(joystick.SelectRelease, func(data interface{}) { fmt.Println("select_release") }) - stick.On(joystick.HomePress, func(data interface{}) { + _ = stick.On(joystick.HomePress, func(data interface{}) { fmt.Println("home_press") }) - stick.On(joystick.HomeRelease, func(data interface{}) { + _ = stick.On(joystick.HomeRelease, func(data interface{}) { fmt.Println("home_release") }) - stick.On(joystick.RightPress, func(data interface{}) { + _ = stick.On(joystick.RightPress, func(data interface{}) { fmt.Println("right_press") }) - stick.On(joystick.RightRelease, func(data interface{}) { + _ = stick.On(joystick.RightRelease, func(data interface{}) { fmt.Println("right_release") }) - stick.On(joystick.LeftPress, func(data interface{}) { + _ = stick.On(joystick.LeftPress, func(data interface{}) { fmt.Println("left_press") }) - stick.On(joystick.LeftRelease, func(data interface{}) { + _ = stick.On(joystick.LeftRelease, func(data interface{}) { fmt.Println("left_release") }) - stick.On(joystick.UpPress, func(data interface{}) { + _ = stick.On(joystick.UpPress, func(data interface{}) { fmt.Println("up_press") }) - stick.On(joystick.UpRelease, func(data interface{}) { + _ = stick.On(joystick.UpRelease, func(data interface{}) { fmt.Println("up_release") }) - stick.On(joystick.DownPress, func(data interface{}) { + _ = stick.On(joystick.DownPress, func(data interface{}) { fmt.Println("down_press") }) - stick.On(joystick.DownRelease, func(data interface{}) { + _ = stick.On(joystick.DownRelease, func(data interface{}) { fmt.Println("down_release") }) // joysticks - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { fmt.Println("left_x", data) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { fmt.Println("left_y", data) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { fmt.Println("right_x", data) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { fmt.Println("right_y", data) }) // triggers - stick.On(joystick.R1Press, func(data interface{}) { + _ = stick.On(joystick.R1Press, func(data interface{}) { fmt.Println("R1Press", data) }) - stick.On(joystick.R1Release, func(data interface{}) { + _ = stick.On(joystick.R1Release, func(data interface{}) { fmt.Println("R1Release", data) }) - stick.On(joystick.R2Press, func(data interface{}) { + _ = stick.On(joystick.R2Press, func(data interface{}) { fmt.Println("R2Press", data) }) - stick.On(joystick.R2Release, func(data interface{}) { + _ = stick.On(joystick.R2Release, func(data interface{}) { fmt.Println("R2Release", data) }) - stick.On(joystick.L1Press, func(data interface{}) { + _ = stick.On(joystick.L1Press, func(data interface{}) { fmt.Println("L1Press", data) }) - stick.On(joystick.L1Release, func(data interface{}) { + _ = stick.On(joystick.L1Release, func(data interface{}) { fmt.Println("L1Release", data) }) - stick.On(joystick.L2Press, func(data interface{}) { + _ = stick.On(joystick.L2Press, func(data interface{}) { fmt.Println("L2Press", data) }) - stick.On(joystick.L2Release, func(data interface{}) { + _ = stick.On(joystick.L2Release, func(data interface{}) { fmt.Println("L2Release", data) }) } @@ -133,5 +133,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joystick_ps4.go b/examples/joystick_ps4.go index c824090d4..de950ab76 100644 --- a/examples/joystick_ps4.go +++ b/examples/joystick_ps4.go @@ -18,114 +18,114 @@ func main() { stick := joystick.NewDriver(joystickAdaptor, joystick.Dualshock4) work := func() { - stick.On(joystick.SquarePress, func(data interface{}) { + _ = stick.On(joystick.SquarePress, func(data interface{}) { fmt.Println("square_press") }) - stick.On(joystick.SquareRelease, func(data interface{}) { + _ = stick.On(joystick.SquareRelease, func(data interface{}) { fmt.Println("square_release") }) - stick.On(joystick.TrianglePress, func(data interface{}) { + _ = stick.On(joystick.TrianglePress, func(data interface{}) { fmt.Println("triangle_press") }) - stick.On(joystick.TriangleRelease, func(data interface{}) { + _ = stick.On(joystick.TriangleRelease, func(data interface{}) { fmt.Println("triangle_release") }) - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { fmt.Println("circle_press") }) - stick.On(joystick.CircleRelease, func(data interface{}) { + _ = stick.On(joystick.CircleRelease, func(data interface{}) { fmt.Println("circle_release") }) - stick.On(joystick.XPress, func(data interface{}) { + _ = stick.On(joystick.XPress, func(data interface{}) { fmt.Println("x_press") }) - stick.On(joystick.XRelease, func(data interface{}) { + _ = stick.On(joystick.XRelease, func(data interface{}) { fmt.Println("x_release") }) - stick.On(joystick.HomePress, func(data interface{}) { + _ = stick.On(joystick.HomePress, func(data interface{}) { fmt.Println("home_press") }) - stick.On(joystick.HomeRelease, func(data interface{}) { + _ = stick.On(joystick.HomeRelease, func(data interface{}) { fmt.Println("home_release") }) - stick.On(joystick.SharePress, func(data interface{}) { + _ = stick.On(joystick.SharePress, func(data interface{}) { fmt.Println("share_press") }) - stick.On(joystick.ShareRelease, func(data interface{}) { + _ = stick.On(joystick.ShareRelease, func(data interface{}) { fmt.Println("share_release") }) - stick.On(joystick.OptionsPress, func(data interface{}) { + _ = stick.On(joystick.OptionsPress, func(data interface{}) { fmt.Println("options_press") }) - stick.On(joystick.OptionsRelease, func(data interface{}) { + _ = stick.On(joystick.OptionsRelease, func(data interface{}) { fmt.Println("options_release") }) - stick.On(joystick.L1Press, func(data interface{}) { + _ = stick.On(joystick.L1Press, func(data interface{}) { fmt.Println("l1_press") }) - stick.On(joystick.L1Release, func(data interface{}) { + _ = stick.On(joystick.L1Release, func(data interface{}) { fmt.Println("l1_release") }) - stick.On(joystick.L2Press, func(data interface{}) { + _ = stick.On(joystick.L2Press, func(data interface{}) { fmt.Println("l2_press") }) - stick.On(joystick.L2Release, func(data interface{}) { + _ = stick.On(joystick.L2Release, func(data interface{}) { fmt.Println("l2_release") }) - stick.On(joystick.R1Press, func(data interface{}) { + _ = stick.On(joystick.R1Press, func(data interface{}) { fmt.Println("r1_press") }) - stick.On(joystick.R1Release, func(data interface{}) { + _ = stick.On(joystick.R1Release, func(data interface{}) { fmt.Println("r1_release") }) - stick.On(joystick.R2Press, func(data interface{}) { + _ = stick.On(joystick.R2Press, func(data interface{}) { fmt.Println("r2_press") }) - stick.On(joystick.R2Release, func(data interface{}) { + _ = stick.On(joystick.R2Release, func(data interface{}) { fmt.Println("r2_release") }) - stick.On(joystick.UpPress, func(data interface{}) { + _ = stick.On(joystick.UpPress, func(data interface{}) { fmt.Println("up_press") }) - stick.On(joystick.UpRelease, func(data interface{}) { + _ = stick.On(joystick.UpRelease, func(data interface{}) { fmt.Println("up_release") }) - stick.On(joystick.DownPress, func(data interface{}) { + _ = stick.On(joystick.DownPress, func(data interface{}) { fmt.Println("down_press") }) - stick.On(joystick.DownRelease, func(data interface{}) { + _ = stick.On(joystick.DownRelease, func(data interface{}) { fmt.Println("down_release") }) - stick.On(joystick.RightPress, func(data interface{}) { + _ = stick.On(joystick.RightPress, func(data interface{}) { fmt.Println("right_press") }) - stick.On(joystick.RightRelease, func(data interface{}) { + _ = stick.On(joystick.RightRelease, func(data interface{}) { fmt.Println("right_release") }) - stick.On(joystick.LeftPress, func(data interface{}) { + _ = stick.On(joystick.LeftPress, func(data interface{}) { fmt.Println("left_press") }) - stick.On(joystick.LeftRelease, func(data interface{}) { + _ = stick.On(joystick.LeftRelease, func(data interface{}) { fmt.Println("left_release") }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { fmt.Println("left_x", data) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { fmt.Println("left_y", data) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { fmt.Println("right_x", data) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { fmt.Println("right_y", data) }) - stick.On(joystick.L2, func(data interface{}) { + _ = stick.On(joystick.L2, func(data interface{}) { fmt.Println("L2", data) }) - stick.On(joystick.R2, func(data interface{}) { + _ = stick.On(joystick.R2, func(data interface{}) { fmt.Println("R2", data) }) } @@ -136,5 +136,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joystick_ps5.go b/examples/joystick_ps5.go index d5cbf631b..0057a5a78 100644 --- a/examples/joystick_ps5.go +++ b/examples/joystick_ps5.go @@ -18,114 +18,114 @@ func main() { stick := joystick.NewDriver(joystickAdaptor, joystick.Dualsense) work := func() { - stick.On(joystick.SquarePress, func(data interface{}) { + _ = stick.On(joystick.SquarePress, func(data interface{}) { fmt.Println("square_press") }) - stick.On(joystick.SquareRelease, func(data interface{}) { + _ = stick.On(joystick.SquareRelease, func(data interface{}) { fmt.Println("square_release") }) - stick.On(joystick.TrianglePress, func(data interface{}) { + _ = stick.On(joystick.TrianglePress, func(data interface{}) { fmt.Println("triangle_press") }) - stick.On(joystick.TriangleRelease, func(data interface{}) { + _ = stick.On(joystick.TriangleRelease, func(data interface{}) { fmt.Println("triangle_release") }) - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { fmt.Println("circle_press") }) - stick.On(joystick.CircleRelease, func(data interface{}) { + _ = stick.On(joystick.CircleRelease, func(data interface{}) { fmt.Println("circle_release") }) - stick.On(joystick.XPress, func(data interface{}) { + _ = stick.On(joystick.XPress, func(data interface{}) { fmt.Println("x_press") }) - stick.On(joystick.XRelease, func(data interface{}) { + _ = stick.On(joystick.XRelease, func(data interface{}) { fmt.Println("x_release") }) - stick.On(joystick.HomePress, func(data interface{}) { + _ = stick.On(joystick.HomePress, func(data interface{}) { fmt.Println("home_press") }) - stick.On(joystick.HomeRelease, func(data interface{}) { + _ = stick.On(joystick.HomeRelease, func(data interface{}) { fmt.Println("home_release") }) - stick.On(joystick.CreatePress, func(data interface{}) { + _ = stick.On(joystick.CreatePress, func(data interface{}) { fmt.Println("create_press") }) - stick.On(joystick.CreateRelease, func(data interface{}) { + _ = stick.On(joystick.CreateRelease, func(data interface{}) { fmt.Println("create_release") }) - stick.On(joystick.OptionsPress, func(data interface{}) { + _ = stick.On(joystick.OptionsPress, func(data interface{}) { fmt.Println("options_press") }) - stick.On(joystick.OptionsRelease, func(data interface{}) { + _ = stick.On(joystick.OptionsRelease, func(data interface{}) { fmt.Println("options_release") }) - stick.On(joystick.L1Press, func(data interface{}) { + _ = stick.On(joystick.L1Press, func(data interface{}) { fmt.Println("l1_press") }) - stick.On(joystick.L1Release, func(data interface{}) { + _ = stick.On(joystick.L1Release, func(data interface{}) { fmt.Println("l1_release") }) - stick.On(joystick.R1Press, func(data interface{}) { + _ = stick.On(joystick.R1Press, func(data interface{}) { fmt.Println("r1_press") }) - stick.On(joystick.R1Release, func(data interface{}) { + _ = stick.On(joystick.R1Release, func(data interface{}) { fmt.Println("r1_release") }) - stick.On(joystick.PSPress, func(data interface{}) { + _ = stick.On(joystick.PSPress, func(data interface{}) { fmt.Println("ps_press") }) - stick.On(joystick.PSRelease, func(data interface{}) { + _ = stick.On(joystick.PSRelease, func(data interface{}) { fmt.Println("ps_release") }) - stick.On(joystick.TrackpadPress, func(data interface{}) { + _ = stick.On(joystick.TrackpadPress, func(data interface{}) { fmt.Println("trackpad_press") }) - stick.On(joystick.TrackpadRelease, func(data interface{}) { + _ = stick.On(joystick.TrackpadRelease, func(data interface{}) { fmt.Println("trackpad_release") }) - stick.On(joystick.UpPress, func(data interface{}) { + _ = stick.On(joystick.UpPress, func(data interface{}) { fmt.Println("up_press") }) - stick.On(joystick.UpRelease, func(data interface{}) { + _ = stick.On(joystick.UpRelease, func(data interface{}) { fmt.Println("up_release") }) - stick.On(joystick.DownPress, func(data interface{}) { + _ = stick.On(joystick.DownPress, func(data interface{}) { fmt.Println("down_press") }) - stick.On(joystick.DownRelease, func(data interface{}) { + _ = stick.On(joystick.DownRelease, func(data interface{}) { fmt.Println("down_release") }) - stick.On(joystick.RightPress, func(data interface{}) { + _ = stick.On(joystick.RightPress, func(data interface{}) { fmt.Println("right_press") }) - stick.On(joystick.RightRelease, func(data interface{}) { + _ = stick.On(joystick.RightRelease, func(data interface{}) { fmt.Println("right_release") }) - stick.On(joystick.LeftPress, func(data interface{}) { + _ = stick.On(joystick.LeftPress, func(data interface{}) { fmt.Println("left_press") }) - stick.On(joystick.LeftRelease, func(data interface{}) { + _ = stick.On(joystick.LeftRelease, func(data interface{}) { fmt.Println("left_release") }) - // stick.On(joystick.LeftX, func(data interface{}) { + // _ = stick.On(joystick.LeftX, func(data interface{}) { // fmt.Println("left_x", data) // }) - // stick.On(joystick.LeftY, func(data interface{}) { + // _ = stick.On(joystick.LeftY, func(data interface{}) { // fmt.Println("left_y", data) // }) - // stick.On(joystick.RightX, func(data interface{}) { + // _ = stick.On(joystick.RightX, func(data interface{}) { // fmt.Println("right_x", data) // }) - // stick.On(joystick.RightY, func(data interface{}) { + // _ = stick.On(joystick.RightY, func(data interface{}) { // fmt.Println("right_y", data) // }) - // stick.On(joystick.L2, func(data interface{}) { + // _ = stick.On(joystick.L2, func(data interface{}) { // fmt.Println("L2", data) // }) - // stick.On(joystick.R2, func(data interface{}) { + // _ = stick.On(joystick.R2, func(data interface{}) { // fmt.Println("R2", data) // }) } @@ -136,5 +136,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joystick_xbox360.go b/examples/joystick_xbox360.go index dff41efb3..ad7e111d5 100644 --- a/examples/joystick_xbox360.go +++ b/examples/joystick_xbox360.go @@ -18,40 +18,40 @@ func main() { stick := joystick.NewDriver(joystickAdaptor, joystick.Xbox360) work := func() { - stick.On(joystick.APress, func(data interface{}) { + _ = stick.On(joystick.APress, func(data interface{}) { fmt.Println("a_press") }) - stick.On(joystick.ARelease, func(data interface{}) { + _ = stick.On(joystick.ARelease, func(data interface{}) { fmt.Println("a_release") }) - stick.On(joystick.BPress, func(data interface{}) { + _ = stick.On(joystick.BPress, func(data interface{}) { fmt.Println("b_press") }) - stick.On(joystick.BRelease, func(data interface{}) { + _ = stick.On(joystick.BRelease, func(data interface{}) { fmt.Println("b_release") }) - stick.On(joystick.UpPress, func(data interface{}) { + _ = stick.On(joystick.UpPress, func(data interface{}) { fmt.Println("up", data) }) - stick.On(joystick.DownPress, func(data interface{}) { + _ = stick.On(joystick.DownPress, func(data interface{}) { fmt.Println("down", data) }) - stick.On(joystick.LeftPress, func(data interface{}) { + _ = stick.On(joystick.LeftPress, func(data interface{}) { fmt.Println("left", data) }) - stick.On(joystick.RightPress, func(data interface{}) { + _ = stick.On(joystick.RightPress, func(data interface{}) { fmt.Println("right", data) }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { fmt.Println("left_x", data) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { fmt.Println("left_y", data) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { fmt.Println("right_x", data) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { fmt.Println("right_y", data) }) } @@ -62,5 +62,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joystick_xbox360_rock_band_drums.go b/examples/joystick_xbox360_rock_band_drums.go index 05c6bf0a2..6e01a9da6 100644 --- a/examples/joystick_xbox360_rock_band_drums.go +++ b/examples/joystick_xbox360_rock_band_drums.go @@ -18,46 +18,46 @@ func main() { stick := joystick.NewDriver(joystickAdaptor, joystick.Xbox360RockBandDrums) work := func() { - stick.On(joystick.RedPress, func(data interface{}) { + _ = stick.On(joystick.RedPress, func(data interface{}) { fmt.Println("red_press") }) - stick.On(joystick.RedRelease, func(data interface{}) { + _ = stick.On(joystick.RedRelease, func(data interface{}) { fmt.Println("red_release") }) - stick.On(joystick.YellowPress, func(data interface{}) { + _ = stick.On(joystick.YellowPress, func(data interface{}) { fmt.Println("yellow_press") }) - stick.On(joystick.YellowRelease, func(data interface{}) { + _ = stick.On(joystick.YellowRelease, func(data interface{}) { fmt.Println("yellow_release") }) - stick.On(joystick.BluePress, func(data interface{}) { + _ = stick.On(joystick.BluePress, func(data interface{}) { fmt.Println("blue_press") }) - stick.On(joystick.BlueRelease, func(data interface{}) { + _ = stick.On(joystick.BlueRelease, func(data interface{}) { fmt.Println("blue_release") }) - stick.On(joystick.GreenPress, func(data interface{}) { + _ = stick.On(joystick.GreenPress, func(data interface{}) { fmt.Println("green_press") }) - stick.On(joystick.GreenRelease, func(data interface{}) { + _ = stick.On(joystick.GreenRelease, func(data interface{}) { fmt.Println("blue_release") }) - stick.On(joystick.PedalPress, func(data interface{}) { + _ = stick.On(joystick.PedalPress, func(data interface{}) { fmt.Println("pedal_press") }) - stick.On(joystick.PedalRelease, func(data interface{}) { + _ = stick.On(joystick.PedalRelease, func(data interface{}) { fmt.Println("pedal_release") }) - stick.On(joystick.UpPress, func(data interface{}) { + _ = stick.On(joystick.UpPress, func(data interface{}) { fmt.Println("up", data) }) - stick.On(joystick.DownPress, func(data interface{}) { + _ = stick.On(joystick.DownPress, func(data interface{}) { fmt.Println("down", data) }) - stick.On(joystick.LeftPress, func(data interface{}) { + _ = stick.On(joystick.LeftPress, func(data interface{}) { fmt.Println("left", data) }) - stick.On(joystick.RightPress, func(data interface{}) { + _ = stick.On(joystick.RightPress, func(data interface{}) { fmt.Println("right", data) }) } @@ -68,5 +68,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/joystick_xboxone.go b/examples/joystick_xboxone.go index 883a4d5f9..0732df69d 100644 --- a/examples/joystick_xboxone.go +++ b/examples/joystick_xboxone.go @@ -19,144 +19,144 @@ func main() { work := func() { // start button - joystick.On(joystick.Event("start_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("start_press"), func(data interface{}) { fmt.Println("start_press") }) - joystick.On(joystick.Event("start_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("start_release"), func(data interface{}) { fmt.Println("start_release") }) // back button - joystick.On(joystick.Event("back_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("back_press"), func(data interface{}) { fmt.Println("back_press") }) - joystick.On(joystick.Event("back_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("back_release"), func(data interface{}) { fmt.Println("back_release") }) // a button - joystick.On(joystick.Event("a_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("a_press"), func(data interface{}) { fmt.Println("a_press") }) - joystick.On(joystick.Event("a_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("a_release"), func(data interface{}) { fmt.Println("a_release") }) // b button - joystick.On(joystick.Event("b_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("b_press"), func(data interface{}) { fmt.Println("b_press") }) - joystick.On(joystick.Event("b_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("b_release"), func(data interface{}) { fmt.Println("b_release") }) // x button - joystick.On(joystick.Event("x_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("x_press"), func(data interface{}) { fmt.Println("x_press") }) - joystick.On(joystick.Event("x_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("x_release"), func(data interface{}) { fmt.Println("x_release") }) // y button - joystick.On(joystick.Event("y_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("y_press"), func(data interface{}) { fmt.Println("y_press") }) - joystick.On(joystick.Event("y_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("y_release"), func(data interface{}) { fmt.Println("y_release") }) // up dpad - joystick.On(joystick.Event("up_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("up_press"), func(data interface{}) { fmt.Println("up_press", data) }) - joystick.On(joystick.Event("up_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("up_release"), func(data interface{}) { fmt.Println("up_release", data) }) // down dpad - joystick.On(joystick.Event("down_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("down_press"), func(data interface{}) { fmt.Println("down_press") }) - joystick.On(joystick.Event("down_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("down_release"), func(data interface{}) { fmt.Println("down_release") }) // left dpad - joystick.On(joystick.Event("left_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("left_press"), func(data interface{}) { fmt.Println("left_press") }) - joystick.On(joystick.Event("left_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("left_release"), func(data interface{}) { fmt.Println("left_release") }) // right dpad - joystick.On(joystick.Event("right_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("right_press"), func(data interface{}) { fmt.Println("right_press") }) - joystick.On(joystick.Event("right_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("right_release"), func(data interface{}) { fmt.Println("right_release") }) // rt trigger - joystick.On(joystick.Event("rt"), func(data interface{}) { + _ = joystick.On(joystick.Event("rt"), func(data interface{}) { fmt.Println("rt", data) }) // lt trigger - joystick.On(joystick.Event("lt"), func(data interface{}) { + _ = joystick.On(joystick.Event("lt"), func(data interface{}) { fmt.Println("lt", data) }) // lb button - joystick.On(joystick.Event("lb_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("lb_press"), func(data interface{}) { fmt.Println("lb_press") }) - joystick.On(joystick.Event("lb_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("lb_release"), func(data interface{}) { fmt.Println("lb_release") }) // rb button - joystick.On(joystick.Event("rb_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("rb_press"), func(data interface{}) { fmt.Println("rb_press") }) - joystick.On(joystick.Event("rb_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("rb_release"), func(data interface{}) { fmt.Println("rb_release") }) // rx stick - joystick.On(joystick.Event("right_x"), func(data interface{}) { + _ = joystick.On(joystick.Event("right_x"), func(data interface{}) { fmt.Println("right_x", data) }) // ry stick - joystick.On(joystick.Event("right_y"), func(data interface{}) { + _ = joystick.On(joystick.Event("right_y"), func(data interface{}) { fmt.Println("right_y", data) }) // right_stick button - joystick.On(joystick.Event("right_stick_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("right_stick_press"), func(data interface{}) { fmt.Println("right_stick_press") }) - joystick.On(joystick.Event("right_stick_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("right_stick_release"), func(data interface{}) { fmt.Println("right_stick_release") }) // lx stick - joystick.On(joystick.Event("left_x"), func(data interface{}) { + _ = joystick.On(joystick.Event("left_x"), func(data interface{}) { fmt.Println("left_x", data) }) // ly stick - joystick.On(joystick.Event("left_y"), func(data interface{}) { + _ = joystick.On(joystick.Event("left_y"), func(data interface{}) { fmt.Println("left_y", data) }) // left_stick button - joystick.On(joystick.Event("left_stick_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("left_stick_press"), func(data interface{}) { fmt.Println("left_stick_press") }) - joystick.On(joystick.Event("left_stick_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("left_stick_release"), func(data interface{}) { fmt.Println("left_stick_release") }) } @@ -167,5 +167,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/keyboard.go b/examples/keyboard.go index b26b81661..30eb40135 100644 --- a/examples/keyboard.go +++ b/examples/keyboard.go @@ -17,7 +17,7 @@ func main() { keys := keyboard.NewDriver() work := func() { - keys.On(keyboard.Key, func(data interface{}) { + _ = keys.On(keyboard.Key, func(data interface{}) { key := data.(keyboard.KeyEvent) if key.Key == keyboard.A { @@ -34,5 +34,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/keyboard_mqtt.go b/examples/keyboard_mqtt.go index b56f8155d..5fc54c8c1 100644 --- a/examples/keyboard_mqtt.go +++ b/examples/keyboard_mqtt.go @@ -17,7 +17,7 @@ func main() { mqttAdaptor := mqtt.NewAdaptor("tcp://iot.eclipse.org:1883", "conductor") work := func() { - keys.On(keyboard.Key, func(data interface{}) { + _ = keys.On(keyboard.Key, func(data interface{}) { key := data.(keyboard.KeyEvent) switch key.Key { @@ -39,5 +39,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/leap_motion.go b/examples/leap_motion.go index 25ae1e9f6..eb6375ac6 100644 --- a/examples/leap_motion.go +++ b/examples/leap_motion.go @@ -18,7 +18,7 @@ func main() { l := leap.NewDriver(leapMotionAdaptor) work := func() { - l.On(leap.MessageEvent, func(data interface{}) { + _ = l.On(leap.MessageEvent, func(data interface{}) { fmt.Println(data.(leap.Frame)) }) } @@ -29,5 +29,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/leap_motion_gestures.go b/examples/leap_motion_gestures.go index 152826a33..f607e05e2 100644 --- a/examples/leap_motion_gestures.go +++ b/examples/leap_motion_gestures.go @@ -18,7 +18,7 @@ func main() { l := leap.NewDriver(leapMotionAdaptor) work := func() { - l.On(leap.GestureEvent, func(data interface{}) { + _ = l.On(leap.GestureEvent, func(data interface{}) { printGesture(data.(leap.Gesture)) }) } @@ -29,7 +29,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func printGesture(gesture leap.Gesture) { diff --git a/examples/leap_motion_hands.go b/examples/leap_motion_hands.go index ecf2fbd32..95be506b7 100644 --- a/examples/leap_motion_hands.go +++ b/examples/leap_motion_hands.go @@ -18,7 +18,7 @@ func main() { l := leap.NewDriver(leapMotionAdaptor) work := func() { - l.On(leap.HandEvent, func(data interface{}) { + _ = l.On(leap.HandEvent, func(data interface{}) { printHand(data.(leap.Hand)) }) } @@ -29,7 +29,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func printHand(hand leap.Hand) { diff --git a/examples/leap_servos.go b/examples/leap_servos.go index f3d715447..5d9e068eb 100644 --- a/examples/leap_servos.go +++ b/examples/leap_servos.go @@ -7,6 +7,8 @@ package main import ( + "fmt" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/gpio" "gobot.io/x/gobot/v2/platforms/firmata" @@ -27,21 +29,41 @@ func main() { work := func() { fist := false - l.On(leap.MessageEvent, func(data interface{}) { + _ = l.On(leap.MessageEvent, func(data interface{}) { handIsOpen := len(data.(leap.Frame).Pointables) > 0 if handIsOpen && fist { - servo1.Move(0) - servo2.Move(0) - servo3.Move(0) - servo4.Move(0) - servo5.Move(0) + if err := servo1.Move(0); err != nil { + fmt.Println(err) + } + if err := servo2.Move(0); err != nil { + fmt.Println(err) + } + if err := servo3.Move(0); err != nil { + fmt.Println(err) + } + if err := servo4.Move(0); err != nil { + fmt.Println(err) + } + if err := servo5.Move(0); err != nil { + fmt.Println(err) + } fist = false } else if !handIsOpen && !fist { - servo1.Move(120) - servo2.Move(120) - servo3.Move(120) - servo4.Move(120) - servo5.Move(120) + if err := servo1.Move(120); err != nil { + fmt.Println(err) + } + if err := servo2.Move(120); err != nil { + fmt.Println(err) + } + if err := servo3.Move(120); err != nil { + fmt.Println(err) + } + if err := servo4.Move(120); err != nil { + fmt.Println(err) + } + if err := servo5.Move(120); err != nil { + fmt.Println(err) + } fist = true } }) @@ -53,5 +75,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/leap_sphero.go b/examples/leap_sphero.go index 91e6c179d..b4aae6170 100644 --- a/examples/leap_sphero.go +++ b/examples/leap_sphero.go @@ -23,7 +23,7 @@ func main() { spheroDriver := serial.NewSpheroDriver(spheroAdaptor) work := func() { - leapDriver.On(leap.MessageEvent, func(data interface{}) { + _ = leapDriver.On(leap.MessageEvent, func(data interface{}) { hands := data.(leap.Frame).Hands if len(hands) > 0 { @@ -41,7 +41,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func scale(position float64) uint8 { diff --git a/examples/mavlink.go b/examples/mavlink.go index 6f21624f5..b7d355562 100644 --- a/examples/mavlink.go +++ b/examples/mavlink.go @@ -19,7 +19,7 @@ func main() { iris := mavlink.NewDriver(adaptor) work := func() { - iris.Once(mavlink.PacketEvent, func(data interface{}) { + _ = iris.Once(mavlink.PacketEvent, func(data interface{}) { packet := data.(*common.MAVLinkPacket) dataStream := common.NewRequestDataStream(100, @@ -28,13 +28,13 @@ func main() { 4, 1, ) - iris.SendPacket(common.CraftMAVLinkPacket(packet.SystemID, - packet.ComponentID, - dataStream, - )) + if err := iris.SendPacket( + common.CraftMAVLinkPacket(packet.SystemID, packet.ComponentID, dataStream)); err != nil { + fmt.Println(err) + } }) - iris.On(mavlink.MessageEvent, func(data interface{}) { + _ = iris.On(mavlink.MessageEvent, func(data interface{}) { if data.(common.MAVLinkMessage).Id() == 30 { message := data.(*common.Attitude) fmt.Println("Attitude") @@ -56,5 +56,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/megapi_motor.go b/examples/megapi_motor.go index ca61c3db3..fba251446 100644 --- a/examples/megapi_motor.go +++ b/examples/megapi_motor.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -24,7 +25,9 @@ func main() { fadeAmount := int16(30) gobot.Every(100*time.Millisecond, func() { - motor.Speed(speed) + if err := motor.Speed(speed); err != nil { + fmt.Println(err) + } speed = speed + fadeAmount if speed == 0 || speed == 300 { fadeAmount = -fadeAmount @@ -38,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/metal_button.go b/examples/metal_button.go index 3516e6416..bfc8d68de 100644 --- a/examples/metal_button.go +++ b/examples/metal_button.go @@ -15,22 +15,29 @@ import ( func main() { e := edison.NewAdaptor() - e.Connect() + if err := e.Connect(); err != nil { + fmt.Println(err) + } led := gpio.NewLedDriver(e, "13") - led.Start() - led.Off() + if err := led.Start(); err != nil { + fmt.Println(err) + } + if err := led.Off(); err != nil { + fmt.Println(err) + } button := gpio.NewButtonDriver(e, "5") - button.Start() + if err := button.Start(); err != nil { + fmt.Println(err) + } buttonEvents := button.Subscribe() - for { - select { - case event := <-buttonEvents: - fmt.Println("Event:", event.Name, event.Data) - if event.Name == gpio.ButtonPush { - led.Toggle() + for event := range buttonEvents { + fmt.Println("Event:", event.Name, event.Data) + if event.Name == gpio.ButtonPush { + if err := led.Toggle(); err != nil { + fmt.Println(err) } } } diff --git a/examples/mqtt_driver_ping.go b/examples/mqtt_driver_ping.go index 1236d80c4..27cf9d380 100644 --- a/examples/mqtt_driver_ping.go +++ b/examples/mqtt_driver_ping.go @@ -30,11 +30,11 @@ func main() { helloDriver := mqtt.NewDriver(mqttAdaptor, "hello") work := func() { - helloDriver.On(mqtt.Data, func(data interface{}) { + _ = helloDriver.On(mqtt.Data, func(data interface{}) { fmt.Println("hello") }) - holaDriver.On(mqtt.Data, func(data interface{}) { + _ = holaDriver.On(mqtt.Data, func(data interface{}) { fmt.Println("hola") }) @@ -54,5 +54,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/mqtt_firmata_blink.go b/examples/mqtt_firmata_blink.go index 23fb97016..49d1af067 100644 --- a/examples/mqtt_firmata_blink.go +++ b/examples/mqtt_firmata_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -21,11 +22,15 @@ func main() { led := gpio.NewLedDriver(firmataAdaptor, "13") work := func() { - mqttAdaptor.On("lights/on", func(msg mqtt.Message) { - led.On() + _ = mqttAdaptor.On("lights/on", func(msg mqtt.Message) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - mqttAdaptor.On("lights/off", func(msg mqtt.Message) { - led.Off() + _ = mqttAdaptor.On("lights/off", func(msg mqtt.Message) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) data := []byte("") gobot.Every(1*time.Second, func() { @@ -42,5 +47,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/mqtt_ping.go b/examples/mqtt_ping.go index ba3b1ccd9..bc5fd1b2b 100644 --- a/examples/mqtt_ping.go +++ b/examples/mqtt_ping.go @@ -18,10 +18,10 @@ func main() { mqttAdaptor := mqtt.NewAdaptor("tcp://test.mosquitto.org:1883", "pinger") work := func() { - mqttAdaptor.On("hello", func(msg mqtt.Message) { + _ = mqttAdaptor.On("hello", func(msg mqtt.Message) { fmt.Println("hello") }) - mqttAdaptor.On("hola", func(msg mqtt.Message) { + _ = mqttAdaptor.On("hola", func(msg mqtt.Message) { fmt.Println("hola") }) data := []byte("o") @@ -38,5 +38,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/nanopi_direct_pin.go b/examples/nanopi_direct_pin.go index 616b2ef79..afbb130b6 100644 --- a/examples/nanopi_direct_pin.go +++ b/examples/nanopi_direct_pin.go @@ -20,8 +20,10 @@ import ( // PWR NanoPi: 1, 17 (+3.3V, VCC); 2, 4 (+5V, VDD); 6, 9, 14, 20 (GND) // GPIO NanoPi: header pin 22 is input, pin 23 is normal output, pin 24 is inverted output // Button: the input pin is wired with a button to GND, the internal pull up resistor is used -// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC -// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state changes +// LED's: the output pins are wired to the cathode of the LED, the anode is wired with a resistor (70-130Ohm for 20mA) +// to VCC +// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state +// changes func main() { const ( inPinNum = "22" // 7, 8, 10, 11, 12, 13, 15, 16, 18, 22 @@ -77,5 +79,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/nanopi_direct_pin_event.go b/examples/nanopi_direct_pin_event.go index f29f4dd8d..8a898a4b2 100644 --- a/examples/nanopi_direct_pin_event.go +++ b/examples/nanopi_direct_pin_event.go @@ -31,8 +31,10 @@ var ( // PWR NanoPi: 1, 17 (+3.3V, VCC); 2, 4 (+5V, VDD); 6, 9, 14, 20 (GND) // GPIO NanoPi: header pin 22 is input, pin 23 is normal output, pin 24 is inverted output // Button: the input pin is wired with a button to GND, the internal pull up resistor is used -// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC -// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state changes +// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) +// to VCC +// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state +// changes func main() { board := nanopi.NewNeoAdaptor() @@ -73,7 +75,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func buttonEventHandler(offset int, t time.Duration, et string, sn uint32, lsn uint32) { diff --git a/examples/nanopi_led_brightness.go b/examples/nanopi_led_brightness.go index 72af91a01..d9ad9ac77 100644 --- a/examples/nanopi_led_brightness.go +++ b/examples/nanopi_led_brightness.go @@ -18,7 +18,7 @@ import ( // Wiring // PWR NanoPi: 1, 17 (+3.3V, VCC); 2, 4 (+5V, VDD); 6, 9, 14, 20 (GND) // GPIO NanoPi: the fourth header pin at inner USB side, count from USB side, is the PWM output -// LED: the PWM output is NOT able to drive a 20mA LED with full brightness, so a custom driver or low current LED is needed +// LED: the PWM output is NOT able to drive a 20mA LED with full brightness (custom driver or low current LED is needed) // Expected behavior: the LED fades in and out func main() { r := nanopi.NewNeoAdaptor() @@ -45,5 +45,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/nanopi_pca9533.go b/examples/nanopi_pca9533.go index 73a5d614a..844f75cea 100644 --- a/examples/nanopi_pca9533.go +++ b/examples/nanopi_pca9533.go @@ -69,9 +69,8 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/nats.go b/examples/nats.go index fdefc5085..2213fabac 100644 --- a/examples/nats.go +++ b/examples/nats.go @@ -38,5 +38,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/nats_driver_ping.go b/examples/nats_driver_ping.go index b813b9fb7..d372ee678 100644 --- a/examples/nats_driver_ping.go +++ b/examples/nats_driver_ping.go @@ -29,11 +29,11 @@ func main() { helloDriver := nats.NewDriver(natsAdaptor, "hello") work := func() { - helloDriver.On(nats.Data, func(msg nats.Message) { + _ = helloDriver.On(nats.Data, func(msg nats.Message) { fmt.Println("hello") }) - holaDriver.On(nats.Data, func(msg nats.Message) { + _ = holaDriver.On(nats.Data, func(msg nats.Message) { fmt.Println("hola") }) @@ -53,5 +53,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/neurosky.go b/examples/neurosky.go index 37cb12a94..4c492230f 100644 --- a/examples/neurosky.go +++ b/examples/neurosky.go @@ -18,25 +18,25 @@ func main() { neuro := neurosky.NewDriver(adaptor) work := func() { - neuro.On(neuro.Event("extended"), func(data interface{}) { + _ = neuro.On(neuro.Event("extended"), func(data interface{}) { fmt.Println("Extended", data) }) - neuro.On(neuro.Event("signal"), func(data interface{}) { + _ = neuro.On(neuro.Event("signal"), func(data interface{}) { fmt.Println("Signal", data) }) - neuro.On(neuro.Event("attention"), func(data interface{}) { + _ = neuro.On(neuro.Event("attention"), func(data interface{}) { fmt.Println("Attention", data) }) - neuro.On(neuro.Event("meditation"), func(data interface{}) { + _ = neuro.On(neuro.Event("meditation"), func(data interface{}) { fmt.Println("Meditation", data) }) - neuro.On(neuro.Event("blink"), func(data interface{}) { + _ = neuro.On(neuro.Event("blink"), func(data interface{}) { fmt.Println("Blink", data) }) - neuro.On(neuro.Event("wave"), func(data interface{}) { + _ = neuro.On(neuro.Event("wave"), func(data interface{}) { fmt.Println("Wave", data) }) - neuro.On(neuro.Event("eeg"), func(data interface{}) { + _ = neuro.On(neuro.Event("eeg"), func(data interface{}) { eeg := data.(neurosky.EEGData) fmt.Println("Delta", eeg.Delta) fmt.Println("Theta", eeg.Theta) @@ -56,5 +56,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/opencv_face_detect.go b/examples/opencv_face_detect.go index 54774e8e4..88aec5e02 100644 --- a/examples/opencv_face_detect.go +++ b/examples/opencv_face_detect.go @@ -53,5 +53,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/opencv_window.go b/examples/opencv_window.go index ece48d187..51286bf4e 100644 --- a/examples/opencv_window.go +++ b/examples/opencv_window.go @@ -29,5 +29,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/particle_api.go b/examples/particle_api.go index d39f390a7..ee267d073 100644 --- a/examples/particle_api.go +++ b/examples/particle_api.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -32,7 +33,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -44,5 +47,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/particle_blink.go b/examples/particle_blink.go index 53212927b..0f4eb4382 100644 --- a/examples/particle_blink.go +++ b/examples/particle_blink.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -28,7 +29,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -38,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/particle_button.go b/examples/particle_button.go index abe5d7f94..bb9580e99 100644 --- a/examples/particle_button.go +++ b/examples/particle_button.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "gobot.io/x/gobot/v2" @@ -27,12 +28,16 @@ func main() { button := gpio.NewButtonDriver(core, "D5") work := func() { - button.On(button.Event("push"), func(data interface{}) { - led.On() + _ = button.On(button.Event("push"), func(data interface{}) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(button.Event("release"), func(data interface{}) { - led.Off() + _ = button.On(button.Event("release"), func(data interface{}) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -42,5 +47,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/particle_events.go b/examples/particle_events.go index 77d39b43f..3106ab22d 100644 --- a/examples/particle_events.go +++ b/examples/particle_events.go @@ -38,5 +38,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/particle_function.go b/examples/particle_function.go index 5135519c3..3c45ec3fe 100644 --- a/examples/particle_function.go +++ b/examples/particle_function.go @@ -37,5 +37,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/particle_led_brightness.go b/examples/particle_led_brightness.go index 40e7672c8..89907e120 100644 --- a/examples/particle_led_brightness.go +++ b/examples/particle_led_brightness.go @@ -14,6 +14,7 @@ package main import ( + "fmt" "os" "time" @@ -31,7 +32,9 @@ func main() { fadeAmount := uint8(25) gobot.Every(500*time.Millisecond, func() { - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } brightness = brightness + fadeAmount if brightness == 0 || brightness == 255 { fadeAmount = -fadeAmount @@ -45,5 +48,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/particle_variable.go b/examples/particle_variable.go index 1f2023902..54fddba49 100644 --- a/examples/particle_variable.go +++ b/examples/particle_variable.go @@ -40,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/pebble.go b/examples/pebble.go index d585e5654..3bbe1bedd 100644 --- a/examples/pebble.go +++ b/examples/pebble.go @@ -25,11 +25,11 @@ func main() { work := func() { pebbleDriver.SendNotification("Hello Pebble!") - pebbleDriver.On(pebbleDriver.Event("button"), func(data interface{}) { + _ = pebbleDriver.On(pebbleDriver.Event("button"), func(data interface{}) { fmt.Println("Button pushed: " + data.(string)) }) - pebbleDriver.On(pebbleDriver.Event("tap"), func(data interface{}) { + _ = pebbleDriver.On(pebbleDriver.Event("tap"), func(data interface{}) { fmt.Println("Tap event detected") }) } @@ -42,5 +42,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/pebble_accelerometer.go b/examples/pebble_accelerometer.go index 5444312b3..632989ed3 100644 --- a/examples/pebble_accelerometer.go +++ b/examples/pebble_accelerometer.go @@ -24,7 +24,7 @@ func main() { pebbleDriver := pebble.NewDriver(pebbleAdaptor) work := func() { - pebbleDriver.On(pebbleDriver.Event("accel"), func(data interface{}) { + _ = pebbleDriver.On(pebbleDriver.Event("accel"), func(data interface{}) { fmt.Println(data.(string)) }) } @@ -37,5 +37,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_adafruit2327_servo.go b/examples/raspi_adafruit2327_servo.go index 9a93aa985..d87d78103 100644 --- a/examples/raspi_adafruit2327_servo.go +++ b/examples/raspi_adafruit2327_servo.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "log" "time" @@ -38,7 +39,9 @@ func main() { work := func() { gobot.Every(5*time.Second, func() { - adafruitServoMotorRunner(adaFruit) + if err := adafruitServoMotorRunner(adaFruit); err != nil { + fmt.Println(err) + } }) } @@ -48,7 +51,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func adafruitServoMotorRunner(a *i2c.Adafruit2327Driver) error { @@ -60,26 +65,22 @@ func adafruitServoMotorRunner(a *i2c.Adafruit2327Driver) error { // Do not need to set this every run loop freq := 60.0 if err := a.SetServoMotorFreq(freq); err != nil { - log.Printf("%s", err.Error()) return err } // start in the middle of the 180-deg range pulse := degree2pulse(deg) if err := a.SetServoMotorPulse(channel, 0, pulse); err != nil { - log.Printf(err.Error()) return err } // INCR pulse = degree2pulse(deg + degIncrease) if err := a.SetServoMotorPulse(channel, 0, pulse); err != nil { - log.Printf(err.Error()) return err } time.Sleep(2000 * time.Millisecond) // DECR pulse = degree2pulse(deg - degIncrease) if err := a.SetServoMotorPulse(channel, 0, pulse); err != nil { - log.Printf(err.Error()) return err } return nil diff --git a/examples/raspi_adafruit2348_dcmotor.go b/examples/raspi_adafruit2348_dcmotor.go index b15967109..0df538cc5 100644 --- a/examples/raspi_adafruit2348_dcmotor.go +++ b/examples/raspi_adafruit2348_dcmotor.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "log" "time" @@ -24,7 +25,9 @@ func main() { work := func() { gobot.Every(5*time.Second, func() { dcMotor := 2 // 0-based - adafruitDCMotorRunner(adaFruit, dcMotor) + if err := adafruitDCMotorRunner(adaFruit, dcMotor); err != nil { + fmt.Println(err) + } }) } @@ -34,7 +37,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func adafruitDCMotorRunner(a *i2c.Adafruit2348Driver, dcMotor int) error { diff --git a/examples/raspi_adafruit2348_stepper.go b/examples/raspi_adafruit2348_stepper.go index c1eb80f38..0cac6546a 100644 --- a/examples/raspi_adafruit2348_stepper.go +++ b/examples/raspi_adafruit2348_stepper.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "log" "time" @@ -24,7 +25,9 @@ func main() { work := func() { gobot.Every(5*time.Second, func() { motor := 0 // 0-based - adafruitStepperMotorRunner(adaFruit, motor) + if err := adafruitStepperMotorRunner(adaFruit, motor); err != nil { + fmt.Println(err) + } }) } @@ -34,7 +37,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func adafruitStepperMotorRunner(a *i2c.Adafruit2348Driver, motor int) error { @@ -44,15 +49,17 @@ func adafruitStepperMotorRunner(a *i2c.Adafruit2348Driver, motor int) error { style := i2c.Adafruit2348Double steps := 20 - a.SetStepperMotorSpeed(motor, speed) + if err := a.SetStepperMotorSpeed(motor, speed); err != nil { + return err + } if err := a.Step(motor, steps, i2c.Adafruit2348Forward, style); err != nil { - log.Printf(err.Error()) return err } + if err := a.Step(motor, steps, i2c.Adafruit2348Backward, style); err != nil { - log.Printf(err.Error()) return err } + return nil } diff --git a/examples/raspi_ads1015.go b/examples/raspi_ads1015.go index 8ac0b29a2..3255d3d7d 100644 --- a/examples/raspi_ads1015.go +++ b/examples/raspi_ads1015.go @@ -33,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_blink.go b/examples/raspi_blink.go index fb3623955..f519f006e 100644 --- a/examples/raspi_blink.go +++ b/examples/raspi_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_blinkm.go b/examples/raspi_blinkm.go index bf7a3d066..80afb59b2 100644 --- a/examples/raspi_blinkm.go +++ b/examples/raspi_blinkm.go @@ -24,8 +24,13 @@ func main() { r := byte(gobot.Rand(255)) g := byte(gobot.Rand(255)) b := byte(gobot.Rand(255)) - blinkm.Rgb(r, g, b) - color, _ := blinkm.Color() + if err := blinkm.Rgb(r, g, b); err != nil { + fmt.Println(err) + } + color, err := blinkm.Color() + if err != nil { + fmt.Println(err) + } fmt.Println("color", color) }) } @@ -36,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_button.go b/examples/raspi_button.go index b1e620df4..f491b401b 100644 --- a/examples/raspi_button.go +++ b/examples/raspi_button.go @@ -20,14 +20,18 @@ func main() { led := gpio.NewLedDriver(r, "7") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { fmt.Println("button pressed") - led.On() + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("button released") - led.Off() + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -37,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_ccs811.go b/examples/raspi_ccs811.go index 275fe915b..312223519 100644 --- a/examples/raspi_ccs811.go +++ b/examples/raspi_ccs811.go @@ -18,21 +18,21 @@ import ( func CCS811BootData(a *i2c.CCS811Driver) { v, err := a.GetHardwareVersion() if err != nil { - fmt.Printf(err.Error()) + fmt.Println(err.Error()) } fmt.Printf("Hardare Version %#x\n", v) d, err := a.GetFirmwareBootVersion() if err != nil { - fmt.Printf(err.Error()) + fmt.Println(err.Error()) } fmt.Printf("Boot Version %#x\n", d) d, err = a.GetFirmwareAppVersion() if err != nil { - fmt.Printf(err.Error()) + fmt.Println(err.Error()) } fmt.Printf("App Version %#x\n\n", d) @@ -74,5 +74,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_direct_pin.go b/examples/raspi_direct_pin.go index 24f31e47d..e41b826c3 100644 --- a/examples/raspi_direct_pin.go +++ b/examples/raspi_direct_pin.go @@ -20,8 +20,10 @@ import ( // PWR Raspi: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) // GPIO Raspi: header pin 21 (GPIO9) is input, pin 24 (GPIO8) is normal output, pin 26 (GPIO7) is inverted output // Button: the input pin is wired with a button to GND, the internal pull up resistor is used -// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC -// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state changes +// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) +// to VCC +// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state +// changes func main() { const ( inPinNum = "21" @@ -76,5 +78,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_direct_pin_event.go b/examples/raspi_direct_pin_event.go index 0f50f3122..87f022c45 100644 --- a/examples/raspi_direct_pin_event.go +++ b/examples/raspi_direct_pin_event.go @@ -31,8 +31,10 @@ var ( // PWR Raspi: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) // GPIO Raspi: header pin 21 (GPIO9) is input, pin 24 (GPIO8) is normal output, pin 26 (GPIO7) is inverted output // Button: the input pin is wired with a button to GND, the internal pull up resistor is used -// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC -// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state changes +// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) +// to VCC +// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state +// changes func main() { board := raspi.NewAdaptor() @@ -73,7 +75,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func buttonEventHandler(offset int, t time.Duration, et string, sn uint32, lsn uint32) { diff --git a/examples/raspi_generic.go b/examples/raspi_generic.go index 319986cdc..da2b90ab1 100644 --- a/examples/raspi_generic.go +++ b/examples/raspi_generic.go @@ -87,8 +87,7 @@ func main() { work, ) - err = robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/raspi_grove_pi_blink.go b/examples/raspi_grove_pi_blink.go index 96d0678cf..384bed35f 100644 --- a/examples/raspi_grove_pi_blink.go +++ b/examples/raspi_grove_pi_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -22,7 +23,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -32,5 +35,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_grove_pi_button.go b/examples/raspi_grove_pi_button.go index 88cfd6059..07519da52 100644 --- a/examples/raspi_grove_pi_button.go +++ b/examples/raspi_grove_pi_button.go @@ -23,14 +23,18 @@ func main() { led := gpio.NewLedDriver(gp, "D2") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { fmt.Println("button pressed") - led.On() + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { fmt.Println("button released") - led.Off() + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -40,5 +44,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_grove_pi_dht.go b/examples/raspi_grove_pi_dht.go index 6aee0f996..015c7d025 100644 --- a/examples/raspi_grove_pi_dht.go +++ b/examples/raspi_grove_pi_dht.go @@ -42,5 +42,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_grove_pi_rotary.go b/examples/raspi_grove_pi_rotary.go index afecd5eff..9f97f1822 100644 --- a/examples/raspi_grove_pi_rotary.go +++ b/examples/raspi_grove_pi_rotary.go @@ -22,7 +22,7 @@ func main() { sensor := aio.NewGroveRotaryDriver(gp, "A1", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } @@ -33,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_grove_pi_ultrasonic.go b/examples/raspi_grove_pi_ultrasonic.go index 4d213b901..2391cd0f4 100644 --- a/examples/raspi_grove_pi_ultrasonic.go +++ b/examples/raspi_grove_pi_ultrasonic.go @@ -40,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_grove_rotary_sensor.go b/examples/raspi_grove_rotary_sensor.go index f9960ce7f..b6c5ee3d7 100644 --- a/examples/raspi_grove_rotary_sensor.go +++ b/examples/raspi_grove_rotary_sensor.go @@ -22,7 +22,7 @@ func main() { sensor := aio.NewGroveRotaryDriver(ads1015, "0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } @@ -33,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_hcsr04.go b/examples/raspi_hcsr04.go index a16bf01b0..7ff54ea3f 100644 --- a/examples/raspi_hcsr04.go +++ b/examples/raspi_hcsr04.go @@ -88,6 +88,6 @@ func main() { ) if err := robot.Start(); err != nil { - log.Fatal(err) + panic(err) } } diff --git a/examples/raspi_hmc5883l.go b/examples/raspi_hmc5883l.go index 1a6e46dc1..a02cb004e 100644 --- a/examples/raspi_hmc5883l.go +++ b/examples/raspi_hmc5883l.go @@ -43,5 +43,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_ina3221.go b/examples/raspi_ina3221.go index 13f4786bd..c4cca7f43 100644 --- a/examples/raspi_ina3221.go +++ b/examples/raspi_ina3221.go @@ -55,5 +55,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_led_brightness.go b/examples/raspi_led_brightness.go index 1ae9a6dc9..2348cd593 100644 --- a/examples/raspi_led_brightness.go +++ b/examples/raspi_led_brightness.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -23,7 +24,9 @@ func main() { fadeAmount := uint8(15) gobot.Every(100*time.Millisecond, func() { - led.Brightness(brightness) + if err := led.Brightness(brightness); err != nil { + fmt.Println(err) + } brightness = brightness + fadeAmount if brightness == 0 || brightness == 255 { fadeAmount = -fadeAmount @@ -37,5 +40,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_mcp3008.go b/examples/raspi_mcp3008.go index 1ecebd751..df393f928 100644 --- a/examples/raspi_mcp3008.go +++ b/examples/raspi_mcp3008.go @@ -32,5 +32,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_pca9533.go b/examples/raspi_pca9533.go index f71959f2f..da9454e6c 100644 --- a/examples/raspi_pca9533.go +++ b/examples/raspi_pca9533.go @@ -69,9 +69,8 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/raspi_sht2x.go b/examples/raspi_sht2x.go index 92cca3234..b37144372 100644 --- a/examples/raspi_sht2x.go +++ b/examples/raspi_sht2x.go @@ -35,5 +35,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_sht3x.go b/examples/raspi_sht3x.go index 2f3411ba0..8efd07801 100644 --- a/examples/raspi_sht3x.go +++ b/examples/raspi_sht3x.go @@ -21,7 +21,9 @@ func main() { work := func() { sht3x.Units = "F" - sht3x.Start() + if err := sht3x.Start(); err != nil { + fmt.Println(err) + } sn, err := sht3x.SerialNumber() fmt.Printf("Serial Number: 0x%08x, err: %v\n", sn, err) @@ -37,5 +39,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_ssd1306.go b/examples/raspi_ssd1306.go index c43f58175..276a74971 100644 --- a/examples/raspi_ssd1306.go +++ b/examples/raspi_ssd1306.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -33,7 +34,9 @@ func main() { } } stage = !stage - oled.Display() + if err := oled.Display(); err != nil { + fmt.Println(err) + } }) } @@ -43,5 +46,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_ssd1306spi.go b/examples/raspi_ssd1306spi.go index 4df424e77..2bf5bc5a6 100644 --- a/examples/raspi_ssd1306spi.go +++ b/examples/raspi_ssd1306spi.go @@ -7,25 +7,33 @@ package main import ( + "fmt" + "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/spi" "gobot.io/x/gobot/v2/platforms/raspi" ) // this example only works for a 128x64 display +// +//nolint:lll // ok for example var gobotLogo = []byte{0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xe0, 0xb0, 0x90, 0xc8, 0x6e, 0x9a, 0xb6, 0xd, 0x3a, 0x15, 0xf7, 0xd, 0x59, 0x98, 0x94, 0xf4, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x8f, 0x8f, 0xff, 0x97, 0xcf, 0x4f, 0xc3, 0x51, 0xc0, 0x41, 0xd1, 0x40, 0xa4, 0xc4, 0x50, 0xc0, 0x40, 0xd1, 0x87, 0xdf, 0x97, 0x77, 0x3f, 0x8f, 0x4f, 0xff, 0x9f, 0xbf, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x37, 0x37, 0xef, 0xda, 0xbf, 0xef, 0x8e, 0x8d, 0xe7, 0xad, 0xfb, 0xaf, 0x1b, 0xdb, 0x29, 0x1f, 0x56, 0xcf, 0x1b, 0xcf, 0x9b, 0x55, 0x8f, 0xdd, 0x1a, 0xd7, 0x1e, 0xb5, 0x9b, 0xad, 0x17, 0xbd, 0xab, 0x15, 0xbf, 0x2d, 0x9a, 0xb7, 0x1d, 0xb7, 0x2d, 0x9a, 0xb7, 0x9e, 0x95, 0x9f, 0x55, 0x9b, 0x5d, 0x97, 0x5a, 0x8f, 0xda, 0xf, 0xda, 0x4f, 0x9a, 0x2e, 0x5a, 0xae, 0x14, 0xff, 0x67, 0xcf, 0x8b, 0x56, 0xdd, 0x74, 0xdd, 0x77, 0x57, 0x5f, 0x5f, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfe, 0xff, 0xf2, 0xff, 0xfc, 0xef, 0xba, 0xef, 0xba, 0xed, 0xbf, 0xea, 0x5f, 0xfa, 0x56, 0xfe, 0xb4, 0xde, 0x74, 0xbe, 0xec, 0x5a, 0xfc, 0x55, 0xfc, 0xd5, 0xbc, 0x74, 0xad, 0x7c, 0xa9, 0xfc, 0xa5, 0xec, 0x9d, 0xc8, 0xcd, 0xac, 0x79, 0xd5, 0x7c, 0xb4, 0xdc, 0xb4, 0xdd, 0x74, 0xdd, 0xf4, 0xac, 0xfd, 0xaa, 0xfc, 0x56, 0xfc, 0xae, 0xfa, 0xad, 0xfe, 0xaa, 0x7f, 0xed, 0x5b, 0xfe, 0x55, 0xff, 0xff, 0xab, 0xaf, 0xf9, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f, 0x6e, 0xfb, 0x6e, 0xdb, 0x7e, 0xd5, 0x7f, 0xd5, 0x7f, 0xd5, 0xff, 0xaa, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0xd6, 0xfd, 0xd7, 0x7d, 0xeb, 0xff, 0xaa, 0xff, 0xdb, 0x7f, 0xf5, 0xdf, 0x7b, 0xef, 0xfb, 0xed, 0xbf, 0xea, 0x7f, 0xea, 0xbf, 0xeb, 0xbe, 0xeb, 0x5e, 0xfb, 0x56, 0xff, 0x55, 0xff, 0xaa, 0xff, 0x56, 0xfd, 0x57, 0xfd, 0x57, 0xfd, 0x57, 0xfd, 0xb7, 0xb7, 0xda, 0x1a, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xf, 0xf, 0xf, 0x1, 0x20, 0x8, 0x40, 0x10, 0x84, 0x0, 0xa8, 0x0, 0x2, 0xa8, 0x0, 0x2, 0xa8, 0x0, 0x42, 0xfd, 0x9f, 0x75, 0xdf, 0xb5, 0xdf, 0xb5, 0xff, 0xaa, 0x7f, 0x2a, 0x5f, 0x75, 0x3f, 0x6d, 0x7f, 0x5b, 0x7f, 0xf6, 0x3f, 0xed, 0x7f, 0xfb, 0xaf, 0x7e, 0xfb, 0x6f, 0xbd, 0xf7, 0x5f, 0xfd, 0x77, 0xde, 0x7f, 0xf5, 0x5f, 0x7f, 0xf5, 0x5f, 0xff, 0x35, 0xff, 0x57, 0x7d, 0x6f, 0x3d, 0x6b, 0x3f, 0x2a, 0xff, 0x55, 0xff, 0x95, 0x7f, 0x55, 0xff, 0x95, 0x6f, 0xa8, 0x40, 0x0, 0x2a, 0x0, 0x44, 0x10, 0x4, 0x40, 0x10, 0x84, 0x0, 0x28, 0x0, 0x20, 0x1, 0xf, 0x2f, 0x2f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0x7, 0x7, 0x7, 0xa1, 0x0, 0x48, 0xa0, 0xd4, 0x30, 0xe8, 0x1a, 0x4, 0x18, 0x44, 0xc, 0x80, 0xe, 0x20, 0x84, 0x8c, 0x0, 0xcd, 0x8, 0x88, 0x92, 0x8, 0xa0, 0x2, 0x8, 0x42, 0xb0, 0x60, 0x9a, 0xf0, 0xc, 0x10, 0x4d, 0x8, 0x85, 0x24, 0x5, 0x48, 0x4, 0x84, 0x2c, 0x0, 0x8c, 0x19, 0x68, 0xb2, 0x48, 0xf1, 0x0, 0x44, 0x10, 0x0, 0x6c, 0xd8, 0x24, 0xfc, 0x80, 0x4c, 0x84, 0x48, 0x84, 0x4c, 0x80, 0x4c, 0x84, 0x48, 0xd4, 0x38, 0xe4, 0x18, 0x60, 0x4, 0x90, 0x2, 0x20, 0xc4, 0x31, 0xe8, 0x92, 0x78, 0x4, 0x19, 0x44, 0x9, 0x85, 0x25, 0x8, 0x85, 0x24, 0x4, 0x48, 0x5, 0x18, 0xb4, 0x49, 0xb0, 0xd4, 0x21, 0xcc, 0x0, 0x4c, 0x1, 0x8c, 0x24, 0x4, 0x88, 0x76, 0xa8, 0xdc, 0x30, 0x4e, 0x0, 0xc, 0x44, 0xc, 0x0, 0xc, 0x8, 0x62, 0x0, 0xa, 0x0, 0x10, 0x10, 0x80, 0xc0, 0xe0, 0xe2, 0x8, 0x0, 0x13, 0x6, 0x9, 0x27, 0xc, 0xc9, 0x18, 0x2, 0x58, 0x0, 0x9a, 0x10, 0x44, 0x18, 0x81, 0x18, 0x47, 0x18, 0x7, 0x4d, 0x2, 0x10, 0x4, 0x1, 0x13, 0x4, 0xb, 0x26, 0xd, 0xc8, 0x18, 0x82, 0x18, 0x10, 0x54, 0x1, 0x18, 0x40, 0x1a, 0x88, 0x98, 0xc6, 0x9, 0x27, 0xa, 0x85, 0x11, 0x40, 0xa, 0x20, 0x8b, 0x16, 0x49, 0x8e, 0x19, 0x80, 0x58, 0x82, 0x18, 0x81, 0x58, 0x8, 0x90, 0x89, 0xd8, 0x5, 0xe, 0x29, 0x7, 0x12, 0x4, 0x0, 0x68, 0x1, 0x87, 0xa0, 0xf, 0xa, 0xd4, 0x9, 0x18, 0x40, 0x1a, 0x0, 0x58, 0x2, 0x18, 0x40, 0x99, 0x4, 0x58, 0x6, 0x2b, 0x4, 0x13, 0x5, 0x80, 0x8, 0x2, 0x0, 0x28, 0x2, 0x40, 0x8, 0x97, 0xa, 0x9d, 0x53, 0x4, 0x0, 0x51, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80} func main() { raspiAdaptor := raspi.NewAdaptor() oled := spi.NewSSD1306Driver(raspiAdaptor) work := func() { - oled.Clear() - oled.SetBufferAndDisplay(gobotLogo) + _ = oled.Clear() + if err := oled.SetBufferAndDisplay(gobotLogo); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("ssd1360", []gobot.Connection{raspiAdaptor}, []gobot.Device{oled}, work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/raspi_stepper_move.go b/examples/raspi_stepper_move.go index 2dd62cd60..d214d5438 100644 --- a/examples/raspi_stepper_move.go +++ b/examples/raspi_stepper_move.go @@ -69,7 +69,6 @@ func main() { if err := stepper.MoveDeg(-360 * countRot); err != nil { log.Println("move backward", err) } - return } robot := gobot.NewRobot("stepperBot", @@ -78,5 +77,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/serial_sphero.go b/examples/serial_sphero.go index a6d942811..d44143497 100644 --- a/examples/serial_sphero.go +++ b/examples/serial_sphero.go @@ -23,11 +23,11 @@ func main() { work := func() { spheroDriver.SetDataStreaming(sphero.DefaultDataStreamingConfig()) - spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { + _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { fmt.Printf("Collision! %+v\n", data) }) - spheroDriver.On(sphero.SensorDataEvent, func(data interface{}) { + _ = spheroDriver.On(sphero.SensorDataEvent, func(data interface{}) { fmt.Printf("Streaming Data! %+v\n", data) }) @@ -49,5 +49,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/serial_sphero_api.go b/examples/serial_sphero_api.go index 33607ae13..558ae86d3 100644 --- a/examples/serial_sphero_api.go +++ b/examples/serial_sphero_api.go @@ -42,5 +42,7 @@ func main() { master.AddRobot(robot) } - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/serial_sphero_calibration.go b/examples/serial_sphero_calibration.go index b0f2ae353..d81830b27 100644 --- a/examples/serial_sphero_calibration.go +++ b/examples/serial_sphero_calibration.go @@ -27,7 +27,7 @@ func main() { calibrating := false work := func() { - keys.On(keyboard.Key, func(data interface{}) { + _ = keys.On(keyboard.Key, func(data interface{}) { key := data.(keyboard.KeyEvent) switch key.Key { @@ -64,5 +64,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/serial_sphero_conways.go b/examples/serial_sphero_conways.go index c03a0b2df..d7acbf908 100644 --- a/examples/serial_sphero_conways.go +++ b/examples/serial_sphero_conways.go @@ -43,7 +43,7 @@ func main() { conway.birth() - cell.On(sphero.CollisionEvent, func(data interface{}) { + _ = cell.On(sphero.CollisionEvent, func(data interface{}) { conway.contact() }) @@ -69,7 +69,9 @@ func main() { master.AddRobot(robot) } - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } func (c *conway) resetContacts() { diff --git a/examples/serial_sphero_dpad.go b/examples/serial_sphero_dpad.go index 45d34293c..d24673d81 100644 --- a/examples/serial_sphero_dpad.go +++ b/examples/serial_sphero_dpad.go @@ -49,5 +49,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/serial_sphero_master.go b/examples/serial_sphero_master.go index 0c7e16f0c..d57be5d82 100644 --- a/examples/serial_sphero_master.go +++ b/examples/serial_sphero_master.go @@ -52,5 +52,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/serial_sphero_multiple.go b/examples/serial_sphero_multiple.go index a5ab95b02..04cd68339 100644 --- a/examples/serial_sphero_multiple.go +++ b/examples/serial_sphero_multiple.go @@ -24,7 +24,7 @@ func NewSwarmBot(port string) *gobot.Robot { work := func() { spheroDriver.Stop() - spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { + _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { fmt.Println("Collision Detected!") }) @@ -63,5 +63,7 @@ func main() { master.AddRobot(NewSwarmBot(port)) } - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/square.go b/examples/square.go index bd0921b89..7a6c3fc30 100644 --- a/examples/square.go +++ b/examples/square.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -29,9 +30,15 @@ func main() { enabled := true work := func() { - red.Brightness(0xff) - green.Brightness(0x00) - blue.Brightness(0x00) + if err := red.Brightness(0xff); err != nil { + fmt.Println(err) + } + if err := green.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := blue.Brightness(0x00); err != nil { + fmt.Println(err) + } flash := false on := true @@ -40,29 +47,47 @@ func main() { if enabled { if flash { if on { - red.Brightness(0x00) - green.Brightness(0xff) - blue.Brightness(0x00) + if err := red.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := green.Brightness(0xff); err != nil { + fmt.Println(err) + } + if err := blue.Brightness(0x00); err != nil { + fmt.Println(err) + } on = false } else { - red.Brightness(0xff) - green.Brightness(0x00) - blue.Brightness(0x00) + if err := red.Brightness(0xff); err != nil { + fmt.Println(err) + } + if err := green.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := blue.Brightness(0x00); err != nil { + fmt.Println(err) + } on = true } } } }) - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { flash = true }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { flash = false - red.Brightness(0x00) - green.Brightness(0x00) - blue.Brightness(0xff) + if err := red.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := green.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := blue.Brightness(0xff); err != nil { + fmt.Println(err) + } }) } @@ -80,5 +105,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/square_fire.go b/examples/square_fire.go index 69c9c0121..76980069d 100644 --- a/examples/square_fire.go +++ b/examples/square_fire.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -29,9 +30,15 @@ func main() { enabled := true work := func() { - red.Brightness(0xff) - green.Brightness(0x00) - blue.Brightness(0x00) + if err := red.Brightness(0xff); err != nil { + fmt.Println(err) + } + if err := green.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := blue.Brightness(0x00); err != nil { + fmt.Println(err) + } flash := false on := true @@ -40,29 +47,47 @@ func main() { if enabled { if flash { if on { - red.Brightness(0x00) - green.Brightness(0xff) - blue.Brightness(0x00) + if err := red.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := green.Brightness(0xff); err != nil { + fmt.Println(err) + } + if err := blue.Brightness(0x00); err != nil { + fmt.Println(err) + } on = false } else { - red.Brightness(0x00) - green.Brightness(0x00) - blue.Brightness(0xff) + if err := red.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := green.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := blue.Brightness(0xff); err != nil { + fmt.Println(err) + } on = true } } } }) - button.On(gpio.ButtonPush, func(data interface{}) { + _ = button.On(gpio.ButtonPush, func(data interface{}) { flash = true }) - button.On(gpio.ButtonRelease, func(data interface{}) { + _ = button.On(gpio.ButtonRelease, func(data interface{}) { flash = false - red.Brightness(0x00) - green.Brightness(0x00) - blue.Brightness(0xff) + if err := red.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := green.Brightness(0x00); err != nil { + fmt.Println(err) + } + if err := blue.Brightness(0xff); err != nil { + fmt.Println(err) + } }) } @@ -80,5 +105,7 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } diff --git a/examples/tello.go b/examples/tello.go index 2d7b442f6..cba99b307 100644 --- a/examples/tello.go +++ b/examples/tello.go @@ -16,6 +16,7 @@ Once you are connected you can run the Gobot code on your computer to control th package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -26,10 +27,14 @@ func main() { drone := tello.NewDriver("8888") work := func() { - drone.TakeOff() + if err := drone.TakeOff(); err != nil { + fmt.Println(err) + } gobot.After(5*time.Second, func() { - drone.Land() + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) } @@ -39,5 +44,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tello_facetracker.go b/examples/tello_facetracker.go index 38cc2bcc6..e576f7413 100644 --- a/examples/tello_facetracker.go +++ b/examples/tello_facetracker.go @@ -94,22 +94,30 @@ func init() { return } - drone.On(tello.FlightDataEvent, func(data interface{}) { + _ = drone.On(tello.FlightDataEvent, func(data interface{}) { // TODO: protect flight data from race condition flightData = data.(*tello.FlightData) }) - drone.On(tello.ConnectedEvent, func(data interface{}) { + _ = drone.On(tello.ConnectedEvent, func(data interface{}) { fmt.Println("Connected") - drone.StartVideo() - drone.SetVideoEncoderRate(tello.VideoBitRateAuto) - drone.SetExposure(0) + if err := drone.StartVideo(); err != nil { + fmt.Println(err) + } + if err := drone.SetVideoEncoderRate(tello.VideoBitRateAuto); err != nil { + fmt.Println(err) + } + if err := drone.SetExposure(0); err != nil { + fmt.Println(err) + } gobot.Every(100*time.Millisecond, func() { - drone.StartVideo() + if err := drone.StartVideo(); err != nil { + fmt.Println(err) + } }) }) - drone.On(tello.VideoFrameEvent, func(data interface{}) { + _ = drone.On(tello.VideoFrameEvent, func(data interface{}) { pkt := data.([]byte) if _, err := ffmpegIn.Write(pkt); err != nil { fmt.Println(err) @@ -121,7 +129,10 @@ func init() { []gobot.Device{drone, stick}, ) - robot.Start() + err := robot.Start() + if err != nil { + fmt.Println(err) + } }() } @@ -257,7 +268,7 @@ func dist(x1, y1, x2, y2 float64) float64 { } func handleJoystick() { - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { drone.Forward(0) drone.Up(0) drone.Clockwise(0) @@ -270,33 +281,33 @@ func handleJoystick() { println("not tracking") } }) - stick.On(joystick.SquarePress, func(data interface{}) { + _ = stick.On(joystick.SquarePress, func(data interface{}) { fmt.Println("battery:", flightData.BatteryPercentage) }) - stick.On(joystick.TrianglePress, func(data interface{}) { + _ = stick.On(joystick.TrianglePress, func(data interface{}) { drone.TakeOff() println("Takeoff") }) - stick.On(joystick.XPress, func(data interface{}) { + _ = stick.On(joystick.XPress, func(data interface{}) { drone.Land() println("Land") }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { val := float64(data.(int16)) leftX.Store(val) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { val := float64(data.(int16)) leftY.Store(val) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { val := float64(data.(int16)) rightX.Store(val) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { val := float64(data.(int16)) rightY.Store(val) }) @@ -305,20 +316,32 @@ func handleJoystick() { switch { case rightStick.y < -10: - drone.Forward(tello.ValidatePitch(rightStick.y, offset)) + if err := drone.Forward(tello.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } case rightStick.y > 10: - drone.Backward(tello.ValidatePitch(rightStick.y, offset)) + if err := drone.Backward(tello.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Forward(0) + if err := drone.Forward(0); err != nil { + fmt.Println(err) + } } switch { case rightStick.x > 10: - drone.Right(tello.ValidatePitch(rightStick.x, offset)) + if err := drone.Right(tello.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } case rightStick.x < -10: - drone.Left(tello.ValidatePitch(rightStick.x, offset)) + if err := drone.Left(tello.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Right(0) + if err := drone.Right(0); err != nil { + fmt.Println(err) + } } }) @@ -326,20 +349,32 @@ func handleJoystick() { leftStick := getLeftStick() switch { case leftStick.y < -10: - drone.Up(tello.ValidatePitch(leftStick.y, offset)) + if err := drone.Up(tello.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } case leftStick.y > 10: - drone.Down(tello.ValidatePitch(leftStick.y, offset)) + if err := drone.Down(tello.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Up(0) + if err := drone.Up(0); err != nil { + fmt.Println(err) + } } switch { case leftStick.x > 20: - drone.Clockwise(tello.ValidatePitch(leftStick.x, offset)) + if err := drone.Clockwise(tello.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } case leftStick.x < -20: - drone.CounterClockwise(tello.ValidatePitch(leftStick.x, offset)) + if err := drone.CounterClockwise(tello.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Clockwise(0) + if err := drone.Clockwise(0); err != nil { + fmt.Println(err) + } } }) } diff --git a/examples/tello_keyboard.go b/examples/tello_keyboard.go index 82ee7c9bf..7d143e9b9 100644 --- a/examples/tello_keyboard.go +++ b/examples/tello_keyboard.go @@ -24,58 +24,96 @@ import ( ) func resetDronePostion(drone *tello.Driver) { - drone.Forward(0) - drone.Backward(0) - drone.Up(0) - drone.Down(0) - drone.Left(0) - drone.Right(0) - drone.Clockwise(0) + if err := drone.Forward(0); err != nil { + fmt.Println(err) + } + if err := drone.Backward(0); err != nil { + fmt.Println(err) + } + if err := drone.Up(0); err != nil { + fmt.Println(err) + } + if err := drone.Down(0); err != nil { + fmt.Println(err) + } + if err := drone.Left(0); err != nil { + fmt.Println(err) + } + if err := drone.Right(0); err != nil { + fmt.Println(err) + } + if err := drone.Clockwise(0); err != nil { + fmt.Println(err) + } } func main() { drone := tello.NewDriver("8888") keys := keyboard.NewDriver() - keys.On(keyboard.Key, func(data interface{}) { + _ = keys.On(keyboard.Key, func(data interface{}) { key := data.(keyboard.KeyEvent) switch key.Key { case keyboard.A: fmt.Println(key.Char) - drone.Clockwise(-25) + if err := drone.Clockwise(-25); err != nil { + fmt.Println(err) + } case keyboard.D: fmt.Println(key.Char) - drone.Clockwise(25) + if err := drone.Clockwise(25); err != nil { + fmt.Println(err) + } case keyboard.W: fmt.Println(key.Char) - drone.Forward(20) + if err := drone.Forward(20); err != nil { + fmt.Println(err) + } case keyboard.S: fmt.Println(key.Char) - drone.Backward(20) + if err := drone.Backward(20); err != nil { + fmt.Println(err) + } case keyboard.K: fmt.Println(key.Char) - drone.Down(20) + if err := drone.Down(20); err != nil { + fmt.Println(err) + } case keyboard.J: fmt.Println(key.Char) - drone.Up(20) + if err := drone.Up(20); err != nil { + fmt.Println(err) + } case keyboard.Q: fmt.Println(key.Char) - drone.Land() + if err := drone.Land(); err != nil { + fmt.Println(err) + } case keyboard.P: fmt.Println(key.Char) - drone.TakeOff() + if err := drone.TakeOff(); err != nil { + fmt.Println(err) + } case keyboard.ArrowUp: fmt.Println(key.Char) - drone.FrontFlip() + if err := drone.FrontFlip(); err != nil { + fmt.Println(err) + } case keyboard.ArrowDown: fmt.Println(key.Char) - drone.BackFlip() + if err := drone.BackFlip(); err != nil { + fmt.Println(err) + } case keyboard.ArrowLeft: fmt.Println(key.Char) - drone.LeftFlip() + if err := drone.LeftFlip(); err != nil { + fmt.Println(err) + } case keyboard.ArrowRight: fmt.Println(key.Char) - drone.RightFlip() + if err := drone.RightFlip(); err != nil { + fmt.Println(err) + } case keyboard.Escape: resetDronePostion(drone) } @@ -83,7 +121,7 @@ func main() { var flightData *tello.FlightData work := func() { - drone.On(tello.FlightDataEvent, func(data interface{}) { + _ = drone.On(tello.FlightDataEvent, func(data interface{}) { flightData = data.(*tello.FlightData) fmt.Println("Height:", flightData.Height) }) @@ -95,5 +133,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tello_opencv.go b/examples/tello_opencv.go index 165c5d85f..9b135c188 100644 --- a/examples/tello_opencv.go +++ b/examples/tello_opencv.go @@ -48,18 +48,26 @@ func main() { return } - drone.On(tello.ConnectedEvent, func(data interface{}) { + _ = drone.On(tello.ConnectedEvent, func(data interface{}) { fmt.Println("Connected") - drone.StartVideo() - drone.SetVideoEncoderRate(tello.VideoBitRateAuto) - drone.SetExposure(0) + if err := drone.StartVideo(); err != nil { + fmt.Println(err) + } + if err := drone.SetVideoEncoderRate(tello.VideoBitRateAuto); err != nil { + fmt.Println(err) + } + if err := drone.SetExposure(0); err != nil { + fmt.Println(err) + } gobot.Every(100*time.Millisecond, func() { - drone.StartVideo() + if err := drone.StartVideo(); err != nil { + fmt.Println(err) + } }) }) - drone.On(tello.VideoFrameEvent, func(data interface{}) { + _ = drone.On(tello.VideoFrameEvent, func(data interface{}) { pkt := data.([]byte) if _, err := ffmpegIn.Write(pkt); err != nil { fmt.Println(err) diff --git a/examples/tello_ps3.go b/examples/tello_ps3.go index fb0e2a7f1..267d5be91 100644 --- a/examples/tello_ps3.go +++ b/examples/tello_ps3.go @@ -48,50 +48,62 @@ func main() { rightX.Store(float64(0.0)) rightY.Store(float64(0.0)) - stick.On(joystick.TrianglePress, func(data interface{}) { - drone.TakeOff() + _ = stick.On(joystick.TrianglePress, func(data interface{}) { + if err := drone.TakeOff(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.XPress, func(data interface{}) { - drone.Land() + _ = stick.On(joystick.XPress, func(data interface{}) { + if err := drone.Land(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.UpPress, func(data interface{}) { + _ = stick.On(joystick.UpPress, func(data interface{}) { fmt.Println("FrontFlip") - drone.FrontFlip() + if err := drone.FrontFlip(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.DownPress, func(data interface{}) { + _ = stick.On(joystick.DownPress, func(data interface{}) { fmt.Println("BackFlip") - drone.BackFlip() + if err := drone.BackFlip(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.RightPress, func(data interface{}) { + _ = stick.On(joystick.RightPress, func(data interface{}) { fmt.Println("RightFlip") - drone.RightFlip() + if err := drone.RightFlip(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.LeftPress, func(data interface{}) { + _ = stick.On(joystick.LeftPress, func(data interface{}) { fmt.Println("LeftFlip") - drone.LeftFlip() + if err := drone.LeftFlip(); err != nil { + fmt.Println(err) + } }) - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { val := float64(data.(int16)) leftX.Store(val) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { val := float64(data.(int16)) leftY.Store(val) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { val := float64(data.(int16)) rightX.Store(val) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { val := float64(data.(int16)) rightY.Store(val) }) @@ -101,20 +113,32 @@ func main() { switch { case rightStick.y < -10: - drone.Forward(tello.ValidatePitch(rightStick.y, offset)) + if err := drone.Forward(tello.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } case rightStick.y > 10: - drone.Backward(tello.ValidatePitch(rightStick.y, offset)) + if err := drone.Backward(tello.ValidatePitch(rightStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Forward(0) + if err := drone.Forward(0); err != nil { + fmt.Println(err) + } } switch { case rightStick.x > 10: - drone.Right(tello.ValidatePitch(rightStick.x, offset)) + if err := drone.Right(tello.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } case rightStick.x < -10: - drone.Left(tello.ValidatePitch(rightStick.x, offset)) + if err := drone.Left(tello.ValidatePitch(rightStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Right(0) + if err := drone.Right(0); err != nil { + fmt.Println(err) + } } }) @@ -122,20 +146,32 @@ func main() { leftStick := getLeftStick() switch { case leftStick.y < -10: - drone.Up(tello.ValidatePitch(leftStick.y, offset)) + if err := drone.Up(tello.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } case leftStick.y > 10: - drone.Down(tello.ValidatePitch(leftStick.y, offset)) + if err := drone.Down(tello.ValidatePitch(leftStick.y, offset)); err != nil { + fmt.Println(err) + } default: - drone.Up(0) + if err := drone.Up(0); err != nil { + fmt.Println(err) + } } switch { case leftStick.x > 20: - drone.Clockwise(tello.ValidatePitch(leftStick.x, offset)) + if err := drone.Clockwise(tello.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } case leftStick.x < -20: - drone.CounterClockwise(tello.ValidatePitch(leftStick.x, offset)) + if err := drone.CounterClockwise(tello.ValidatePitch(leftStick.x, offset)); err != nil { + fmt.Println(err) + } default: - drone.Clockwise(0) + if err := drone.Clockwise(0); err != nil { + fmt.Println(err) + } } }) } @@ -146,7 +182,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } func getLeftStick() pair { diff --git a/examples/tello_video.go b/examples/tello_video.go index 55b649b4e..63728c5e1 100644 --- a/examples/tello_video.go +++ b/examples/tello_video.go @@ -35,16 +35,22 @@ func main() { } work := func() { - drone.On(tello.ConnectedEvent, func(data interface{}) { + _ = drone.On(tello.ConnectedEvent, func(data interface{}) { fmt.Println("Connected") - drone.StartVideo() - drone.SetVideoEncoderRate(tello.VideoBitRateAuto) + if err := drone.StartVideo(); err != nil { + fmt.Println(err) + } + if err := drone.SetVideoEncoderRate(tello.VideoBitRateAuto); err != nil { + fmt.Println(err) + } gobot.Every(100*time.Millisecond, func() { - drone.StartVideo() + if err := drone.StartVideo(); err != nil { + fmt.Println(err) + } }) }) - drone.On(tello.VideoFrameEvent, func(data interface{}) { + _ = drone.On(tello.VideoFrameEvent, func(data interface{}) { pkt := data.([]byte) if _, err := mplayerIn.Write(pkt); err != nil { fmt.Println(err) @@ -58,5 +64,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_adafruit1109_lcd_keys.go b/examples/tinkerboard_adafruit1109_lcd_keys.go index 305c09484..acdef3cdd 100644 --- a/examples/tinkerboard_adafruit1109_lcd_keys.go +++ b/examples/tinkerboard_adafruit1109_lcd_keys.go @@ -26,24 +26,40 @@ func main() { work := func() { // set a custom character smiley := [8]byte{0, 0, 10, 0, 0, 17, 14, 0} - ada.CreateChar(0, smiley) + if err := ada.CreateChar(0, smiley); err != nil { + fmt.Println(err) + } - ada.Clear() - ada.SetRGB(true, false, false) - ada.Write(" Hello from \n Tinker Board ") + if err := ada.Clear(); err != nil { + fmt.Println(err) + } + if err := ada.SetRGB(true, false, false); err != nil { + fmt.Println(err) + } + if err := ada.Write(" Hello from \n Tinker Board "); err != nil { + fmt.Println(err) + } // add the custom character at the end of the string - ada.Write(string(byte(0))) + if err := ada.Write(string(byte(0))); err != nil { + fmt.Println(err) + } // after 1 sec. activate rotation direction := 1 gobot.After(1*time.Second, func() { - ada.SetRGB(false, true, false) + if err := ada.SetRGB(false, true, false); err != nil { + fmt.Println(err) + } gobot.Every(400*time.Millisecond, func() { if direction == 1 { - ada.ScrollLeft() + if err := ada.ScrollLeft(); err != nil { + fmt.Println(err) + } } if direction == 2 { - ada.ScrollRight() + if err := ada.ScrollRight(); err != nil { + fmt.Println(err) + } } }) }) @@ -52,62 +68,92 @@ func main() { gobot.After(7*time.Second, func() { direction = 0 time.Sleep(1 * time.Second) - ada.LeftToRight() - ada.Clear() - ada.SetRGB(false, false, true) - ada.Write("Try the buttons!") + if err := ada.LeftToRight(); err != nil { + fmt.Println(err) + } + if err := ada.Clear(); err != nil { + fmt.Println(err) + } + if err := ada.SetRGB(false, false, true); err != nil { + fmt.Println(err) + } + if err := ada.Write("Try the buttons!"); err != nil { + fmt.Println(err) + } gobot.Every(500*time.Millisecond, func() { if val, err := ada.SelectButton(); err != nil { fmt.Println(err) - } else { - if val != 0 { - ada.Clear() - ada.Write("-Select Button-\nclear the screen") - ada.Blink(false) - direction = 0 + } else if val != 0 { + if err := ada.Clear(); err != nil { + fmt.Println(err) + } + if err := ada.Write("-Select Button-\nclear the screen"); err != nil { + fmt.Println(err) + } + if err := ada.Blink(false); err != nil { + fmt.Println(err) } + direction = 0 } if val, err := ada.UpButton(); err != nil { fmt.Println(err) - } else { - if val != 0 { - ada.Clear() - ada.Write(" -Up Button- \nset RGB to white") - ada.Blink(false) - ada.SetRGB(true, true, true) - direction = 0 + } else if val != 0 { + if err := ada.Clear(); err != nil { + fmt.Println(err) + } + if err := ada.Write(" -Up Button- \nset RGB to white"); err != nil { + fmt.Println(err) + } + if err := ada.Blink(false); err != nil { + fmt.Println(err) + } + if err := ada.SetRGB(true, true, true); err != nil { + fmt.Println(err) } + direction = 0 } if val, err := ada.DownButton(); err != nil { fmt.Println(err) - } else { - if val != 0 { - ada.Clear() - ada.Write(" -Down Button- \nset blink on") - ada.Blink(true) - direction = 0 + } else if val != 0 { + if err := ada.Clear(); err != nil { + fmt.Println(err) } + if err := ada.Write(" -Down Button- \nset blink on"); err != nil { + fmt.Println(err) + } + if err := ada.Blink(true); err != nil { + fmt.Println(err) + } + direction = 0 } if val, err := ada.LeftButton(); err != nil { fmt.Println(err) - } else { - if val != 0 { - ada.Clear() - ada.Write(" -Left Button- \nrotate left") - ada.Blink(false) - direction = 1 + } else if val != 0 { + if err := ada.Clear(); err != nil { + fmt.Println(err) + } + if err := ada.Write(" -Left Button- \nrotate left"); err != nil { + fmt.Println(err) + } + if err := ada.Blink(false); err != nil { + fmt.Println(err) } + direction = 1 } if val, err := ada.RightButton(); err != nil { fmt.Println(err) - } else { - if val != 0 { - ada.Clear() - ada.Write(" -Right Button- \nrotate right") - ada.Blink(false) - direction = 2 + } else if val != 0 { + if err := ada.Clear(); err != nil { + fmt.Println(err) } + if err := ada.Write(" -Right Button- \nrotate right"); err != nil { + fmt.Println(err) + } + if err := ada.Blink(false); err != nil { + fmt.Println(err) + } + direction = 2 } }) }) @@ -119,5 +165,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_ads1115.go b/examples/tinkerboard_ads1115.go index 883048635..625e01fba 100644 --- a/examples/tinkerboard_ads1115.go +++ b/examples/tinkerboard_ads1115.go @@ -84,6 +84,6 @@ func main() { ) if err := robot.Start(); err != nil { - fmt.Println(err) + panic(err) } } diff --git a/examples/tinkerboard_adxl345.go b/examples/tinkerboard_adxl345.go index 4dd6b65c6..1ddb1c4d7 100644 --- a/examples/tinkerboard_adxl345.go +++ b/examples/tinkerboard_adxl345.go @@ -39,5 +39,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_blink.go b/examples/tinkerboard_blink.go index c90faefe0..9a63d61d7 100644 --- a/examples/tinkerboard_blink.go +++ b/examples/tinkerboard_blink.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -20,7 +21,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -30,5 +33,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_bme280.go b/examples/tinkerboard_bme280.go index 4a78ff95e..eca32cc79 100644 --- a/examples/tinkerboard_bme280.go +++ b/examples/tinkerboard_bme280.go @@ -62,8 +62,7 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/tinkerboard_bmp280.go b/examples/tinkerboard_bmp280.go index 8146ca7e0..721d8e499 100644 --- a/examples/tinkerboard_bmp280.go +++ b/examples/tinkerboard_bmp280.go @@ -55,8 +55,7 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/tinkerboard_direct_pin.go b/examples/tinkerboard_direct_pin.go index 222425f60..564a17cd8 100644 --- a/examples/tinkerboard_direct_pin.go +++ b/examples/tinkerboard_direct_pin.go @@ -20,7 +20,8 @@ import ( // PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) // GPIO Tinkerboard: header pin 21 is input, pin 24 used as normal output, pin 26 used as inverted output // Button: the input pin is wired with a button to GND, an external pull up resistor is needed (e.g. 1K) -// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) to VCC +// LED's: the output pins are wired to the cathode of a LED, the anode is wired with a resistor (70-130Ohm for 20mA) +// to VCC // Expected behavior: always one LED is on, the other in opposite state, on button press the state changes func main() { const ( @@ -71,5 +72,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_generic.go b/examples/tinkerboard_generic.go index c76e9e16e..9410163b5 100644 --- a/examples/tinkerboard_generic.go +++ b/examples/tinkerboard_generic.go @@ -97,13 +97,13 @@ func main() { work, ) - err = robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } -// workaround for some boards (e.g. tinkerboard), because Read*Data not working together with PCA9501 caused by bad timing +// workaround for some boards (e.g. tinkerboard), because Read*Data not working together with PCA9501, +// caused by bad timing func readBlockDataBadTiming(drv *i2c.GenericDriver, reg uint8, data []byte) error { // set a value to the dummy address if err := drv.WriteByteData(reg-1, 0x00); err != nil { diff --git a/examples/tinkerboard_grove_lcd.go b/examples/tinkerboard_grove_lcd.go index b0ff7ed7f..d7414d136 100644 --- a/examples/tinkerboard_grove_lcd.go +++ b/examples/tinkerboard_grove_lcd.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -19,26 +20,46 @@ func main() { screen := i2c.NewGroveLcdDriver(board) work := func() { - screen.Write("Hello from") + if err := screen.Write("Hello from"); err != nil { + fmt.Println(err) + } - screen.SetRGB(255, 0, 0) + if err := screen.SetRGB(255, 0, 0); err != nil { + fmt.Println(err) + } gobot.After(5*time.Second, func() { - screen.Clear() - screen.Home() - screen.SetRGB(0, 255, 0) + if err := screen.Clear(); err != nil { + fmt.Println(err) + } + if err := screen.Home(); err != nil { + fmt.Println(err) + } + if err := screen.SetRGB(0, 255, 0); err != nil { + fmt.Println(err) + } // set a custom character in the first position - screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]) + if err := screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]); err != nil { + fmt.Println(err) + } // add the custom character at the end of the string - screen.Write("\nTinker Board " + string(byte(0))) + if err := screen.Write("\nTinker Board " + string(byte(0))); err != nil { + fmt.Println(err) + } gobot.Every(500*time.Millisecond, func() { - screen.Scroll(false) + if err := screen.Scroll(false); err != nil { + fmt.Println(err) + } }) }) - screen.Home() + if err := screen.Home(); err != nil { + fmt.Println(err) + } time.Sleep(1 * time.Second) - screen.SetRGB(0, 0, 255) + if err := screen.SetRGB(0, 0, 255); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("screenBot", @@ -47,5 +68,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_hcsr04.go b/examples/tinkerboard_hcsr04.go index f7a89f941..333f54168 100644 --- a/examples/tinkerboard_hcsr04.go +++ b/examples/tinkerboard_hcsr04.go @@ -92,6 +92,6 @@ func main() { ) if err := robot.Start(); err != nil { - log.Fatal(err) + panic(err) } } diff --git a/examples/tinkerboard_hmc5883l.go b/examples/tinkerboard_hmc5883l.go index 32b9c3c37..86467ff8e 100644 --- a/examples/tinkerboard_hmc5883l.go +++ b/examples/tinkerboard_hmc5883l.go @@ -48,5 +48,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_mfcrc522gpio.go b/examples/tinkerboard_mfcrc522gpio.go index fa126e2df..484743bd2 100644 --- a/examples/tinkerboard_mfcrc522gpio.go +++ b/examples/tinkerboard_mfcrc522gpio.go @@ -72,5 +72,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_mfcrc522spi.go b/examples/tinkerboard_mfcrc522spi.go index ccb0c8496..161567e9c 100644 --- a/examples/tinkerboard_mfcrc522spi.go +++ b/examples/tinkerboard_mfcrc522spi.go @@ -64,5 +64,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_mpl115a2.go b/examples/tinkerboard_mpl115a2.go index fbab149e8..b8b967312 100644 --- a/examples/tinkerboard_mpl115a2.go +++ b/examples/tinkerboard_mpl115a2.go @@ -47,8 +47,7 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/tinkerboard_mpu6050.go b/examples/tinkerboard_mpu6050.go index dbac9d20a..d7ecbdca9 100644 --- a/examples/tinkerboard_mpu6050.go +++ b/examples/tinkerboard_mpu6050.go @@ -41,5 +41,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_pca9533.go b/examples/tinkerboard_pca9533.go index cf9b03085..fe084c7b4 100644 --- a/examples/tinkerboard_pca9533.go +++ b/examples/tinkerboard_pca9533.go @@ -69,9 +69,8 @@ func main() { work, ) - err := robot.Start() - if err != nil { - fmt.Println(err) + if err := robot.Start(); err != nil { + panic(err) } } diff --git a/examples/tinkerboard_pcf8583_clock.go b/examples/tinkerboard_pcf8583_clock.go index ddd3209be..6392a088c 100644 --- a/examples/tinkerboard_pcf8583_clock.go +++ b/examples/tinkerboard_pcf8583_clock.go @@ -17,9 +17,9 @@ import ( ) // Wiring -// PWR Tinkerboard: 1 (+3.3V, VCC), 6, 9, 14, 20 (GND) -// I2C1 Tinkerboard: 3 (SDA), 5 (SCL) -// PCF8583 DIP package: 1 (OSCI, 50Hz), 2 (OSCO, nc), 3 (A0 - GND), 4 (VSS, GND), 5 (SDA), 6 (SCL), 7 (/INT, nc), 8 (VDD, +3.3V) +// PWR Tinkerboard: 1(+3.3V, VCC), 6,9,14,20(GND) +// I2C1 Tinkerboard: 3(SDA), 5(SCL) +// PCF8583 DIP package: 1(OSCI,50Hz), 2(OSCO,nc), 3(A0-GND), 4(VSS,GND), 5(SDA), 6(SCL), 7(/INT,nc), 8(VDD,+3.3V) func main() { board := tinkerboard.NewAdaptor() pcf := i2c.NewPCF8583Driver(board, i2c.WithBus(1), i2c.WithPCF8583Mode(i2c.PCF8583CtrlModeClock50)) @@ -58,5 +58,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_pcf8583_counter.go b/examples/tinkerboard_pcf8583_counter.go index 63fda9679..89e292792 100644 --- a/examples/tinkerboard_pcf8583_counter.go +++ b/examples/tinkerboard_pcf8583_counter.go @@ -17,9 +17,9 @@ import ( ) // Wiring -// PWR Tinkerboard: 1 (+3.3V, VCC), 6, 9, 14, 20 (GND) -// I2C1 Tinkerboard: 3 (SDA), 5 (SCL) -// PCF8583 DIP package: 1 (OSCI, event), 2 (OSCO, nc), 3 (A0 - GND), 4 (VSS, GND), 5 (SDA), 6 (SCL), 7 (/INT, nc), 8 (VDD, +3.3V) +// PWR Tinkerboard: 1(+3.3V,VCC), 6,9,14,20(GND) +// I2C1 Tinkerboard: 3(SDA), 5(SCL) +// PCF8583 DIP package: 1(OSCI,event), 2(OSCO,nc), 3(A0-GND), 4(VSS,GND), 5(SDA), 6(SCL), 7(/INT,nc), 8(VDD,+3.3V) // Note: event can be created by e.g. an debounced button func main() { board := tinkerboard.NewAdaptor() @@ -59,5 +59,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_pcf8591.go b/examples/tinkerboard_pcf8591.go index c25cc664a..b422ee87a 100644 --- a/examples/tinkerboard_pcf8591.go +++ b/examples/tinkerboard_pcf8591.go @@ -89,5 +89,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/tinkerboard_yl40.go b/examples/tinkerboard_yl40.go index 222d9562b..7d2201443 100644 --- a/examples/tinkerboard_yl40.go +++ b/examples/tinkerboard_yl40.go @@ -74,5 +74,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/up2_lcd.go b/examples/up2_lcd.go index 94cf3b860..0fd97c0d8 100644 --- a/examples/up2_lcd.go +++ b/examples/up2_lcd.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -19,26 +20,46 @@ func main() { screen := i2c.NewGroveLcdDriver(board) work := func() { - screen.Write("hello") + if err := screen.Write("hello"); err != nil { + fmt.Println(err) + } - screen.SetRGB(255, 0, 0) + if err := screen.SetRGB(255, 0, 0); err != nil { + fmt.Println(err) + } gobot.After(5*time.Second, func() { - screen.Clear() - screen.Home() - screen.SetRGB(0, 255, 0) + if err := screen.Clear(); err != nil { + fmt.Println(err) + } + if err := screen.Home(); err != nil { + fmt.Println(err) + } + if err := screen.SetRGB(0, 255, 0); err != nil { + fmt.Println(err) + } // set a custom character in the first position - screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]) + if err := screen.SetCustomChar(0, i2c.CustomLCDChars["smiley"]); err != nil { + fmt.Println(err) + } // add the custom character at the end of the string - screen.Write("goodbye\nhave a nice day " + string(byte(0))) + if err := screen.Write("goodbye\nhave a nice day " + string(byte(0))); err != nil { + fmt.Println(err) + } gobot.Every(500*time.Millisecond, func() { - screen.Scroll(false) + if err := screen.Scroll(false); err != nil { + fmt.Println(err) + } }) }) - screen.Home() + if err := screen.Home(); err != nil { + fmt.Println(err) + } time.Sleep(1 * time.Second) - screen.SetRGB(0, 0, 255) + if err := screen.SetRGB(0, 0, 255); err != nil { + fmt.Println(err) + } } robot := gobot.NewRobot("screenBot", @@ -47,5 +68,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/up2_leds.go b/examples/up2_leds.go index 9c7ff0916..cefae8410 100644 --- a/examples/up2_leds.go +++ b/examples/up2_leds.go @@ -7,6 +7,7 @@ package main import ( + "fmt" "time" "gobot.io/x/gobot/v2" @@ -22,22 +23,38 @@ func main() { yellow := gpio.NewLedDriver(b, up2.LEDYellow) work := func() { - red.Off() - blue.Off() - green.Off() - yellow.Off() + if err := red.Off(); err != nil { + fmt.Println(err) + } + if err := blue.Off(); err != nil { + fmt.Println(err) + } + if err := green.Off(); err != nil { + fmt.Println(err) + } + if err := yellow.Off(); err != nil { + fmt.Println(err) + } gobot.Every(1*time.Second, func() { - red.Toggle() + if err := red.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(2*time.Second, func() { - green.Toggle() + if err := green.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(4*time.Second, func() { - yellow.Toggle() + if err := yellow.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(8*time.Second, func() { - blue.Toggle() + if err := blue.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -47,5 +64,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/wifi_firmata_analog_input.go b/examples/wifi_firmata_analog_input.go index 924d81e35..9b5275690 100644 --- a/examples/wifi_firmata_analog_input.go +++ b/examples/wifi_firmata_analog_input.go @@ -21,7 +21,7 @@ func main() { sensor := aio.NewAnalogSensorDriver(firmataAdaptor, "A0", aio.WithSensorCyclicRead(500*time.Millisecond)) work := func() { - sensor.On(aio.Data, func(data interface{}) { + _ = sensor.On(aio.Data, func(data interface{}) { brightness := uint8( gobot.ToScale(gobot.FromScale(float64(data.(int)), 0, 1024), 0, 255), ) @@ -36,5 +36,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/examples/wifi_firmata_blink.go b/examples/wifi_firmata_blink.go index b996db114..d1d06b148 100644 --- a/examples/wifi_firmata_blink.go +++ b/examples/wifi_firmata_blink.go @@ -20,6 +20,7 @@ package main import ( + "fmt" "os" "time" @@ -34,7 +35,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -44,5 +47,7 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } diff --git a/platforms/beaglebone/README.md b/platforms/beaglebone/README.md index ea871af24..b3a116e98 100644 --- a/platforms/beaglebone/README.md +++ b/platforms/beaglebone/README.md @@ -45,7 +45,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -55,7 +57,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` @@ -78,7 +82,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -88,7 +94,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/beaglebone/doc.go b/platforms/beaglebone/doc.go index d868ed3f7..48f9716dd 100644 --- a/platforms/beaglebone/doc.go +++ b/platforms/beaglebone/doc.go @@ -24,7 +24,9 @@ Example: work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -34,7 +36,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For more information refer to the beaglebone README: diff --git a/platforms/bleclient/README.md b/platforms/bleclient/README.md index 271c93880..8655f7526 100644 --- a/platforms/bleclient/README.md +++ b/platforms/bleclient/README.md @@ -85,6 +85,8 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/dexter/gopigo3/README.md b/platforms/dexter/gopigo3/README.md index cadbc9df4..061c555a2 100644 --- a/platforms/dexter/gopigo3/README.md +++ b/platforms/dexter/gopigo3/README.md @@ -47,6 +47,8 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/digispark/README.md b/platforms/digispark/README.md index 95813e2bc..80a953aff 100644 --- a/platforms/digispark/README.md +++ b/platforms/digispark/README.md @@ -48,7 +48,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -58,7 +60,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/digispark/doc.go b/platforms/digispark/doc.go index 4a6477dfa..dd335f32c 100644 --- a/platforms/digispark/doc.go +++ b/platforms/digispark/doc.go @@ -26,7 +26,9 @@ Example: work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -36,7 +38,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For further information refer to digispark README: diff --git a/platforms/dji/tello/README.md b/platforms/dji/tello/README.md index 9b0f9cf61..29326ee3e 100644 --- a/platforms/dji/tello/README.md +++ b/platforms/dji/tello/README.md @@ -44,7 +44,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/firmata/README.md b/platforms/firmata/README.md index 6d7dedb6e..94b5230a9 100644 --- a/platforms/firmata/README.md +++ b/platforms/firmata/README.md @@ -42,7 +42,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -52,7 +54,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` @@ -75,7 +79,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -85,7 +91,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/firmata/client/examples/blink.go b/platforms/firmata/client/examples/blink.go index eebee49ac..6e76ca3e9 100644 --- a/platforms/firmata/client/examples/blink.go +++ b/platforms/firmata/client/examples/blink.go @@ -11,6 +11,7 @@ import ( "time" "go.bug.st/serial" + "gobot.io/x/gobot/v2/platforms/firmata/client" ) @@ -24,7 +25,11 @@ func main() { fmt.Println("connecting.....") err = board.Connect(sp) - defer board.Disconnect() + defer func() { + if err := board.Disconnect(); err != nil { + fmt.Println(err) + } + }() if err != nil { panic(err) diff --git a/platforms/firmata/doc.go b/platforms/firmata/doc.go index adf227c12..66c5c5a3d 100644 --- a/platforms/firmata/doc.go +++ b/platforms/firmata/doc.go @@ -23,7 +23,9 @@ Example: work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -33,7 +35,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For further information refer to firmata readme: diff --git a/platforms/holystone/hs200/README.md b/platforms/holystone/hs200/README.md index 7357f3a9d..39e87ef4d 100644 --- a/platforms/holystone/hs200/README.md +++ b/platforms/holystone/hs200/README.md @@ -45,7 +45,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/intel-iot/curie/README.md b/platforms/intel-iot/curie/README.md index 45b5eee11..7fd8616af 100644 --- a/platforms/intel-iot/curie/README.md +++ b/platforms/intel-iot/curie/README.md @@ -37,20 +37,22 @@ func main() { imu := curie.NewIMUDriver(firmataAdaptor) work := func() { - imu.On("Accelerometer", func(data interface{}) { + _ = imu.On("Accelerometer", func(data interface{}) { log.Println("Accelerometer", data) }) - imu.On("Gyroscope", func(data interface{}) { + _ = imu.On("Gyroscope", func(data interface{}) { log.Println("Gyroscope", data) }) - imu.On("Temperature", func(data interface{}) { + _ = imu.On("Temperature", func(data interface{}) { log.Println("Temperature", data) }) gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) gobot.Every(100*time.Millisecond, func() { @@ -66,7 +68,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/intel-iot/edison/README.md b/platforms/intel-iot/edison/README.md index 8334b34ce..2819009e9 100644 --- a/platforms/intel-iot/edison/README.md +++ b/platforms/intel-iot/edison/README.md @@ -61,7 +61,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -71,7 +73,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/intel-iot/joule/README.md b/platforms/intel-iot/joule/README.md index 7800e61eb..d07b10b48 100644 --- a/platforms/intel-iot/joule/README.md +++ b/platforms/intel-iot/joule/README.md @@ -38,7 +38,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -48,7 +50,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/jetson/README.md b/platforms/jetson/README.md index 18fde6556..178c7cfe8 100644 --- a/platforms/jetson/README.md +++ b/platforms/jetson/README.md @@ -34,7 +34,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -44,7 +46,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/joystick/README.md b/platforms/joystick/README.md index 9f8f06740..555bd61d2 100644 --- a/platforms/joystick/README.md +++ b/platforms/joystick/README.md @@ -56,68 +56,68 @@ func main() { work := func() { // buttons - stick.On(joystick.SquarePress, func(data interface{}) { + _ = stick.On(joystick.SquarePress, func(data interface{}) { fmt.Println("square_press") }) - stick.On(joystick.SquareRelease, func(data interface{}) { + _ = stick.On(joystick.SquareRelease, func(data interface{}) { fmt.Println("square_release") }) - stick.On(joystick.TrianglePress, func(data interface{}) { + _ = stick.On(joystick.TrianglePress, func(data interface{}) { fmt.Println("triangle_press") }) - stick.On(joystick.TriangleRelease, func(data interface{}) { + _ = stick.On(joystick.TriangleRelease, func(data interface{}) { fmt.Println("triangle_release") }) - stick.On(joystick.CirclePress, func(data interface{}) { + _ = stick.On(joystick.CirclePress, func(data interface{}) { fmt.Println("circle_press") }) - stick.On(joystick.CircleRelease, func(data interface{}) { + _ = stick.On(joystick.CircleRelease, func(data interface{}) { fmt.Println("circle_release") }) - stick.On(joystick.XPress, func(data interface{}) { + _ = stick.On(joystick.XPress, func(data interface{}) { fmt.Println("x_press") }) - stick.On(joystick.XRelease, func(data interface{}) { + _ = stick.On(joystick.XRelease, func(data interface{}) { fmt.Println("x_release") }) - stick.On(joystick.StartPress, func(data interface{}) { + _ = stick.On(joystick.StartPress, func(data interface{}) { fmt.Println("start_press") }) - stick.On(joystick.StartRelease, func(data interface{}) { + _ = stick.On(joystick.StartRelease, func(data interface{}) { fmt.Println("start_release") }) - stick.On(joystick.SelectPress, func(data interface{}) { + _ = stick.On(joystick.SelectPress, func(data interface{}) { fmt.Println("select_press") }) - stick.On(joystick.SelectRelease, func(data interface{}) { + _ = stick.On(joystick.SelectRelease, func(data interface{}) { fmt.Println("select_release") }) // joysticks - stick.On(joystick.LeftX, func(data interface{}) { + _ = stick.On(joystick.LeftX, func(data interface{}) { fmt.Println("left_x", data) }) - stick.On(joystick.LeftY, func(data interface{}) { + _ = stick.On(joystick.LeftY, func(data interface{}) { fmt.Println("left_y", data) }) - stick.On(joystick.RightX, func(data interface{}) { + _ = stick.On(joystick.RightX, func(data interface{}) { fmt.Println("right_x", data) }) - stick.On(joystick.RightY, func(data interface{}) { + _ = stick.On(joystick.RightY, func(data interface{}) { fmt.Println("right_y", data) }) // triggers - stick.On(joystick.R1Press, func(data interface{}) { + _ = stick.On(joystick.R1Press, func(data interface{}) { fmt.Println("R1Press", data) }) - stick.On(joystick.R2Press, func(data interface{}) { + _ = stick.On(joystick.R2Press, func(data interface{}) { fmt.Println("R2Press", data) }) - stick.On(joystick.L1Press, func(data interface{}) { + _ = stick.On(joystick.L1Press, func(data interface{}) { fmt.Println("L1Press", data) }) - stick.On(joystick.L2Press, func(data interface{}) { + _ = stick.On(joystick.L2Press, func(data interface{}) { fmt.Println("L2Press", data) }) } @@ -128,7 +128,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/joystick/doc.go b/platforms/joystick/doc.go index 3b5fcd64e..640429d6c 100644 --- a/platforms/joystick/doc.go +++ b/platforms/joystick/doc.go @@ -21,28 +21,28 @@ Example: joystick := joystick.NewDriver(joystickAdaptor, "dualshock3") work := func() { - joystick.On(joystick.Event("square_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("square_press"), func(data interface{}) { fmt.Println("square_press") }) - joystick.On(joystick.Event("square_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("square_release"), func(data interface{}) { fmt.Println("square_release") }) - joystick.On(joystick.Event("triangle_press"), func(data interface{}) { + _ = joystick.On(joystick.Event("triangle_press"), func(data interface{}) { fmt.Println("triangle_press") }) - joystick.On(joystick.Event("triangle_release"), func(data interface{}) { + _ = joystick.On(joystick.Event("triangle_release"), func(data interface{}) { fmt.Println("triangle_release") }) - joystick.On(joystick.Event("left_x"), func(data interface{}) { + _ = joystick.On(joystick.Event("left_x"), func(data interface{}) { fmt.Println("left_x", data) }) - joystick.On(joystick.Event("left_y"), func(data interface{}) { + _ = joystick.On(joystick.Event("left_y"), func(data interface{}) { fmt.Println("left_y", data) }) - joystick.On(joystick.Event("right_x"), func(data interface{}) { + _ = joystick.On(joystick.Event("right_x"), func(data interface{}) { fmt.Println("right_x", data) }) - joystick.On(joystick.Event("right_y"), func(data interface{}) { + _ = joystick.On(joystick.Event("right_y"), func(data interface{}) { fmt.Println("right_y", data) }) } @@ -53,7 +53,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For further information refer to joystick README: diff --git a/platforms/keyboard/README.md b/platforms/keyboard/README.md index 2044a1624..8c0d79b01 100644 --- a/platforms/keyboard/README.md +++ b/platforms/keyboard/README.md @@ -24,7 +24,7 @@ func main() { keys := keyboard.NewDriver() work := func() { - keys.On(keyboard.Key, func(data interface{}) { + _ = keys.On(keyboard.Key, func(data interface{}) { key := data.(keyboard.KeyEvent) if key.Key == keyboard.A { @@ -41,6 +41,8 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/keyboard/doc.go b/platforms/keyboard/doc.go index e7e364c69..f5c6620e6 100644 --- a/platforms/keyboard/doc.go +++ b/platforms/keyboard/doc.go @@ -22,7 +22,7 @@ Example: keys := keyboard.NewDriver() work := func() { - keys.On(keyboard.Key, func(data interface{}) { + _ = keys.On(keyboard.Key, func(data interface{}) { key := data.(keyboard.KeyEvent) if key.Key == keyboard.A { @@ -39,7 +39,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For further information refer to keyboard README: diff --git a/platforms/leap/README.md b/platforms/leap/README.md index c6132061b..a77220103 100644 --- a/platforms/leap/README.md +++ b/platforms/leap/README.md @@ -39,7 +39,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/leap/doc.go b/platforms/leap/doc.go index 226445d60..fbb030810 100644 --- a/platforms/leap/doc.go +++ b/platforms/leap/doc.go @@ -34,7 +34,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For more information refer to the leap README: diff --git a/platforms/mavlink/README.md b/platforms/mavlink/README.md index b8b7412bd..45ab173d8 100644 --- a/platforms/mavlink/README.md +++ b/platforms/mavlink/README.md @@ -75,7 +75,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/mavlink/doc.go b/platforms/mavlink/doc.go index b88fcf757..630c180de 100644 --- a/platforms/mavlink/doc.go +++ b/platforms/mavlink/doc.go @@ -59,7 +59,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For further information refer to mavlink README: diff --git a/platforms/megapi/README.md b/platforms/megapi/README.md index f4200b919..29db58c1b 100644 --- a/platforms/megapi/README.md +++ b/platforms/megapi/README.md @@ -45,6 +45,8 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/microbit/README.md b/platforms/microbit/README.md index b95e086a2..ba0f30423 100644 --- a/platforms/microbit/README.md +++ b/platforms/microbit/README.md @@ -51,7 +51,9 @@ func main() { ubit := microbit.NewLEDDriver(bleAdaptor) work := func() { - ubit.Blank() + if err := ubit.Blank(); err != nil { + fmt.Println(err) + } gobot.After(1*time.Second, func() { ubit.WriteText("Hello") }) @@ -66,7 +68,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` @@ -96,11 +100,15 @@ func main() { led := gpio.NewLedDriver(ubit, "1") work := func() { - button.On(gpio.ButtonPush, func(data interface{}) { - led.On() + _ = button.On(gpio.ButtonPush, func(data interface{}) { + if err := led.On(); err != nil { + fmt.Println(err) + } }) - button.On(gpio.ButtonRelease, func(data interface{}) { - led.Off() + _ = button.On(gpio.ButtonRelease, func(data interface{}) { + if err := led.Off(); err != nil { + fmt.Println(err) + } }) } @@ -110,7 +118,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/mqtt/README.md b/platforms/mqtt/README.md index 5b7555db3..62d85c04f 100644 --- a/platforms/mqtt/README.md +++ b/platforms/mqtt/README.md @@ -30,10 +30,10 @@ func main() { mqttAdaptor := mqtt.NewAdaptor("tcp://0.0.0.0:1883", "pinger") work := func() { - mqttAdaptor.On("hello", func(msg mqtt.Message) { + _ = mqttAdaptor.On("hello", func(msg mqtt.Message) { fmt.Println(msg) }) - mqttAdaptor.On("hola", func(msg mqtt.Message) { + _ = mqttAdaptor.On("hola", func(msg mqtt.Message) { fmt.Println(msg) }) data := []byte("o") @@ -50,7 +50,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/nats/README.md b/platforms/nats/README.md index a079fb659..1594c94b7 100644 --- a/platforms/nats/README.md +++ b/platforms/nats/README.md @@ -60,7 +60,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` @@ -105,7 +107,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/neurosky/README.md b/platforms/neurosky/README.md index 68ec33cc4..b0cc9f33a 100644 --- a/platforms/neurosky/README.md +++ b/platforms/neurosky/README.md @@ -67,25 +67,25 @@ func main() { neuro := neurosky.NewDriver(adaptor) work := func() { - neuro.On(neuro.Event("extended"), func(data interface{}) { + _ = neuro.On(neuro.Event("extended"), func(data interface{}) { fmt.Println("Extended", data) }) - neuro.On(neuro.Event("signal"), func(data interface{}) { + _ = neuro.On(neuro.Event("signal"), func(data interface{}) { fmt.Println("Signal", data) }) - neuro.On(neuro.Event("attention"), func(data interface{}) { + _ = neuro.On(neuro.Event("attention"), func(data interface{}) { fmt.Println("Attention", data) }) - neuro.On(neuro.Event("meditation"), func(data interface{}) { + _ = neuro.On(neuro.Event("meditation"), func(data interface{}) { fmt.Println("Meditation", data) }) - neuro.On(neuro.Event("blink"), func(data interface{}) { + _ = neuro.On(neuro.Event("blink"), func(data interface{}) { fmt.Println("Blink", data) }) - neuro.On(neuro.Event("wave"), func(data interface{}) { + _ = neuro.On(neuro.Event("wave"), func(data interface{}) { fmt.Println("Wave", data) }) - neuro.On(neuro.Event("eeg"), func(data interface{}) { + _ = neuro.On(neuro.Event("eeg"), func(data interface{}) { eeg := data.(neurosky.EEGData) fmt.Println("Delta", eeg.Delta) fmt.Println("Theta", eeg.Theta) @@ -105,6 +105,8 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/neurosky/doc.go b/platforms/neurosky/doc.go index d4afbff6a..bee9e928a 100644 --- a/platforms/neurosky/doc.go +++ b/platforms/neurosky/doc.go @@ -21,25 +21,25 @@ Example: neuro := neurosky.NewDriver(adaptor) work := func() { - neuro.On(neuro.Event("extended"), func(data interface{}) { + _ = neuro.On(neuro.Event("extended"), func(data interface{}) { fmt.Println("Extended", data) }) - neuro.On(neuro.Event("signal"), func(data interface{}) { + _ = neuro.On(neuro.Event("signal"), func(data interface{}) { fmt.Println("Signal", data) }) - neuro.On(neuro.Event("attention"), func(data interface{}) { + _ = neuro.On(neuro.Event("attention"), func(data interface{}) { fmt.Println("Attention", data) }) - neuro.On(neuro.Event("meditation"), func(data interface{}) { + _ = neuro.On(neuro.Event("meditation"), func(data interface{}) { fmt.Println("Meditation", data) }) - neuro.On(neuro.Event("blink"), func(data interface{}) { + _ = neuro.On(neuro.Event("blink"), func(data interface{}) { fmt.Println("Blink", data) }) - neuro.On(neuro.Event("wave"), func(data interface{}) { + _ = neuro.On(neuro.Event("wave"), func(data interface{}) { fmt.Println("Wave", data) }) - neuro.On(neuro.Event("eeg"), func(data interface{}) { + _ = neuro.On(neuro.Event("eeg"), func(data interface{}) { eeg := data.(neurosky.EEGData) fmt.Println("Delta", eeg.Delta) fmt.Println("Theta", eeg.Theta) @@ -59,7 +59,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For further information refer to neuroky README: diff --git a/platforms/opencv/README.md b/platforms/opencv/README.md index f45dad612..c89e25b92 100644 --- a/platforms/opencv/README.md +++ b/platforms/opencv/README.md @@ -64,6 +64,8 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/opencv/doc.go b/platforms/opencv/doc.go index ecd83ce15..da047368f 100644 --- a/platforms/opencv/doc.go +++ b/platforms/opencv/doc.go @@ -34,7 +34,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For further information refer to opencv README: diff --git a/platforms/parrot/ardrone/README.md b/platforms/parrot/ardrone/README.md index 893e103f4..5a57a2e2f 100644 --- a/platforms/parrot/ardrone/README.md +++ b/platforms/parrot/ardrone/README.md @@ -40,7 +40,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/parrot/ardrone/doc.go b/platforms/parrot/ardrone/doc.go index 3ea5b032f..bb1f8b896 100644 --- a/platforms/parrot/ardrone/doc.go +++ b/platforms/parrot/ardrone/doc.go @@ -35,7 +35,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For more information refer to the ardrone README: diff --git a/platforms/parrot/bebop/README.md b/platforms/parrot/bebop/README.md index 112c86276..746af9756 100644 --- a/platforms/parrot/bebop/README.md +++ b/platforms/parrot/bebop/README.md @@ -40,7 +40,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/parrot/bebop/client/examples/takeoff.go b/platforms/parrot/bebop/client/examples/takeoff.go index 605b2ca38..60b4d1358 100644 --- a/platforms/parrot/bebop/client/examples/takeoff.go +++ b/platforms/parrot/bebop/client/examples/takeoff.go @@ -21,7 +21,10 @@ func main() { return } - bebop.HullProtection(true) + if err := bebop.HullProtection(true); err != nil { + fmt.Println(err) + return + } fmt.Println("takeoff") if err := bebop.TakeOff(); err != nil { diff --git a/platforms/parrot/minidrone/README.md b/platforms/parrot/minidrone/README.md index dc03a75b7..b52c5c2e5 100644 --- a/platforms/parrot/minidrone/README.md +++ b/platforms/parrot/minidrone/README.md @@ -82,7 +82,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/particle/README.md b/platforms/particle/README.md index 50f8d2786..364f9f2b5 100644 --- a/platforms/particle/README.md +++ b/platforms/particle/README.md @@ -31,7 +31,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -41,6 +43,8 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/particle/doc.go b/platforms/particle/doc.go index 467b65dec..8151b6335 100644 --- a/platforms/particle/doc.go +++ b/platforms/particle/doc.go @@ -23,7 +23,9 @@ Example: work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -33,7 +35,9 @@ Example: work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } For further information refer to Particle readme: diff --git a/platforms/pebble/README.md b/platforms/pebble/README.md index 0fa25a4a5..c12e35005 100644 --- a/platforms/pebble/README.md +++ b/platforms/pebble/README.md @@ -54,7 +54,9 @@ func main() { master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/pebble/doc.go b/platforms/pebble/doc.go index 686eb837a..5e723cf76 100644 --- a/platforms/pebble/doc.go +++ b/platforms/pebble/doc.go @@ -49,7 +49,9 @@ your computer IP, robot name is 'pebble' and robot api port is 8080 master.AddRobot(robot) - master.Start() + if err := master.Start(); err != nil { + panic(err) + } } For more information refer to the pebble README: diff --git a/platforms/raspi/README.md b/platforms/raspi/README.md index 8db99b238..718c523e3 100644 --- a/platforms/raspi/README.md +++ b/platforms/raspi/README.md @@ -37,7 +37,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -47,7 +49,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/rockpi/README.md b/platforms/rockpi/README.md index 42af42108..ba6fc76d4 100644 --- a/platforms/rockpi/README.md +++ b/platforms/rockpi/README.md @@ -42,7 +42,9 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { - led.Toggle() + if err := led.Toggle(); err != nil { + fmt.Println(err) + } }) } @@ -52,7 +54,9 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/sphero/bb8/README.md b/platforms/sphero/bb8/README.md index e9b2f85b7..fa1d77ea8 100644 --- a/platforms/sphero/bb8/README.md +++ b/platforms/sphero/bb8/README.md @@ -39,7 +39,10 @@ func main() { work, ) - robot.Start() + err := robot.Start() + if err != nil { + fmt.Println(err) + } } ``` diff --git a/platforms/sphero/ollie/README.md b/platforms/sphero/ollie/README.md index 803016f5d..48cc3bb1d 100644 --- a/platforms/sphero/ollie/README.md +++ b/platforms/sphero/ollie/README.md @@ -39,7 +39,10 @@ func main() { work, ) - robot.Start() + err := robot.Start() + if err != nil { + fmt.Println(err) + } } ``` diff --git a/platforms/sphero/sphero/README.md b/platforms/sphero/sphero/README.md index e2cdb0087..d156bce53 100644 --- a/platforms/sphero/sphero/README.md +++ b/platforms/sphero/sphero/README.md @@ -84,6 +84,8 @@ func main() { work, ) - robot.Start() + if err := robot.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/sphero/sprkplus/README.md b/platforms/sphero/sprkplus/README.md index 87fcdb3c4..c6ab58a7c 100644 --- a/platforms/sphero/sprkplus/README.md +++ b/platforms/sphero/sprkplus/README.md @@ -39,7 +39,10 @@ func main() { work, ) - robot.Start() + err := robot.Start() + if err != nil { + fmt.Println(err) + } } ``` From 9430005b82d6f607cf9f72d054a553160628ad5e Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Sun, 11 Feb 2024 17:01:24 +0100 Subject: [PATCH 43/57] ble(client): add scan timout (#1051) --- examples/bleclient_battery.go | 2 +- examples/bleclient_device_info.go | 3 +- examples/bleclient_generic_access.go | 3 +- platforms/bleclient/ble_client_adaptor.go | 260 +++++++----- .../bleclient/ble_client_adaptor_options.go | 30 ++ .../ble_client_adaptor_options_test.go | 27 ++ .../bleclient/ble_client_adaptor_test.go | 380 ++++++++++++++++++ platforms/bleclient/btwrapper.go | 154 +++++++ platforms/bleclient/helper_test.go | 118 ++++++ platforms/bleclient/uuid.go | 38 +- platforms/bleclient/uuid_test.go | 58 +++ 11 files changed, 950 insertions(+), 123 deletions(-) create mode 100644 platforms/bleclient/ble_client_adaptor_options.go create mode 100644 platforms/bleclient/ble_client_adaptor_options_test.go create mode 100644 platforms/bleclient/btwrapper.go create mode 100644 platforms/bleclient/helper_test.go create mode 100644 platforms/bleclient/uuid_test.go diff --git a/examples/bleclient_battery.go b/examples/bleclient_battery.go index f0a179954..b84d0e62d 100644 --- a/examples/bleclient_battery.go +++ b/examples/bleclient_battery.go @@ -26,7 +26,7 @@ import ( ) func main() { - bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1], bleclient.WithScanTimeout(30*time.Second)) battery := ble.NewBatteryDriver(bleAdaptor) work := func() { diff --git a/examples/bleclient_device_info.go b/examples/bleclient_device_info.go index 69f8c997b..0b8adfce1 100644 --- a/examples/bleclient_device_info.go +++ b/examples/bleclient_device_info.go @@ -18,6 +18,7 @@ package main import ( "fmt" "os" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble" @@ -25,7 +26,7 @@ import ( ) func main() { - bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1], bleclient.WithScanTimeout(30*time.Second), bleclient.WithDebug()) info := ble.NewDeviceInformationDriver(bleAdaptor) work := func() { diff --git a/examples/bleclient_generic_access.go b/examples/bleclient_generic_access.go index 47e7842fb..400f4b4a8 100644 --- a/examples/bleclient_generic_access.go +++ b/examples/bleclient_generic_access.go @@ -18,6 +18,7 @@ package main import ( "fmt" "os" + "time" "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble" @@ -25,7 +26,7 @@ import ( ) func main() { - bleAdaptor := bleclient.NewAdaptor(os.Args[1]) + bleAdaptor := bleclient.NewAdaptor(os.Args[1], bleclient.WithScanTimeout(30*time.Second), bleclient.WithDebug()) access := ble.NewGenericAccessDriver(bleAdaptor) work := func() { diff --git a/platforms/bleclient/ble_client_adaptor.go b/platforms/bleclient/ble_client_adaptor.go index ffc09f155..c6e336f80 100644 --- a/platforms/bleclient/ble_client_adaptor.go +++ b/platforms/bleclient/ble_client_adaptor.go @@ -11,112 +11,168 @@ import ( "gobot.io/x/gobot/v2" ) -var ( - currentAdapter *bluetooth.Adapter - bleMutex sync.Mutex -) +type configuration struct { + scanTimeout time.Duration + sleepAfterDisconnect time.Duration + debug bool +} -// Adaptor represents a client connection to a BLE Peripheral +// Adaptor represents a Client Connection to a BLE Peripheral type Adaptor struct { - name string - address string - AdapterName string + name string + identifier string + cfg *configuration - addr bluetooth.Address - adpt *bluetooth.Adapter - device *bluetooth.Device - characteristics map[string]bluetooth.DeviceCharacteristic + btAdpt *btAdapter + btDevice *btDevice + characteristics map[string]bluetoothExtCharacteristicer - connected bool - withoutResponses bool + connected bool + rssi int + + btAdptCreator btAdptCreatorFunc + mutex *sync.Mutex } -// NewAdaptor returns a new Bluetooth LE client adaptor given an address -func NewAdaptor(address string) *Adaptor { - return &Adaptor{ - name: gobot.DefaultName("BLEClient"), - address: address, - AdapterName: "default", - connected: false, - withoutResponses: false, - characteristics: make(map[string]bluetooth.DeviceCharacteristic), +// NewAdaptor returns a new Adaptor given an identifier. The identifier can be the address or the name. +// +// Supported options: +// +// "WithAdaptorDebug" +// "WithAdaptorScanTimeout" +func NewAdaptor(identifier string, opts ...optionApplier) *Adaptor { + cfg := configuration{ + scanTimeout: 10 * time.Minute, + sleepAfterDisconnect: 500 * time.Millisecond, + } + + a := Adaptor{ + name: gobot.DefaultName("BLEClient"), + identifier: identifier, + cfg: &cfg, + characteristics: make(map[string]bluetoothExtCharacteristicer), + btAdptCreator: newBtAdapter, + mutex: &sync.Mutex{}, + } + + for _, o := range opts { + o.apply(a.cfg) } + + return &a +} + +// WithDebug switch on some debug messages. +func WithDebug() debugOption { + return debugOption(true) } -// Name returns the name for the adaptor -func (a *Adaptor) Name() string { return a.name } +// WithScanTimeout substitute the default scan timeout of 10 min. +func WithScanTimeout(timeout time.Duration) scanTimeoutOption { + return scanTimeoutOption(timeout) +} + +// Name returns the name for the adaptor and after the connection is done, the name of the device +func (a *Adaptor) Name() string { + if a.btDevice != nil { + return a.btDevice.name() + } + return a.name +} // SetName sets the name for the adaptor func (a *Adaptor) SetName(n string) { a.name = n } -// Address returns the Bluetooth LE address for the adaptor -func (a *Adaptor) Address() string { return a.address } +// Address returns the Bluetooth LE address of the device if connected, otherwise the identifier +func (a *Adaptor) Address() string { + if a.btDevice != nil { + return a.btDevice.address() + } + + return a.identifier +} + +// RSSI returns the Bluetooth LE RSSI value at the moment of connecting the adaptor +func (a *Adaptor) RSSI() int { return a.rssi } // WithoutResponses sets if the adaptor should expect responses after -// writing characteristics for this device -func (a *Adaptor) WithoutResponses(use bool) { a.withoutResponses = use } +// writing characteristics for this device (has no effect at the moment). +func (a *Adaptor) WithoutResponses(bool) {} -// Connect initiates a connection to the BLE peripheral. Returns true on successful connection. +// Connect initiates a connection to the BLE peripheral. func (a *Adaptor) Connect() error { - bleMutex.Lock() - defer bleMutex.Unlock() + a.mutex.Lock() + defer a.mutex.Unlock() var err error - // enable adaptor - a.adpt, err = getBLEAdapter(a.AdapterName) - if err != nil { - return fmt.Errorf("can't get adapter %s: %w", a.AdapterName, err) - } - // handle address - a.addr.Set(a.Address()) + if a.cfg.debug { + fmt.Println("[Connect]: enable adaptor...") + } - // scan for the address - ch := make(chan bluetooth.ScanResult, 1) - err = a.adpt.Scan(func(adapter *bluetooth.Adapter, result bluetooth.ScanResult) { - if result.Address.String() == a.Address() { - if err := a.adpt.StopScan(); err != nil { - panic(err) - } - a.SetName(result.LocalName()) - ch <- result + // for re-connect, the adapter is already known + if a.btAdpt == nil { + a.btAdpt = a.btAdptCreator(bluetooth.DefaultAdapter, a.cfg.debug) + if err := a.btAdpt.enable(); err != nil { + return fmt.Errorf("can't get adapter default: %w", err) } - }) + } + + if a.cfg.debug { + fmt.Printf("[Connect]: scan %s for the identifier '%s'...\n", a.cfg.scanTimeout, a.identifier) + } + result, err := a.btAdpt.scan(a.identifier, a.cfg.scanTimeout) if err != nil { return err } - // wait to connect to peripheral device - result := <-ch - a.device, err = a.adpt.Connect(result.Address, bluetooth.ConnectionParams{}) + if a.cfg.debug { + fmt.Printf("[Connect]: connect to peripheral device with address %s...\n", result.Address) + } + + dev, err := a.btAdpt.connect(result.Address, result.LocalName()) if err != nil { return err } - // get all services/characteristics - srvcs, err := a.device.DiscoverServices(nil) + a.rssi = int(result.RSSI) + a.btDevice = dev + + if a.cfg.debug { + fmt.Println("[Connect]: get all services/characteristics...") + } + services, err := a.btDevice.discoverServices(nil) if err != nil { return err } - for _, srvc := range srvcs { - chars, err := srvc.DiscoverCharacteristics(nil) + for _, service := range services { + if a.cfg.debug { + fmt.Printf("[Connect]: service found: %s\n", service) + } + chars, err := service.DiscoverCharacteristics(nil) if err != nil { log.Println(err) continue } for _, char := range chars { - a.characteristics[char.UUID().String()] = char + if a.cfg.debug { + fmt.Printf("[Connect]: characteristic found: %s\n", char) + } + c := char // to prevent implicit memory aliasing in for loop, before go 1.22 + a.characteristics[char.UUID().String()] = &c } } + if a.cfg.debug { + fmt.Println("[Connect]: connected") + } a.connected = true return nil } // Reconnect attempts to reconnect to the BLE peripheral. If it has an active connection // it will first close that connection and then establish a new connection. -// Returns true on Successful reconnection func (a *Adaptor) Reconnect() error { if a.connected { if err := a.Disconnect(); err != nil { @@ -126,10 +182,17 @@ func (a *Adaptor) Reconnect() error { return a.Connect() } -// Disconnect terminates the connection to the BLE peripheral. Returns true on successful disconnect. +// Disconnect terminates the connection to the BLE peripheral. func (a *Adaptor) Disconnect() error { - err := a.device.Disconnect() - time.Sleep(500 * time.Millisecond) + if a.cfg.debug { + fmt.Println("[Disconnect]: disconnect...") + } + err := a.btDevice.disconnect() + time.Sleep(a.cfg.sleepAfterDisconnect) + a.connected = false + if a.cfg.debug { + fmt.Println("[Disconnect]: disconnected") + } return err } @@ -138,74 +201,59 @@ func (a *Adaptor) Finalize() error { return a.Disconnect() } -// ReadCharacteristic returns bytes from the BLE device for the -// requested characteristic uuid +// ReadCharacteristic returns bytes from the BLE device for the requested characteristic UUID. +// The UUID can be given as 16-bit or 128-bit (with or without dashes) value. func (a *Adaptor) ReadCharacteristic(cUUID string) ([]byte, error) { if !a.connected { - return nil, fmt.Errorf("Cannot read from BLE device until connected") + return nil, fmt.Errorf("cannot read from BLE device until connected") } - cUUID = convertUUID(cUUID) + cUUID, err := convertUUID(cUUID) + if err != nil { + return nil, err + } - if char, ok := a.characteristics[cUUID]; ok { - buf := make([]byte, 255) - n, err := char.Read(buf) - if err != nil { - return nil, err - } - return buf[:n], nil + if chara, ok := a.characteristics[cUUID]; ok { + return readFromCharacteristic(chara) } - return nil, fmt.Errorf("Unknown characteristic: %s", cUUID) + return nil, fmt.Errorf("unknown characteristic: %s", cUUID) } -// WriteCharacteristic writes bytes to the BLE device for the -// requested service and characteristic +// WriteCharacteristic writes bytes to the BLE device for the requested characteristic UUID. +// The UUID can be given as 16-bit or 128-bit (with or without dashes) value. func (a *Adaptor) WriteCharacteristic(cUUID string, data []byte) error { if !a.connected { - return fmt.Errorf("Cannot write to BLE device until connected") + return fmt.Errorf("cannot write to BLE device until connected") } - cUUID = convertUUID(cUUID) + cUUID, err := convertUUID(cUUID) + if err != nil { + return err + } - if char, ok := a.characteristics[cUUID]; ok { - _, err := char.WriteWithoutResponse(data) - if err != nil { - return err - } - return nil + if chara, ok := a.characteristics[cUUID]; ok { + return writeToCharacteristicWithoutResponse(chara, data) } - return fmt.Errorf("Unknown characteristic: %s", cUUID) + return fmt.Errorf("unknown characteristic: %s", cUUID) } -// Subscribe subscribes to notifications from the BLE device for the -// requested service and characteristic -func (a *Adaptor) Subscribe(cUUID string, f func([]byte)) error { +// Subscribe subscribes to notifications from the BLE device for the requested characteristic UUID. +// The UUID can be given as 16-bit or 128-bit (with or without dashes) value. +func (a *Adaptor) Subscribe(cUUID string, f func(data []byte)) error { if !a.connected { - return fmt.Errorf("Cannot subscribe to BLE device until connected") - } - - cUUID = convertUUID(cUUID) - - if char, ok := a.characteristics[cUUID]; ok { - return char.EnableNotifications(f) + return fmt.Errorf("cannot subscribe to BLE device until connected") } - return fmt.Errorf("Unknown characteristic: %s", cUUID) -} - -// getBLEAdapter is singleton for bluetooth adapter connection -func getBLEAdapter(impl string) (*bluetooth.Adapter, error) { //nolint:unparam // TODO: impl is unused, maybe an error - if currentAdapter != nil { - return currentAdapter, nil + cUUID, err := convertUUID(cUUID) + if err != nil { + return err } - currentAdapter = bluetooth.DefaultAdapter - err := currentAdapter.Enable() - if err != nil { - return nil, err + if chara, ok := a.characteristics[cUUID]; ok { + return enableNotificationsForCharacteristic(chara, f) } - return currentAdapter, nil + return fmt.Errorf("unknown characteristic: %s", cUUID) } diff --git a/platforms/bleclient/ble_client_adaptor_options.go b/platforms/bleclient/ble_client_adaptor_options.go new file mode 100644 index 000000000..91e924789 --- /dev/null +++ b/platforms/bleclient/ble_client_adaptor_options.go @@ -0,0 +1,30 @@ +package bleclient + +import "time" + +// optionApplier needs to be implemented by each configurable option type +type optionApplier interface { + apply(cfg *configuration) +} + +// debugOption is the type for applying the debug switch on or off. +type debugOption bool + +// scanTimeoutOption is the type for applying another timeout than the default 10 min. +type scanTimeoutOption time.Duration + +func (o debugOption) String() string { + return "debug option for BLE client adaptors" +} + +func (o scanTimeoutOption) String() string { + return "scan timeout option for BLE client adaptors" +} + +func (o debugOption) apply(cfg *configuration) { + cfg.debug = bool(o) +} + +func (o scanTimeoutOption) apply(cfg *configuration) { + cfg.scanTimeout = time.Duration(o) +} diff --git a/platforms/bleclient/ble_client_adaptor_options_test.go b/platforms/bleclient/ble_client_adaptor_options_test.go new file mode 100644 index 000000000..462ae21e3 --- /dev/null +++ b/platforms/bleclient/ble_client_adaptor_options_test.go @@ -0,0 +1,27 @@ +package bleclient + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestWithDebug(t *testing.T) { + // This is a general test, that options are applied by using the WithDebug() option. + // All other configuration options can also be tested by With..(val).apply(cfg). + // arrange & act + a := NewAdaptor("address", WithDebug()) + // assert + assert.True(t, a.cfg.debug) +} + +func TestWithScanTimeout(t *testing.T) { + // arrange + newTimeout := 2 * time.Second + cfg := &configuration{scanTimeout: 10 * time.Second} + // act + WithScanTimeout(newTimeout).apply(cfg) + // assert + assert.Equal(t, newTimeout, cfg.scanTimeout) +} diff --git a/platforms/bleclient/ble_client_adaptor_test.go b/platforms/bleclient/ble_client_adaptor_test.go index 2364e9aa7..614c6a04c 100644 --- a/platforms/bleclient/ble_client_adaptor_test.go +++ b/platforms/bleclient/ble_client_adaptor_test.go @@ -3,8 +3,10 @@ package bleclient import ( "strings" "testing" + "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -25,3 +27,381 @@ func TestName(t *testing.T) { a.SetName("awesome") assert.Equal(t, "awesome", a.Name()) } + +func TestConnect(t *testing.T) { + const ( + scanTimeout = 5 * time.Millisecond + deviceName = "hello" + deviceAddress = "11:22:44:AA:BB:CC" + rssi = 56 + ) + tests := map[string]struct { + identifier string + extAdapter *btTestAdapter + extDevice *btTestDevice + wantAddress string + wantName string + wantErr string + }{ + "connect_by_address": { + identifier: deviceAddress, + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + rssi: rssi, + payload: &btTestPayload{name: deviceName}, + }, + extDevice: &btTestDevice{}, + wantAddress: deviceAddress, + wantName: deviceName, + }, + "connect_by_name": { + identifier: deviceName, + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + rssi: rssi, + payload: &btTestPayload{name: deviceName}, + }, + extDevice: &btTestDevice{}, + wantAddress: deviceAddress, + wantName: deviceName, + }, + "error_enable": { + extAdapter: &btTestAdapter{ + simulateEnableErr: true, + }, + wantName: "BLEClient", + wantErr: "can't get adapter default: adapter enable error", + }, + "error_scan": { + extAdapter: &btTestAdapter{ + simulateScanErr: true, + }, + wantName: "BLEClient", + wantErr: "scan error", + }, + "error_stop_scan": { + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + payload: &btTestPayload{}, + simulateStopScanErr: true, + }, + wantName: "BLEClient", + wantErr: "stop scan error", + }, + "error_timeout_long_delay": { + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + payload: &btTestPayload{}, + scanDelay: 2 * scanTimeout, + }, + wantName: "BLEClient", + wantErr: "scan timeout (5ms) elapsed", + }, + "error_timeout_bad_identifier": { + identifier: "bad_identifier", + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + payload: &btTestPayload{}, + }, + wantAddress: "bad_identifier", + wantName: "BLEClient", + wantErr: "scan timeout (5ms) elapsed", + }, + "error_connect": { + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + payload: &btTestPayload{}, + simulateConnectErr: true, + }, + wantName: "BLEClient", + wantErr: "adapter connect error", + }, + "error_discovery_services": { + identifier: "disco_err", + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + payload: &btTestPayload{name: "disco_err"}, + }, + extDevice: &btTestDevice{ + simulateDiscoverServicesErr: true, + }, + wantAddress: deviceAddress, + wantName: "disco_err", + wantErr: "device discover services error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := NewAdaptor(tc.identifier) + btdc := func(_ bluetoothExtDevicer, address, name string) *btDevice { + return &btDevice{extDevice: tc.extDevice, devAddress: address, devName: name} + } + btac := func(bluetoothExtAdapterer, bool) *btAdapter { + return &btAdapter{extAdapter: tc.extAdapter, btDeviceCreator: btdc} + } + a.btAdptCreator = btac + a.cfg.scanTimeout = scanTimeout // to speed up test + // act + err := a.Connect() + // assert + if tc.wantErr == "" { + require.NoError(t, err) + assert.Equal(t, tc.wantName, a.Name()) + assert.Equal(t, tc.wantAddress, a.Address()) + assert.Equal(t, rssi, a.RSSI()) + assert.True(t, a.connected) + } else { + require.ErrorContains(t, err, tc.wantErr) + assert.Contains(t, a.Name(), tc.wantName) + assert.Equal(t, tc.wantAddress, a.Address()) + assert.False(t, a.connected) + } + }) + } +} + +func TestReconnect(t *testing.T) { + const ( + scanTimeout = 5 * time.Millisecond + deviceName = "hello" + deviceAddress = "11:22:44:AA:BB:CC" + rssi = 56 + ) + tests := map[string]struct { + extAdapter *btTestAdapter + extDevice *btTestDevice + wasConnected bool + wantErr string + }{ + "reconnect_not_connected": { + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + rssi: rssi, + payload: &btTestPayload{name: deviceName}, + }, + extDevice: &btTestDevice{}, + }, + "reconnect_was_connected": { + extAdapter: &btTestAdapter{ + deviceAddress: deviceAddress, + rssi: rssi, + payload: &btTestPayload{name: deviceName}, + }, + extDevice: &btTestDevice{}, + wasConnected: true, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := NewAdaptor(deviceAddress) + btdc := func(_ bluetoothExtDevicer, address, name string) *btDevice { + return &btDevice{extDevice: tc.extDevice, devAddress: address, devName: name} + } + a.btAdpt = &btAdapter{extAdapter: tc.extAdapter, btDeviceCreator: btdc} + a.cfg.scanTimeout = scanTimeout // to speed up test in case of errors + a.cfg.sleepAfterDisconnect = 0 // to speed up test + if tc.wasConnected { + a.btDevice = btdc(nil, "", "") + a.connected = tc.wasConnected + } + // act + err := a.Reconnect() + // assert + if tc.wantErr == "" { + require.NoError(t, err) + assert.Equal(t, rssi, a.RSSI()) + } else { + require.ErrorContains(t, err, tc.wantErr) + } + assert.True(t, a.connected) + }) + } +} + +func TestFinalize(t *testing.T) { + // this also tests Disconnect() + tests := map[string]struct { + extDevice *btTestDevice + wantErr string + }{ + "disconnect": { + extDevice: &btTestDevice{}, + }, + "error_disconnect": { + extDevice: &btTestDevice{ + simulateDisconnectErr: true, + }, + wantErr: "device disconnect error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := NewAdaptor("") + a.cfg.sleepAfterDisconnect = 0 // to speed up test + a.btDevice = &btDevice{extDevice: tc.extDevice} + // act + err := a.Finalize() + // assert + if tc.wantErr == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tc.wantErr) + } + assert.False(t, a.connected) + }) + } +} + +func TestReadCharacteristic(t *testing.T) { + const uuid = "00001234-0000-1000-8000-00805f9b34fb" + tests := map[string]struct { + inUUID string + chara *btTestChara + notConnected bool + want []byte + wantErr string + }{ + "read_ok": { + inUUID: uuid, + chara: &btTestChara{readData: []byte{1, 2, 3}}, + want: []byte{1, 2, 3}, + }, + "error_not_connected": { + notConnected: true, + wantErr: "cannot read from BLE device until connected", + }, + "error_bad_chara": { + inUUID: "gag1", + wantErr: "'gag1' is not a valid 16-bit Bluetooth UUID", + }, + "error_unknown_chara": { + inUUID: uuid, + wantErr: "unknown characteristic: 00001234-0000-1000-8000-00805f9b34fb", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := NewAdaptor("") + if tc.chara != nil { + a.characteristics[uuid] = tc.chara + } + a.connected = !tc.notConnected + // act + got, err := a.ReadCharacteristic(tc.inUUID) + // assert + if tc.wantErr == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tc.wantErr) + } + assert.Equal(t, tc.want, got) + }) + } +} + +func TestWriteCharacteristic(t *testing.T) { + const uuid = "00004321-0000-1000-8000-00805f9b34fb" + tests := map[string]struct { + inUUID string + inData []byte + notConnected bool + chara *btTestChara + want []byte + wantErr string + }{ + "write_ok": { + inUUID: uuid, + inData: []byte{3, 2, 1}, + chara: &btTestChara{}, + want: []byte{3, 2, 1}, + }, + "error_not_connected": { + notConnected: true, + wantErr: "cannot write to BLE device until connected", + }, + "error_bad_chara": { + inUUID: "gag2", + wantErr: "'gag2' is not a valid 16-bit Bluetooth UUID", + }, + "error_unknown_chara": { + inUUID: uuid, + wantErr: "unknown characteristic: 00004321-0000-1000-8000-00805f9b34fb", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := NewAdaptor("") + if tc.chara != nil { + a.characteristics[uuid] = tc.chara + } + a.connected = !tc.notConnected + // act + err := a.WriteCharacteristic(tc.inUUID, tc.inData) + // assert + if tc.wantErr == "" { + require.NoError(t, err) + assert.Equal(t, tc.want, tc.chara.writtenData) + } else { + require.ErrorContains(t, err, tc.wantErr) + } + }) + } +} + +func TestSubscribe(t *testing.T) { + const uuid = "00004321-0000-1000-8000-00805f9b34fb" + tests := map[string]struct { + inUUID string + notConnected bool + chara *btTestChara + want []byte + wantErr string + }{ + "subscribe_ok": { + inUUID: uuid, + chara: &btTestChara{}, + want: []byte{3, 4, 5}, + }, + "error_not_connected": { + notConnected: true, + wantErr: "cannot subscribe to BLE device until connected", + }, + "error_bad_chara": { + inUUID: "gag2", + wantErr: "'gag2' is not a valid 16-bit Bluetooth UUID", + }, + "error_unknown_chara": { + inUUID: uuid, + wantErr: "unknown characteristic: 00004321-0000-1000-8000-00805f9b34fb", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a := NewAdaptor("") + if tc.chara != nil { + a.characteristics[uuid] = tc.chara + } + a.connected = !tc.notConnected + var got []byte + notificationFunc := func(data []byte) { + got = append(got, data...) + } + // act + err := a.Subscribe(tc.inUUID, notificationFunc) + // assert + if tc.wantErr == "" { + require.NoError(t, err) + tc.chara.notificationFunc([]byte{3, 4, 5}) + } else { + require.ErrorContains(t, err, tc.wantErr) + } + assert.Equal(t, tc.want, got) + }) + } +} diff --git a/platforms/bleclient/btwrapper.go b/platforms/bleclient/btwrapper.go new file mode 100644 index 000000000..011526a31 --- /dev/null +++ b/platforms/bleclient/btwrapper.go @@ -0,0 +1,154 @@ +package bleclient + +import ( + "fmt" + "time" + + "tinygo.org/x/bluetooth" +) + +// bluetoothExtDevicer is the interface usually implemented by bluetooth.Device +type bluetoothExtDevicer interface { + DiscoverServices(uuids []bluetooth.UUID) ([]bluetooth.DeviceService, error) + Disconnect() error +} + +// bluetoothExtAdapterer is the interface usually implemented by bluetooth.Adapter +type bluetoothExtAdapterer interface { + Enable() error + Scan(callback func(*bluetooth.Adapter, bluetooth.ScanResult)) error + StopScan() error + Connect(address bluetooth.Address, params bluetooth.ConnectionParams) (*bluetooth.Device, error) +} + +type bluetoothExtCharacteristicer interface { + Read(data []byte) (int, error) + WriteWithoutResponse(p []byte) (n int, err error) + EnableNotifications(callback func(buf []byte)) error +} + +// btAdptCreatorFunc is just a convenience type, used in the BLE client to ensure testability +type btAdptCreatorFunc func(bluetoothExtAdapterer, bool) *btAdapter + +// btAdapter is the wrapper for an external adapter implementation +type btAdapter struct { + extAdapter bluetoothExtAdapterer + btDeviceCreator func(bluetoothExtDevicer, string, string) *btDevice + debug bool +} + +// newBtAdapter creates a new wrapper around the given external implementation +func newBtAdapter(a bluetoothExtAdapterer, debug bool) *btAdapter { + bta := btAdapter{ + extAdapter: a, + btDeviceCreator: newBtDevice, + debug: debug, + } + + return &bta +} + +// Enable configures the BLE stack. It must be called before any Bluetooth-related calls (unless otherwise indicated). +// It pass through the function of the external implementation. +func (bta *btAdapter) enable() error { + return bta.extAdapter.Enable() +} + +// StopScan stops any in-progress scan. It can be called from within a Scan callback to stop the current scan. +// If no scan is in progress, an error will be returned. +func (bta *btAdapter) stopScan() error { + return bta.extAdapter.StopScan() +} + +// Connect starts a connection attempt to the given peripheral device address. +// +// On Linux and Windows, the IsRandom part of the address is ignored. +func (bta *btAdapter) connect(address bluetooth.Address, devName string) (*btDevice, error) { + extDev, err := bta.extAdapter.Connect(address, bluetooth.ConnectionParams{}) + if err != nil { + return nil, err + } + + return bta.btDeviceCreator(extDev, address.String(), devName), nil +} + +// Scan starts a BLE scan for the given identifier (address or name). +func (bta *btAdapter) scan(identifier string, scanTimeout time.Duration) (*bluetooth.ScanResult, error) { + resultChan := make(chan bluetooth.ScanResult, 1) + errChan := make(chan error) + + go func() { + callback := func(_ *bluetooth.Adapter, result bluetooth.ScanResult) { + if bta.debug { + fmt.Printf("[scan result]: address: '%s', rssi: %d, name: '%s', manufacturer: %v\n", + result.Address, result.RSSI, result.LocalName(), result.ManufacturerData()) + } + if result.Address.String() == identifier || result.LocalName() == identifier { + resultChan <- result + } + } + err := bta.extAdapter.Scan(callback) + if err != nil { + errChan <- err + } + }() + + select { + case result := <-resultChan: + if err := bta.stopScan(); err != nil { + return nil, err + } + + return &result, nil + case err := <-errChan: + return nil, err + case <-time.After(scanTimeout): + _ = bta.stopScan() + return nil, fmt.Errorf("scan timeout (%s) elapsed", scanTimeout) + } +} + +// btDevice is the wrapper for an external device implementation +type btDevice struct { + extDevice bluetoothExtDevicer + devAddress string + devName string +} + +// newBtDevice creates a new wrapper around the given external implementation +func newBtDevice(d bluetoothExtDevicer, address, name string) *btDevice { + return &btDevice{extDevice: d, devAddress: address, devName: name} +} + +func (btd *btDevice) name() string { return btd.devName } + +func (btd *btDevice) address() string { return btd.devAddress } + +func (btd *btDevice) discoverServices(uuids []bluetooth.UUID) ([]bluetooth.DeviceService, error) { + return btd.extDevice.DiscoverServices(uuids) +} + +// Disconnect from the BLE device. This method is non-blocking and does not wait until the connection is fully gone. +func (btd *btDevice) disconnect() error { + return btd.extDevice.Disconnect() +} + +func readFromCharacteristic(chara bluetoothExtCharacteristicer) ([]byte, error) { + buf := make([]byte, 255) + n, err := chara.Read(buf) + if err != nil { + return nil, err + } + return buf[:n], nil +} + +func writeToCharacteristicWithoutResponse(chara bluetoothExtCharacteristicer, data []byte) error { + if _, err := chara.WriteWithoutResponse(data); err != nil { + return err + } + return nil +} + +func enableNotificationsForCharacteristic(chara bluetoothExtCharacteristicer, f func(data []byte)) error { + return chara.EnableNotifications(f) +} diff --git a/platforms/bleclient/helper_test.go b/platforms/bleclient/helper_test.go new file mode 100644 index 000000000..459d9b412 --- /dev/null +++ b/platforms/bleclient/helper_test.go @@ -0,0 +1,118 @@ +package bleclient + +import ( + "fmt" + "time" + + "tinygo.org/x/bluetooth" +) + +type btTestAdapter struct { + deviceAddress string + rssi int16 + scanDelay time.Duration + payload *btTestPayload + simulateEnableErr bool + simulateScanErr bool + simulateStopScanErr bool + simulateConnectErr bool +} + +func (bta *btTestAdapter) Enable() error { + if bta.simulateEnableErr { + return fmt.Errorf("adapter enable error") + } + + return nil +} + +func (bta *btTestAdapter) Scan(callback func(*bluetooth.Adapter, bluetooth.ScanResult)) error { + if bta.simulateScanErr { + return fmt.Errorf("adapter scan error") + } + + devAddr, err := bluetooth.ParseMAC(bta.deviceAddress) + if err != nil { + // normally this error should not happen in test + return err + } + time.Sleep(bta.scanDelay) + + a := bluetooth.Address{MACAddress: bluetooth.MACAddress{MAC: devAddr}} + r := bluetooth.ScanResult{Address: a, RSSI: bta.rssi, AdvertisementPayload: bta.payload} + callback(nil, r) + + return nil +} + +func (bta *btTestAdapter) StopScan() error { + if bta.simulateStopScanErr { + return fmt.Errorf("adapter stop scan error") + } + + return nil +} + +func (bta *btTestAdapter) Connect(_ bluetooth.Address, _ bluetooth.ConnectionParams) (*bluetooth.Device, error) { + if bta.simulateConnectErr { + return nil, fmt.Errorf("adapter connect error") + } + + //nolint:nilnil // for this test we can not return a *bluetooth.Device + return nil, nil +} + +type btTestPayload struct { + name string +} + +func (ptp *btTestPayload) LocalName() string { return ptp.name } + +func (*btTestPayload) HasServiceUUID(bluetooth.UUID) bool { return true } + +func (*btTestPayload) Bytes() []byte { return nil } + +func (*btTestPayload) ManufacturerData() map[uint16][]byte { return nil } + +type btTestDevice struct { + simulateDiscoverServicesErr bool + simulateDisconnectErr bool +} + +func (btd *btTestDevice) DiscoverServices(_ []bluetooth.UUID) ([]bluetooth.DeviceService, error) { + if btd.simulateDiscoverServicesErr { + return nil, fmt.Errorf("device discover services error") + } + + // for this test we can not return any []bluetooth.DeviceService + return nil, nil +} + +func (btd *btTestDevice) Disconnect() error { + if btd.simulateDisconnectErr { + return fmt.Errorf("device disconnect error") + } + + return nil +} + +type btTestChara struct { + readData []byte + writtenData []byte + notificationFunc func(buf []byte) +} + +func (btc *btTestChara) Read(data []byte) (int, error) { + copy(data, btc.readData) + return len(btc.readData), nil +} + +func (btc *btTestChara) WriteWithoutResponse(data []byte) (int, error) { + btc.writtenData = append(btc.writtenData, data...) + return len(data), nil +} + +func (btc *btTestChara) EnableNotifications(callback func(buf []byte)) error { + btc.notificationFunc = callback + return nil +} diff --git a/platforms/bleclient/uuid.go b/platforms/bleclient/uuid.go index bf120fbe7..ddec347a5 100644 --- a/platforms/bleclient/uuid.go +++ b/platforms/bleclient/uuid.go @@ -3,28 +3,38 @@ package bleclient import ( "fmt" "strconv" + "strings" "tinygo.org/x/bluetooth" ) -func convertUUID(cUUID string) string { +// convertUUID creates a common 128 bit UUID xxxxyyyy-0000-1000-8000-00805f9b34fb from a short 16 bit UUID by replacing +// the yyyy fields. If the given ID is still an arbitrary long one but without dashes, the dashes will be added. +// Additionally some simple checks for the resulting UUID will be done. +func convertUUID(cUUID string) (string, error) { + var uuid string switch len(cUUID) { case 4: - // convert to full uuid from "22bb" - uid, e := strconv.ParseUint("0x"+cUUID, 0, 16) - if e != nil { - return "" + uid, err := strconv.ParseUint(cUUID, 16, 16) + if err != nil { + return "", fmt.Errorf("'%s' is not a valid 16-bit Bluetooth UUID: %v", cUUID, err) } - - uuid := bluetooth.New16BitUUID(uint16(uid)) - return uuid.String() - + return bluetooth.New16BitUUID(uint16(uid)).String(), nil case 32: - // convert "22bb746f2bbd75542d6f726568705327" - // to "22bb746f-2bbd-7554-2d6f-726568705327" - return fmt.Sprintf("%s-%s-%s-%s-%s", cUUID[:8], cUUID[8:12], cUUID[12:16], cUUID[16:20], - cUUID[20:32]) + // convert "22bb746f2bbd75542d6f726568705327" to "22bb746f-2bbd-7554-2d6f-726568705327" + uuid = fmt.Sprintf("%s-%s-%s-%s-%s", cUUID[:8], cUUID[8:12], cUUID[12:16], cUUID[16:20], cUUID[20:]) + case 36: + uuid = cUUID + } + + if uuid != "" { + id := strings.ReplaceAll(uuid, "-", "") + _, errHigh := strconv.ParseUint(id[:16], 16, 64) + _, errLow := strconv.ParseUint(id[16:], 16, 64) + if errHigh == nil && errLow == nil { + return uuid, nil + } } - return cUUID + return "", fmt.Errorf("'%s' is not a valid 128-bit Bluetooth UUID", cUUID) } diff --git a/platforms/bleclient/uuid_test.go b/platforms/bleclient/uuid_test.go new file mode 100644 index 000000000..033b9276a --- /dev/null +++ b/platforms/bleclient/uuid_test.go @@ -0,0 +1,58 @@ +package bleclient + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_convertUUID(t *testing.T) { + tests := map[string]struct { + input string + want string + wantErr string + }{ + "32_bit": { + input: "12345678-4321-1234-4321-123456789abc", + want: "12345678-4321-1234-4321-123456789abc", + }, + "16_bit": { + input: "12f4", + want: "000012f4-0000-1000-8000-00805f9b34fb", + }, + "32_bit_without_dashes": { + input: "0123456789abcdef012345678abcdefc", + want: "01234567-89ab-cdef-0123-45678abcdefc", + }, + "error_bad_chacters_16bit": { + input: "123g", + wantErr: "'123g' is not a valid 16-bit Bluetooth UUID", + }, + "error_bad_chacters_32bit": { + input: "12345678-4321-1234-4321-123456789abg", + wantErr: "'12345678-4321-1234-4321-123456789abg' is not a valid 128-bit Bluetooth UUID", + }, + "error_too_long": { + input: "12345678-4321-1234-4321-123456789abcd", + wantErr: "'12345678-4321-1234-4321-123456789abcd' is not a valid 128-bit Bluetooth UUID", + }, + "error_invalid": { + input: "12345", + wantErr: "'12345' is not a valid 128-bit Bluetooth UUID", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // act + got, err := convertUUID(tc.input) + // assert + if tc.wantErr == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tc.wantErr) + } + assert.Equal(t, tc.want, got) + }) + } +} From e2b710bfe7fdcbcf5b8c20b8a1794cd8c5a87ccc Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Mon, 12 Feb 2024 16:27:08 +0100 Subject: [PATCH 44/57] neurosky: use serialport adaptor and move driver to drivers/serial (#1061) --- README.md | 7 +- doc.go | 4 +- drivers/MIGRATION.md | 41 +++- drivers/ble/sphero/sphero_bb8_driver.go | 6 +- drivers/ble/sphero/sphero_ollie_driver.go | 38 +-- .../ble/sphero/sphero_ollie_driver_test.go | 6 +- drivers/ble/sphero/sphero_sprkplus_driver.go | 6 +- .../spherocommon.go} | 2 +- .../spherocommon_packets.go} | 2 +- .../spherocommon_test.go} | 2 +- drivers/serial/README.md | 1 + drivers/serial/helpers_test.go | 28 --- drivers/serial/neurosky/LICENSE | 13 + drivers/serial/neurosky/mindwave_driver.go | 196 ++++++++++++++++ .../serial/neurosky/mindwave_driver_test.go | 60 ++--- drivers/serial/serial_driver.go | 42 ++-- drivers/serial/serial_driver_test.go | 21 +- drivers/serial/sphero/LICENSE | 13 + drivers/serial/{ => sphero}/sphero_driver.go | 92 ++++---- .../serial/{ => sphero}/sphero_driver_test.go | 29 ++- drivers/serial/testutil/testutil.go | 62 +++++ drivers/spi/spi_driver.go | 2 +- examples/leap_sphero.go | 4 +- .../{neurosky.go => serialport_mindwave.go} | 9 +- ...{serial_sphero.go => serialport_sphero.go} | 12 +- ...sphero_api.go => serialport_sphero_api.go} | 4 +- ...on.go => serialport_sphero_calibration.go} | 4 +- ...onways.go => serialport_sphero_conways.go} | 9 +- ...hero_dpad.go => serialport_sphero_dpad.go} | 4 +- ..._master.go => serialport_sphero_master.go} | 6 +- ...tiple.go => serialport_sphero_multiple.go} | 7 +- .../{helper_test.go => helpers_test.go} | 0 platforms/digispark/digispark_adaptor.go | 4 +- platforms/firmata/firmata_adaptor.go | 6 +- platforms/intel-iot/edison/edison_adaptor.go | 4 +- platforms/intel-iot/joule/joule_adaptor.go | 4 +- platforms/jetson/jetson_adaptor.go | 4 +- platforms/joystick/joystick_adaptor.go | 4 +- platforms/mqtt/mqtt_adaptor.go | 4 +- platforms/neurosky/README.md | 81 +------ platforms/neurosky/doc.go | 70 ------ platforms/neurosky/neurosky_adaptor.go | 52 ---- platforms/neurosky/neurosky_adaptor_test.go | 94 -------- platforms/neurosky/neurosky_driver.go | 222 ------------------ platforms/parrot/bebop/bebop_adaptor.go | 4 +- platforms/raspi/raspi_adaptor.go | 4 +- platforms/rockpi/rockpi_adaptor.go | 4 +- platforms/serialport/README.md | 3 +- platforms/serialport/adaptor.go | 80 +++++-- platforms/serialport/adaptor_options.go | 28 +++ platforms/serialport/adaptor_options_test.go | 27 +++ platforms/serialport/adaptor_test.go | 163 ++++++++----- platforms/serialport/helpers_test.go | 36 +++ platforms/sphero/sphero/README.md | 2 +- 54 files changed, 812 insertions(+), 820 deletions(-) rename drivers/common/{sphero/sphero_driver.go => spherocommon/spherocommon.go} (97%) rename drivers/common/{sphero/sphero_packets.go => spherocommon/spherocommon_packets.go} (99%) rename drivers/common/{sphero/sphero_driver_test.go => spherocommon/spherocommon_test.go} (94%) delete mode 100644 drivers/serial/helpers_test.go create mode 100644 drivers/serial/neurosky/LICENSE create mode 100644 drivers/serial/neurosky/mindwave_driver.go rename platforms/neurosky/neurosky_driver_test.go => drivers/serial/neurosky/mindwave_driver_test.go (72%) create mode 100644 drivers/serial/sphero/LICENSE rename drivers/serial/{ => sphero}/sphero_driver.go (82%) rename drivers/serial/{ => sphero}/sphero_driver_test.go (80%) create mode 100644 drivers/serial/testutil/testutil.go rename examples/{neurosky.go => serialport_mindwave.go} (81%) rename examples/{serial_sphero.go => serialport_sphero.go} (68%) rename examples/{serial_sphero_api.go => serialport_sphero_api.go} (89%) rename examples/{serial_sphero_calibration.go => serialport_sphero_calibration.go} (93%) rename examples/{serial_sphero_conways.go => serialport_sphero_conways.go} (88%) rename examples/{serial_sphero_dpad.go => serialport_sphero_dpad.go} (91%) rename examples/{serial_sphero_master.go => serialport_sphero_master.go} (82%) rename examples/{serial_sphero_multiple.go => serialport_sphero_multiple.go} (82%) rename platforms/bleclient/{helper_test.go => helpers_test.go} (100%) delete mode 100644 platforms/neurosky/doc.go delete mode 100644 platforms/neurosky/neurosky_adaptor.go delete mode 100644 platforms/neurosky/neurosky_adaptor_test.go delete mode 100644 platforms/neurosky/neurosky_driver.go create mode 100644 platforms/serialport/adaptor_options.go create mode 100644 platforms/serialport/adaptor_options_test.go create mode 100644 platforms/serialport/helpers_test.go diff --git a/README.md b/README.md index 4d12f82bb..0af24c298 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ import ( func main() { adaptor := serialport.NewAdaptor("/dev/rfcomm0") - driver := serial.NewSpheroDriver(adaptor) + driver := sphero.NewSpheroDriver(adaptor) work := func() { gobot.Every(3*time.Second, func() { @@ -179,14 +179,14 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" "gobot.io/x/gobot/v2/drivers/serial" "gobot.io/x/gobot/v2/platforms/serialport" ) func NewSwarmBot(port string) *gobot.Robot { spheroAdaptor := serialport.NewAdaptor(port) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero" + port)) + spheroDriver := sphero.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero" + port)) work := func() { spheroDriver.Stop() @@ -390,6 +390,7 @@ the `gobot/drivers/serial` package: - [UART](https://en.wikipedia.org/wiki/Serial_port) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/serial) - Sphero: Sphero + - Neurosky: MindWave Support for devices that use Serial Peripheral Interface (SPI) have a shared set of drivers provided using the `gobot/drivers/spi` package: diff --git a/doc.go b/doc.go index 25a8731ab..b24ca6738 100644 --- a/doc.go +++ b/doc.go @@ -88,14 +88,14 @@ Finally, you can use Master Gobot to add the complete Gobot API or control swarm "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" "gobot.io/x/gobot/v2/drivers/serial" "gobot.io/x/gobot/v2/platforms/serialport" ) func NewSwarmBot(port string) *gobot.Robot { spheroAdaptor := serialport.NewAdaptor(port) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero" + port)) + spheroDriver := sphero.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero" + port)) work := func() { spheroDriver.Stop() diff --git a/drivers/MIGRATION.md b/drivers/MIGRATION.md index c0fa1a279..02b12da32 100644 --- a/drivers/MIGRATION.md +++ b/drivers/MIGRATION.md @@ -80,7 +80,7 @@ returned instead and the log output needs to be done at caller side. ### Sphero adaptor split off The Serial Based Sphero adaptor was split off into a generic serial adaptor and the driver part. With this, the imports -needs to be adjusted. In addition all events now have a postfix "Event", see below. +needs to be adjusted. In addition all events now have a suffix "Event", see below. ```go // old @@ -100,19 +100,54 @@ import( // new import( ... - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" "gobot.io/x/gobot/v2/drivers/serial" "gobot.io/x/gobot/v2/platforms/serialport" ... ) ... adaptor := serialport.NewAdaptor("/dev/rfcomm0") - spheroDriver := serial.NewSpheroDriver(adaptor) + spheroDriver := sphero.NewSpheroDriver(adaptor) ... _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { ... ``` +### Neurosky adaptor split off + +The Neurosky adaptor now us the generic serial adaptor. The driver part was moved. With this, the imports needs to be +adjusted. In addition all events now have a suffix "Event", see below. + +```go +// old +import( + ... + "gobot.io/x/gobot/v2/platforms/neurosky" + ... +) + +... + adaptor := neurosky.NewAdaptor("/dev/rfcomm0") + neuro := neurosky.NewDriver(adaptor) +... + _ = neuro.On(neurosky.Extended, func(data interface{}) { +... + +// new +import( + ... + "gobot.io/x/gobot/v2/drivers/serial/neurosky" + "gobot.io/x/gobot/v2/platforms/serialport" + ... +) +... + adaptor := serialport.NewAdaptor("/dev/rfcomm0", serialport.WithName("Neurosky"), serialport.WithBaudRate(57600)) + neuro := neurosky.NewMindWaveDriver(adaptor) +... + _ = neuro.On(neurosky.ExtendedEvent, func(data interface{}) { +... +``` + ## Switch from version 2.2.0 (gpio drivers affected) ### gpio.ButtonDriver, gpio.PIRMotionDriver: substitute parameter "v time.duration" diff --git a/drivers/ble/sphero/sphero_bb8_driver.go b/drivers/ble/sphero/sphero_bb8_driver.go index ee6f9088b..022359ac6 100644 --- a/drivers/ble/sphero/sphero_bb8_driver.go +++ b/drivers/ble/sphero/sphero_bb8_driver.go @@ -3,7 +3,7 @@ package sphero import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" ) // BB8Driver represents a Sphero BB-8 @@ -17,8 +17,8 @@ func NewBB8Driver(a gobot.BLEConnector, opts ...ble.OptionApplier) *BB8Driver { } // bb8DefaultCollisionConfig returns a CollisionConfig with sensible collision defaults -func bb8DefaultCollisionConfig() sphero.CollisionConfig { - return sphero.CollisionConfig{ +func bb8DefaultCollisionConfig() spherocommon.CollisionConfig { + return spherocommon.CollisionConfig{ Method: 0x01, Xt: 0x20, Yt: 0x20, diff --git a/drivers/ble/sphero/sphero_ollie_driver.go b/drivers/ble/sphero/sphero_ollie_driver.go index 81c2daf9b..cd521e597 100644 --- a/drivers/ble/sphero/sphero_ollie_driver.go +++ b/drivers/ble/sphero/sphero_ollie_driver.go @@ -8,7 +8,7 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" ) // MotorModes is used to configure the motor @@ -63,14 +63,14 @@ type Point2D struct { type OllieDriver struct { *ble.Driver gobot.Eventer - defaultCollisionConfig sphero.CollisionConfig + defaultCollisionConfig spherocommon.CollisionConfig seq uint8 collisionResponse []uint8 packetChannel chan *packet asyncBuffer []byte asyncMessage []byte locatorCallback func(p Point2D) - powerstateCallback func(p sphero.PowerStatePacket) + powerstateCallback func(p spherocommon.PowerStatePacket) } // NewOllieDriver creates a driver for a Sphero Ollie @@ -80,7 +80,7 @@ func NewOllieDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *OllieDrive func newOllieBaseDriver( a gobot.BLEConnector, name string, - dcc sphero.CollisionConfig, opts ...ble.OptionApplier, + dcc spherocommon.CollisionConfig, opts ...ble.OptionApplier, ) *OllieDriver { d := &OllieDriver{ defaultCollisionConfig: dcc, @@ -89,8 +89,8 @@ func newOllieBaseDriver( } d.Driver = ble.NewDriver(a, name, d.initialize, d.shutdown, opts...) - d.AddEvent(sphero.ErrorEvent) - d.AddEvent(sphero.CollisionEvent) + d.AddEvent(spherocommon.ErrorEvent) + d.AddEvent(spherocommon.CollisionEvent) return d } @@ -118,7 +118,7 @@ func (d *OllieDriver) Wake() error { } // ConfigureCollisionDetection configures the sensitivity of the detection. -func (d *OllieDriver) ConfigureCollisionDetection(cc sphero.CollisionConfig) { +func (d *OllieDriver) ConfigureCollisionDetection(cc spherocommon.CollisionConfig) { d.sendCraftPacket([]uint8{cc.Method, cc.Xt, cc.Yt, cc.Xs, cc.Ys, cc.Dead}, 0x02, 0x12) } @@ -130,7 +130,7 @@ func (d *OllieDriver) GetLocatorData(f func(p Point2D)) { } // GetPowerState calls the passed function with the Power State information from the sphero -func (d *OllieDriver) GetPowerState(f func(p sphero.PowerStatePacket)) { +func (d *OllieDriver) GetPowerState(f func(p spherocommon.PowerStatePacket)) { // CID 0x20 is the code for the power state d.sendCraftPacket([]uint8{}, 0x00, 0x20) d.powerstateCallback = f @@ -194,7 +194,7 @@ func (d *OllieDriver) Sleep() { } // SetDataStreamingConfig passes the config to the sphero to stream sensor data -func (d *OllieDriver) SetDataStreamingConfig(dsc sphero.DataStreamingConfig) error { +func (d *OllieDriver) SetDataStreamingConfig(dsc spherocommon.DataStreamingConfig) error { buf := new(bytes.Buffer) if err := binary.Write(buf, binary.BigEndian, dsc); err != nil { return err @@ -225,7 +225,7 @@ func (d *OllieDriver) initialize() error { packet := <-d.packetChannel err := d.writeCommand(packet) if err != nil { - d.Publish(d.Event(sphero.ErrorEvent), err) + d.Publish(d.Event(spherocommon.ErrorEvent), err) } } }() @@ -331,13 +331,13 @@ func (d *OllieDriver) handleDataStreaming(data []byte) { // data packet is the same as for the normal sphero, since the same communication api is used // only difference in communication is that the "newer" spheros use BLE for communications - var dataPacket sphero.DataStreamingPacket + var dataPacket spherocommon.DataStreamingPacket buffer := bytes.NewBuffer(data[5:]) // skip header if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { panic(err) } - d.Publish(sphero.SensorDataEvent, dataPacket) + d.Publish(spherocommon.SensorDataEvent, dataPacket) } func (d *OllieDriver) handleLocatorDetected(data []uint8) { @@ -368,7 +368,7 @@ func (d *OllieDriver) handleLocatorDetected(data []uint8) { } func (d *OllieDriver) handlePowerStateDetected(data []uint8) { - var dataPacket sphero.PowerStatePacket + var dataPacket spherocommon.PowerStatePacket buffer := bytes.NewBuffer(data[5:]) // skip header if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { panic(err) @@ -404,18 +404,18 @@ func (d *OllieDriver) handleCollisionDetected(data []uint8) { // confirm checksum size := len(d.collisionResponse) chk := d.collisionResponse[size-1] // last byte is checksum - if chk != sphero.CalculateChecksum(d.collisionResponse[2:size-1]) { + if chk != spherocommon.CalculateChecksum(d.collisionResponse[2:size-1]) { return } - var collision sphero.CollisionPacket + var collision spherocommon.CollisionPacket buffer := bytes.NewBuffer(d.collisionResponse[5:]) // skip header if err := binary.Read(buffer, binary.BigEndian, &collision); err != nil { panic(err) } d.collisionResponse = nil // clear the current response - d.Publish(sphero.CollisionEvent, collision) + d.Publish(spherocommon.CollisionEvent, collision) } func (d *OllieDriver) sendCraftPacket(body []uint8, did byte, cid byte) { @@ -430,15 +430,15 @@ func (d *OllieDriver) craftPacket(body []uint8, did byte, cid byte) *packet { packet := &packet{ body: body, header: hdr, - checksum: sphero.CalculateChecksum(buf[2:]), + checksum: spherocommon.CalculateChecksum(buf[2:]), } return packet } // ollieDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults -func ollieDefaultCollisionConfig() sphero.CollisionConfig { - return sphero.CollisionConfig{ +func ollieDefaultCollisionConfig() spherocommon.CollisionConfig { + return spherocommon.CollisionConfig{ Method: 0x01, Xt: 0x20, Yt: 0x20, diff --git a/drivers/ble/sphero/sphero_ollie_driver_test.go b/drivers/ble/sphero/sphero_ollie_driver_test.go index 671cd1758..1c06021d0 100644 --- a/drivers/ble/sphero/sphero_ollie_driver_test.go +++ b/drivers/ble/sphero/sphero_ollie_driver_test.go @@ -12,7 +12,7 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble" "gobot.io/x/gobot/v2/drivers/ble/testutil" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" ) var _ gobot.Driver = (*OllieDriver)(nil) @@ -82,12 +82,12 @@ func TestLocatorData(t *testing.T) { func TestDataStreaming(t *testing.T) { d := initTestOllieDriver() - err := d.SetDataStreamingConfig(sphero.DefaultDataStreamingConfig()) + err := d.SetDataStreamingConfig(spherocommon.DefaultDataStreamingConfig()) require.NoError(t, err) responseChan := make(chan bool) err = d.On("sensordata", func(data interface{}) { - cont := data.(sphero.DataStreamingPacket) + cont := data.(spherocommon.DataStreamingPacket) // fmt.Printf("got streaming packet: %+v \n", cont) assert.Equal(t, int16(10), cont.RawAccX) responseChan <- true diff --git a/drivers/ble/sphero/sphero_sprkplus_driver.go b/drivers/ble/sphero/sphero_sprkplus_driver.go index 75af9f310..4748b3ec6 100644 --- a/drivers/ble/sphero/sphero_sprkplus_driver.go +++ b/drivers/ble/sphero/sphero_sprkplus_driver.go @@ -3,7 +3,7 @@ package sphero import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/drivers/ble" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" ) // SPRKPlusDriver represents a Sphero SPRK+ @@ -17,8 +17,8 @@ func NewSPRKPlusDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *SPRKPlu } // sprkplusDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults -func sprkplusDefaultCollisionConfig() sphero.CollisionConfig { - return sphero.CollisionConfig{ +func sprkplusDefaultCollisionConfig() spherocommon.CollisionConfig { + return spherocommon.CollisionConfig{ Method: 0x01, Xt: 0x20, Yt: 0x20, diff --git a/drivers/common/sphero/sphero_driver.go b/drivers/common/spherocommon/spherocommon.go similarity index 97% rename from drivers/common/sphero/sphero_driver.go rename to drivers/common/spherocommon/spherocommon.go index d8391a150..978ac7dcd 100644 --- a/drivers/common/sphero/sphero_driver.go +++ b/drivers/common/spherocommon/spherocommon.go @@ -1,4 +1,4 @@ -package sphero +package spherocommon const ( // ErrorEvent event when error encountered diff --git a/drivers/common/sphero/sphero_packets.go b/drivers/common/spherocommon/spherocommon_packets.go similarity index 99% rename from drivers/common/sphero/sphero_packets.go rename to drivers/common/spherocommon/spherocommon_packets.go index 0f6333f85..6693aa9af 100644 --- a/drivers/common/sphero/sphero_packets.go +++ b/drivers/common/spherocommon/spherocommon_packets.go @@ -1,4 +1,4 @@ -package sphero +package spherocommon // LocatorConfig provides configuration for the Location api. // https://github.com/orbotix/DeveloperResources/blob/master/docs/Sphero_API_1.50.pdf diff --git a/drivers/common/sphero/sphero_driver_test.go b/drivers/common/spherocommon/spherocommon_test.go similarity index 94% rename from drivers/common/sphero/sphero_driver_test.go rename to drivers/common/spherocommon/spherocommon_test.go index 03759d7ff..baa5941b0 100644 --- a/drivers/common/sphero/sphero_driver_test.go +++ b/drivers/common/spherocommon/spherocommon_test.go @@ -1,4 +1,4 @@ -package sphero +package spherocommon import "testing" diff --git a/drivers/serial/README.md b/drivers/serial/README.md index 40da591f3..a8ec27b0c 100644 --- a/drivers/serial/README.md +++ b/drivers/serial/README.md @@ -13,3 +13,4 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r Gobot has a extensible system for connecting to hardware devices. The following Serial devices are currently supported: - Sphero: Sphero +- Neurosky: MindWave diff --git a/drivers/serial/helpers_test.go b/drivers/serial/helpers_test.go deleted file mode 100644 index b63f659f8..000000000 --- a/drivers/serial/helpers_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package serial - -type serialTestAdaptor struct { - isConnected bool - name string -} - -func newSerialTestAdaptor() *serialTestAdaptor { - return &serialTestAdaptor{} -} - -func (t *serialTestAdaptor) IsConnected() bool { - return t.isConnected -} - -func (t *serialTestAdaptor) SerialRead(b []byte) (int, error) { - return len(b), nil -} - -func (t *serialTestAdaptor) SerialWrite(b []byte) (int, error) { - return len(b), nil -} - -// gobot.Adaptor interfaces -func (t *serialTestAdaptor) Connect() error { return nil } -func (t *serialTestAdaptor) Finalize() error { return nil } -func (t *serialTestAdaptor) Name() string { return t.name } -func (t *serialTestAdaptor) SetName(n string) { t.name = n } diff --git a/drivers/serial/neurosky/LICENSE b/drivers/serial/neurosky/LICENSE new file mode 100644 index 000000000..09094bb5e --- /dev/null +++ b/drivers/serial/neurosky/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2013-2018 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/serial/neurosky/mindwave_driver.go b/drivers/serial/neurosky/mindwave_driver.go new file mode 100644 index 000000000..96571d3af --- /dev/null +++ b/drivers/serial/neurosky/mindwave_driver.go @@ -0,0 +1,196 @@ +package neurosky + +import ( + "bytes" + "log" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/serial" +) + +type mindWaveSerialAdaptor interface { + gobot.Adaptor + serial.SerialReader +} + +const ( + // mindWaveBTSync is the sync code + mindWaveBTSync byte = 0xAA + // mindWaveCodeEx Extended code + mindWaveCodeEx byte = 0x55 + // mindWaveCodeSignalQuality POOR_SIGNAL quality 0-255 + mindWaveCodeSignalQuality byte = 0x02 + // mindWaveCodeAttention ATTENTION eSense 0-100 + mindWaveCodeAttention byte = 0x04 + // mindWaveCodeMeditation MEDITATION eSense 0-100 + mindWaveCodeMeditation byte = 0x05 + // mindWaveCodeBlink BLINK strength 0-255 + mindWaveCodeBlink byte = 0x16 + // mindWaveCodeWave RAW wave value: 2-byte big-endian 2s-complement + mindWaveCodeWave byte = 0x80 + // mindWaveCodeAsicEEG ASIC EEG POWER 8 3-byte big-endian integers + mindWaveCodeAsicEEG byte = 0x83 + + ExtendedEvent = "extended" + SignalEvent = "signal" + AttentionEvent = "attention" + MeditationEvent = "meditation" + BlinkEvent = "blink" + WaveEvent = "wave" + EEGEvent = "eeg" + ErrorEvent = "error" +) + +// MindWaveDriver is the Gobot driver for the Neurosky MindWave Sensor +type MindWaveDriver struct { + *serial.Driver + gobot.Eventer +} + +// MindWaveEEGData is the EEG raw data returned from the sensor +type MindWaveEEGData struct { + Delta int + Theta int + LoAlpha int + HiAlpha int + LoBeta int + HiBeta int + LoGamma int + MidGamma int +} + +// NewMindWaveDriver creates a driver for Neurosky MindWave +// and adds the following events: +// +// extended - user's current extended level +// signal - shows signal strength +// attention - user's current attention level +// meditation - user's current meditation level +// blink - user's current blink level +// wave - shows wave data +// eeg - showing eeg data +func NewMindWaveDriver(a mindWaveSerialAdaptor, opts ...serial.OptionApplier) *MindWaveDriver { + d := &MindWaveDriver{ + Eventer: gobot.NewEventer(), + } + d.Driver = serial.NewDriver(a, "MindWave", d.initialize, nil, opts...) + + d.AddEvent(ExtendedEvent) + d.AddEvent(SignalEvent) + d.AddEvent(AttentionEvent) + d.AddEvent(MeditationEvent) + d.AddEvent(BlinkEvent) + d.AddEvent(WaveEvent) + d.AddEvent(EEGEvent) + d.AddEvent(ErrorEvent) + + return d +} + +// initialize creates a go routine to listen from serial port and parse buffer readings +// TODO: stop the go routine gracefully on Halt() +func (d *MindWaveDriver) initialize() error { + go func() { + for { + buff := make([]byte, 1024) + _, err := d.adaptor().SerialRead(buff) + if err != nil { + d.Publish(d.Event("error"), err) + } else { + if err := d.parse(bytes.NewBuffer(buff)); err != nil { + panic(err) + } + } + } + }() + return nil +} + +// parse converts bytes buffer into packets until no more data is present +func (d *MindWaveDriver) parse(buf *bytes.Buffer) error { + for buf.Len() > 2 { + b1, _ := buf.ReadByte() + b2, _ := buf.ReadByte() + if b1 == mindWaveBTSync && b2 == mindWaveBTSync { + length, _ := buf.ReadByte() + payload := make([]byte, length) + if _, err := buf.Read(payload); err != nil { + return err + } + // checksum, _ := buf.ReadByte() + buf.Next(1) + if err := d.parsePacket(bytes.NewBuffer(payload)); err != nil { + panic(err) + } + } + } + + return nil +} + +// parsePacket publishes event according to data parsed +func (d *MindWaveDriver) parsePacket(buf *bytes.Buffer) error { + for buf.Len() > 0 { + b, _ := buf.ReadByte() + switch b { + case mindWaveCodeEx: + d.Publish(d.Event(ExtendedEvent), nil) + case mindWaveCodeSignalQuality: + ret, _ := buf.ReadByte() + d.Publish(d.Event(SignalEvent), ret) + case mindWaveCodeAttention: + ret, _ := buf.ReadByte() + d.Publish(d.Event(AttentionEvent), ret) + case mindWaveCodeMeditation: + ret, _ := buf.ReadByte() + d.Publish(d.Event(MeditationEvent), ret) + case mindWaveCodeBlink: + ret, _ := buf.ReadByte() + d.Publish(d.Event(BlinkEvent), ret) + case mindWaveCodeWave: + buf.Next(1) + ret := make([]byte, 2) + if _, err := buf.Read(ret); err != nil { + return err + } + d.Publish(d.Event(WaveEvent), int16(ret[0])<<8|int16(ret[1])) + case mindWaveCodeAsicEEG: + ret := make([]byte, 25) + i, _ := buf.Read(ret) + if i == 25 { + d.Publish(d.Event(EEGEvent), d.parseEEG(ret)) + } + } + } + + return nil +} + +// parseEEG returns data converted into EEG map +func (d *MindWaveDriver) parseEEG(data []byte) MindWaveEEGData { + return MindWaveEEGData{ + Delta: d.parse3ByteInteger(data[0:3]), + Theta: d.parse3ByteInteger(data[3:6]), + LoAlpha: d.parse3ByteInteger(data[6:9]), + HiAlpha: d.parse3ByteInteger(data[9:12]), + LoBeta: d.parse3ByteInteger(data[12:15]), + HiBeta: d.parse3ByteInteger(data[15:18]), + LoGamma: d.parse3ByteInteger(data[18:21]), + MidGamma: d.parse3ByteInteger(data[21:25]), + } +} + +func (d *MindWaveDriver) parse3ByteInteger(data []byte) int { + return ((int(data[0]) << 16) | + (((1 << 16) - 1) & (int(data[1]) << 8)) | + (((1 << 8) - 1) & int(data[2]))) +} + +func (d *MindWaveDriver) adaptor() mindWaveSerialAdaptor { + if a, ok := d.Connection().(mindWaveSerialAdaptor); ok { + return a + } + + log.Printf("%s has no Neurosky serial connector\n", d.Name()) + return nil +} diff --git a/platforms/neurosky/neurosky_driver_test.go b/drivers/serial/neurosky/mindwave_driver_test.go similarity index 72% rename from platforms/neurosky/neurosky_driver_test.go rename to drivers/serial/neurosky/mindwave_driver_test.go index 00dd62a78..4e9eae5f0 100644 --- a/platforms/neurosky/neurosky_driver_test.go +++ b/drivers/serial/neurosky/mindwave_driver_test.go @@ -4,7 +4,6 @@ package neurosky import ( "bytes" "errors" - "io" "strings" "testing" "time" @@ -13,17 +12,15 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/serial/testutil" ) -var _ gobot.Driver = (*Driver)(nil) +var _ gobot.Driver = (*MindWaveDriver)(nil) -func initTestNeuroskyDriver() *Driver { - a := NewAdaptor("/dev/null") - a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { - return &NullReadWriteCloser{}, nil - } +func initTestNeuroskyDriver() *MindWaveDriver { + a := testutil.NewSerialTestAdaptor() _ = a.Connect() - return NewDriver(a) + return NewMindWaveDriver(a) } func TestNeuroskyDriver(t *testing.T) { @@ -33,7 +30,7 @@ func TestNeuroskyDriver(t *testing.T) { func TestNeuroskyDriverName(t *testing.T) { d := initTestNeuroskyDriver() - assert.True(t, strings.HasPrefix(d.Name(), "Neurosky")) + assert.True(t, strings.HasPrefix(d.Name(), "MindWave")) d.SetName("NewName") assert.Equal(t, "NewName", d.Name()) } @@ -41,24 +38,19 @@ func TestNeuroskyDriverName(t *testing.T) { func TestNeuroskyDriverStart(t *testing.T) { sem := make(chan bool) - rwc := &NullReadWriteCloser{} - a := NewAdaptor("/dev/null") - a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { - return rwc, nil - } + a := testutil.NewSerialTestAdaptor() _ = a.Connect() + a.SetSimulateReadError(true) - d := NewDriver(a) + d := NewMindWaveDriver(a) e := errors.New("read error") - _ = d.Once(d.Event(Error), func(data interface{}) { + _ = d.Once(d.Event(ErrorEvent), func(data interface{}) { assert.Equal(t, e, data.(error)) sem <- true }) require.NoError(t, d.Start()) - time.Sleep(50 * time.Millisecond) - rwc.ReadError(e) select { case <-sem: @@ -79,13 +71,13 @@ func TestNeuroskyDriverParse(t *testing.T) { sem := make(chan bool) d := initTestNeuroskyDriver() - // CodeEx + // mindWaveCodeEx go func() { time.Sleep(5 * time.Millisecond) _ = d.parse(bytes.NewBuffer([]byte{0xAA, 0xAA, 1, 0x55, 0x00})) }() - _ = d.On(d.Event(Extended), func(data interface{}) { + _ = d.On(d.Event(ExtendedEvent), func(data interface{}) { sem <- true }) @@ -95,72 +87,72 @@ func TestNeuroskyDriverParse(t *testing.T) { t.Errorf("Event \"extended\" was not published") } - // CodeSignalQuality + // mindWaveCodeSignalQuality go func() { time.Sleep(5 * time.Millisecond) _ = d.parse(bytes.NewBuffer([]byte{0xAA, 0xAA, 2, 0x02, 100, 0x00})) }() - _ = d.On(d.Event(Signal), func(data interface{}) { + _ = d.On(d.Event(SignalEvent), func(data interface{}) { assert.Equal(t, byte(100), data.(byte)) sem <- true }) <-sem - // CodeAttention + // mindWaveCodeAttention go func() { time.Sleep(5 * time.Millisecond) _ = d.parse(bytes.NewBuffer([]byte{0xAA, 0xAA, 2, 0x04, 40, 0x00})) }() - _ = d.On(d.Event(Attention), func(data interface{}) { + _ = d.On(d.Event(AttentionEvent), func(data interface{}) { assert.Equal(t, byte(40), data.(byte)) sem <- true }) <-sem - // CodeMeditation + // mindWaveCodeMeditation go func() { time.Sleep(5 * time.Millisecond) _ = d.parse(bytes.NewBuffer([]byte{0xAA, 0xAA, 2, 0x05, 60, 0x00})) }() - _ = d.On(d.Event(Meditation), func(data interface{}) { + _ = d.On(d.Event(MeditationEvent), func(data interface{}) { assert.Equal(t, byte(60), data.(byte)) sem <- true }) <-sem - // CodeBlink + // mindWaveCodeBlink go func() { time.Sleep(5 * time.Millisecond) _ = d.parse(bytes.NewBuffer([]byte{0xAA, 0xAA, 2, 0x16, 150, 0x00})) }() - _ = d.On(d.Event(Blink), func(data interface{}) { + _ = d.On(d.Event(BlinkEvent), func(data interface{}) { assert.Equal(t, byte(150), data.(byte)) sem <- true }) <-sem - // CodeWave + // mindWaveCodeWave go func() { time.Sleep(5 * time.Millisecond) _ = d.parse(bytes.NewBuffer([]byte{0xAA, 0xAA, 4, 0x80, 0x00, 0x40, 0x11, 0x00})) }() - _ = d.On(d.Event(Wave), func(data interface{}) { + _ = d.On(d.Event(WaveEvent), func(data interface{}) { assert.Equal(t, int16(16401), data.(int16)) sem <- true }) <-sem - // CodeAsicEEG + // mindWaveCodeAsicEEG go func() { time.Sleep(5 * time.Millisecond) _ = d.parse(bytes.NewBuffer([]byte{ @@ -170,9 +162,9 @@ func TestNeuroskyDriverParse(t *testing.T) { })) }() - _ = d.On(d.Event(EEG), func(data interface{}) { + _ = d.On(d.Event(EEGEvent), func(data interface{}) { assert.Equal(t, - EEGData{ + MindWaveEEGData{ Delta: 1573241, Theta: 5832801, LoAlpha: 1703966, @@ -182,7 +174,7 @@ func TestNeuroskyDriverParse(t *testing.T) { LoGamma: 8323090, MidGamma: 13565965, }, - data.(EEGData)) + data.(MindWaveEEGData)) sem <- true }) <-sem diff --git a/drivers/serial/serial_driver.go b/drivers/serial/serial_driver.go index 32e8ec7e7..ac6b428c1 100644 --- a/drivers/serial/serial_driver.go +++ b/drivers/serial/serial_driver.go @@ -15,8 +15,8 @@ type SerialWriter interface { SerialWrite(b []byte) (n int, err error) } -// optionApplier needs to be implemented by each configurable option type -type optionApplier interface { +// OptionApplier needs to be implemented by each configurable option type +type OptionApplier interface { apply(cfg *configuration) } @@ -29,7 +29,7 @@ type configuration struct { type nameOption string // Driver implements the interface gobot.Driver. -type driver struct { +type Driver struct { gobot.Commander connection interface{} driverCfg *configuration @@ -38,14 +38,24 @@ type driver struct { mutex *sync.Mutex } -// newDriver creates a new basic serial gobot driver. -func newDriver(a interface{}, name string, opts ...optionApplier) *driver { - d := driver{ +// NewDriver creates a new basic serial gobot driver. +func NewDriver(a interface{}, name string, + afterStart func() error, beforeHalt func() error, + opts ...OptionApplier, +) *Driver { + if afterStart == nil { + afterStart = func() error { return nil } + } + + if beforeHalt == nil { + beforeHalt = func() error { return nil } + } + d := Driver{ Commander: gobot.NewCommander(), connection: a, driverCfg: &configuration{name: gobot.DefaultName(name)}, - afterStart: func() error { return nil }, - beforeHalt: func() error { return nil }, + afterStart: afterStart, + beforeHalt: beforeHalt, mutex: &sync.Mutex{}, } @@ -57,23 +67,23 @@ func newDriver(a interface{}, name string, opts ...optionApplier) *driver { } // WithName is used to replace the default name of the driver. -func WithName(name string) optionApplier { +func WithName(name string) OptionApplier { return nameOption(name) } // Name returns the name of the driver. -func (d *driver) Name() string { +func (d *Driver) Name() string { return d.driverCfg.name } // SetName sets the name of the driver. // Deprecated: Please use option [serial.WithName] instead. -func (d *driver) SetName(name string) { +func (d *Driver) SetName(name string) { WithName(name).apply(d.driverCfg) } // Connection returns the connection of the driver. -func (d *driver) Connection() gobot.Connection { +func (d *Driver) Connection() gobot.Connection { if conn, ok := d.connection.(gobot.Connection); ok { return conn } @@ -83,7 +93,7 @@ func (d *driver) Connection() gobot.Connection { } // Start initializes the driver. -func (d *driver) Start() error { +func (d *Driver) Start() error { d.mutex.Lock() defer d.mutex.Unlock() @@ -93,7 +103,7 @@ func (d *driver) Start() error { } // Halt halts the driver. -func (d *driver) Halt() error { +func (d *Driver) Halt() error { d.mutex.Lock() defer d.mutex.Unlock() @@ -102,6 +112,10 @@ func (d *driver) Halt() error { return d.beforeHalt() } +func (d *Driver) Mutex() *sync.Mutex { + return d.mutex +} + // apply change the name in the configuration. func (o nameOption) apply(c *configuration) { c.name = string(o) diff --git a/drivers/serial/serial_driver_test.go b/drivers/serial/serial_driver_test.go index 7e965b609..a7109d94e 100644 --- a/drivers/serial/serial_driver_test.go +++ b/drivers/serial/serial_driver_test.go @@ -9,24 +9,25 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/serial/testutil" ) -var _ gobot.Driver = (*driver)(nil) +var _ gobot.Driver = (*Driver)(nil) -func initTestDriver() *driver { - a := newSerialTestAdaptor() - d := newDriver(a, "SERIAL_BASIC") +func initTestDriver() *Driver { + a := testutil.NewSerialTestAdaptor() + d := NewDriver(a, "SERIAL_BASIC", nil, nil) return d } -func Test_newDriver(t *testing.T) { +func TestNewDriver(t *testing.T) { // arrange const name = "mybot" - a := newSerialTestAdaptor() + a := testutil.NewSerialTestAdaptor() // act - d := newDriver(a, name) + d := NewDriver(a, name, nil, nil) // assert - assert.IsType(t, &driver{}, d) + assert.IsType(t, &Driver{}, d) assert.NotNil(t, d.driverCfg) assert.True(t, strings.HasPrefix(d.Name(), name)) assert.Equal(t, a, d.Connection()) @@ -44,9 +45,9 @@ func Test_newDriverWithName(t *testing.T) { name = "mybot" newName = "overwrite mybot" ) - a := newSerialTestAdaptor() + a := testutil.NewSerialTestAdaptor() // act - d := newDriver(a, name, WithName(newName)) + d := NewDriver(a, name, nil, nil, WithName(newName)) // assert assert.Equal(t, newName, d.Name()) } diff --git a/drivers/serial/sphero/LICENSE b/drivers/serial/sphero/LICENSE new file mode 100644 index 000000000..09094bb5e --- /dev/null +++ b/drivers/serial/sphero/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2013-2018 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/serial/sphero_driver.go b/drivers/serial/sphero/sphero_driver.go similarity index 82% rename from drivers/serial/sphero_driver.go rename to drivers/serial/sphero/sphero_driver.go index 6bdd969f5..c9a80cbaa 100644 --- a/drivers/serial/sphero_driver.go +++ b/drivers/serial/sphero/sphero_driver.go @@ -1,4 +1,4 @@ -package serial +package sphero import ( "bytes" @@ -8,13 +8,14 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" + "gobot.io/x/gobot/v2/drivers/serial" ) type spheroSerialAdaptor interface { gobot.Adaptor - SerialReader - SerialWriter + serial.SerialReader + serial.SerialWriter IsConnected() bool } @@ -27,14 +28,15 @@ type packet struct { // SpheroDriver Represents a Sphero 2.0 type SpheroDriver struct { - *driver + *serial.Driver gobot.Eventer - seq uint8 - asyncResponse [][]uint8 - syncResponse [][]uint8 - packetChannel chan *packet - responseChannel chan []uint8 - originalColor []uint8 // Only used for calibration. + seq uint8 + asyncResponse [][]uint8 + syncResponse [][]uint8 + packetChannel chan *packet + responseChannel chan []uint8 + originalColor []uint8 // Only used for calibration. + shutdownWaitTime time.Duration } // NewSpheroDriver returns a new SpheroDriver given a Sphero Adaptor. @@ -51,19 +53,18 @@ type SpheroDriver struct { // "SetStabilization" - See SpheroDriver.SetStabilization // "SetDataStreaming" - See SpheroDriver.SetDataStreaming // "SetRotationRate" - See SpheroDriver.SetRotationRate -func NewSpheroDriver(a spheroSerialAdaptor, opts ...optionApplier) *SpheroDriver { +func NewSpheroDriver(a spheroSerialAdaptor, opts ...serial.OptionApplier) *SpheroDriver { d := &SpheroDriver{ - driver: newDriver(a, "Sphero", opts...), - Eventer: gobot.NewEventer(), - packetChannel: make(chan *packet, 1024), - responseChannel: make(chan []uint8, 1024), + Eventer: gobot.NewEventer(), + packetChannel: make(chan *packet, 1024), + responseChannel: make(chan []uint8, 1024), + shutdownWaitTime: 1 * time.Second, } - d.afterStart = d.initialize - d.beforeHalt = d.shutdown + d.Driver = serial.NewDriver(a, "Sphero", d.initialize, d.shutdown, opts...) - d.AddEvent(sphero.ErrorEvent) - d.AddEvent(sphero.CollisionEvent) - d.AddEvent(sphero.SensorDataEvent) + d.AddEvent(spherocommon.ErrorEvent) + d.AddEvent(spherocommon.CollisionEvent) + d.AddEvent(spherocommon.SensorDataEvent) //nolint:forcetypeassert // ok here d.AddCommand("SetRGB", func(params map[string]interface{}) interface{} { @@ -127,7 +128,7 @@ func NewSpheroDriver(a spheroSerialAdaptor, opts ...optionApplier) *SpheroDriver Pcnt := uint8(params["Pcnt"].(float64)) Mask2 := uint32(params["Mask2"].(float64)) - d.SetDataStreaming(sphero.DataStreamingConfig{N: N, M: M, Mask2: Mask2, Pcnt: Pcnt, Mask: Mask}) + d.SetDataStreaming(spherocommon.DataStreamingConfig{N: N, M: M, Mask2: Mask2, Pcnt: Pcnt, Mask: Mask}) return nil }) //nolint:forcetypeassert // ok here @@ -137,7 +138,7 @@ func NewSpheroDriver(a spheroSerialAdaptor, opts ...optionApplier) *SpheroDriver Y := int16(params["Y"].(float64)) YawTare := int16(params["YawTare"].(float64)) - d.ConfigureLocator(sphero.LocatorConfig{Flags: Flags, X: X, Y: Y, YawTare: YawTare}) + d.ConfigureLocator(spherocommon.LocatorConfig{Flags: Flags, X: X, Y: Y, YawTare: YawTare}) return nil }) @@ -200,7 +201,7 @@ func (d *SpheroDriver) Roll(speed uint8, heading uint16) { } // ConfigureLocator configures and enables the Locator -func (d *SpheroDriver) ConfigureLocator(lc sphero.LocatorConfig) { +func (d *SpheroDriver) ConfigureLocator(lc spherocommon.LocatorConfig) { buf := new(bytes.Buffer) if err := binary.Write(buf, binary.BigEndian, lc); err != nil { panic(err) @@ -210,7 +211,7 @@ func (d *SpheroDriver) ConfigureLocator(lc sphero.LocatorConfig) { } // SetDataStreaming enables sensor data streaming -func (d *SpheroDriver) SetDataStreaming(dsc sphero.DataStreamingConfig) { +func (d *SpheroDriver) SetDataStreaming(dsc spherocommon.DataStreamingConfig) { buf := new(bytes.Buffer) if err := binary.Write(buf, binary.BigEndian, dsc); err != nil { panic(err) @@ -225,7 +226,7 @@ func (d *SpheroDriver) Stop() { } // ConfigureCollisionDetection configures the sensitivity of the detection. -func (d *SpheroDriver) ConfigureCollisionDetection(cc sphero.CollisionConfig) { +func (d *SpheroDriver) ConfigureCollisionDetection(cc spherocommon.CollisionConfig) { d.sendCraftPacket([]uint8{cc.Method, cc.Xt, cc.Yt, cc.Xs, cc.Ys, cc.Dead}, 0x12) } @@ -264,16 +265,18 @@ func (d *SpheroDriver) FinishCalibration() { // // Emits the Events: // -// Collision sphero.CollisionPacket - On Collision Detected -// SensorData sphero.DataStreamingPacket - On Data Streaming event +// Collision spherocommon.CollisionPacket - On Collision Detected +// SensorData spherocommon.DataStreamingPacket - On Data Streaming event // Error error- On error while processing asynchronous response +// +// TODO: stop the go routines gracefully on shutdown() func (d *SpheroDriver) initialize() error { go func() { for { packet := <-d.packetChannel err := d.write(packet) if err != nil { - d.Publish(sphero.ErrorEvent, err) + d.Publish(spherocommon.ErrorEvent, err) } } }() @@ -292,7 +295,7 @@ func (d *SpheroDriver) initialize() error { body := d.readBody(header[4]) data := append(header, body...) checksum := data[len(data)-1] - if checksum != sphero.CalculateChecksum(data[2:len(data)-1]) { + if checksum != spherocommon.CalculateChecksum(data[2:len(data)-1]) { continue } switch header[1] { @@ -327,13 +330,12 @@ func (d *SpheroDriver) initialize() error { } // shutdown halts the SpheroDriver and sends a SpheroDriver.Stop command to the Sphero. -// Returns true on successful halt. func (d *SpheroDriver) shutdown() error { if d.adaptor().IsConnected() { gobot.Every(10*time.Millisecond, func() { d.Stop() }) - time.Sleep(1 * time.Second) + time.Sleep(d.shutdownWaitTime) } return nil } @@ -347,12 +349,12 @@ func (d *SpheroDriver) handleCollisionDetected(data []uint8) { if len(data) != 22 || data[4] != 17 { return } - var collision sphero.CollisionPacket + var collision spherocommon.CollisionPacket buffer := bytes.NewBuffer(data[5:]) // skip header if err := binary.Read(buffer, binary.BigEndian, &collision); err != nil { panic(err) } - d.Publish(sphero.CollisionEvent, collision) + d.Publish(spherocommon.CollisionEvent, collision) } func (d *SpheroDriver) handleDataStreaming(data []uint8) { @@ -360,12 +362,12 @@ func (d *SpheroDriver) handleDataStreaming(data []uint8) { if len(data) != 90 { return } - var dataPacket sphero.DataStreamingPacket + var dataPacket spherocommon.DataStreamingPacket buffer := bytes.NewBuffer(data[5:]) // skip header if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil { panic(err) } - d.Publish(sphero.SensorDataEvent, dataPacket) + d.Publish(spherocommon.SensorDataEvent, dataPacket) } func (d *SpheroDriver) getSyncResponse(packet *packet) []byte { @@ -397,15 +399,15 @@ func (d *SpheroDriver) craftPacket(body []uint8, cid byte) *packet { packet := &packet{ body: body, header: hdr, - checksum: sphero.CalculateChecksum(buf[2:]), + checksum: spherocommon.CalculateChecksum(buf[2:]), } return packet } func (d *SpheroDriver) write(packet *packet) error { - d.mutex.Lock() - defer d.mutex.Unlock() + d.Mutex().Lock() + defer d.Mutex().Unlock() buf := append(packet.header, packet.body...) buf = append(buf, packet.checksum) @@ -445,17 +447,17 @@ func (d *SpheroDriver) readNextChunk(length int) []uint8 { } func (d *SpheroDriver) adaptor() spheroSerialAdaptor { - if a, ok := d.connection.(spheroSerialAdaptor); ok { + if a, ok := d.Connection().(spheroSerialAdaptor); ok { return a } - log.Printf("%s has no Sphere serial connector\n", d.driverCfg.name) + log.Printf("%s has no Sphero serial connector\n", d.Name()) return nil } // spheroDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults -func spheroDefaultCollisionConfig() sphero.CollisionConfig { - return sphero.CollisionConfig{ +func spheroDefaultCollisionConfig() spherocommon.CollisionConfig { + return spherocommon.CollisionConfig{ Method: 0x01, Xt: 0x80, Yt: 0x80, @@ -466,8 +468,8 @@ func spheroDefaultCollisionConfig() sphero.CollisionConfig { } // spheroDefaultLocatorConfig returns a LocatorConfig with defaults -func spheroDefaultLocatorConfig() sphero.LocatorConfig { - return sphero.LocatorConfig{ +func spheroDefaultLocatorConfig() spherocommon.LocatorConfig { + return spherocommon.LocatorConfig{ Flags: 0x01, X: 0x00, Y: 0x00, diff --git a/drivers/serial/sphero_driver_test.go b/drivers/serial/sphero/sphero_driver_test.go similarity index 80% rename from drivers/serial/sphero_driver_test.go rename to drivers/serial/sphero/sphero_driver_test.go index 55f57d23c..9ed175bf8 100644 --- a/drivers/serial/sphero_driver_test.go +++ b/drivers/serial/sphero/sphero_driver_test.go @@ -1,5 +1,5 @@ //nolint:forcetypeassert // ok here -package serial +package sphero import ( "bytes" @@ -11,14 +11,18 @@ import ( "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" + "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/serial/testutil" ) var _ gobot.Driver = (*SpheroDriver)(nil) func initTestSpheroDriver() *SpheroDriver { - a := newSerialTestAdaptor() - return NewSpheroDriver(a) + a := testutil.NewSerialTestAdaptor() + d := NewSpheroDriver(a) + d.shutdownWaitTime = 0 // to speed up the tests + return d } func TestNewSpheroDriver(t *testing.T) { @@ -32,9 +36,9 @@ func TestNewSpheroDriverWithName(t *testing.T) { // tests for options can also be done by call of "WithOption(val).apply(cfg)". // arrange const newName = "new name" - a := newSerialTestAdaptor() + a := testutil.NewSerialTestAdaptor() // act - d := NewSpheroDriver(a, WithName(newName)) + d := NewSpheroDriver(a, serial.WithName(newName)) // assert assert.Equal(t, newName, d.Name()) } @@ -99,20 +103,21 @@ func TestSpheroStart(t *testing.T) { } func TestSpheroHalt(t *testing.T) { - a := newSerialTestAdaptor() - a.isConnected = true + a := testutil.NewSerialTestAdaptor() + _ = a.Connect() d := NewSpheroDriver(a) + d.shutdownWaitTime = 0 // to speed up the tests require.NoError(t, d.Halt()) } func TestSpheroSetDataStreaming(t *testing.T) { d := initTestSpheroDriver() - d.SetDataStreaming(sphero.DefaultDataStreamingConfig()) + d.SetDataStreaming(spherocommon.DefaultDataStreamingConfig()) data := <-d.packetChannel buf := new(bytes.Buffer) - _ = binary.Write(buf, binary.BigEndian, sphero.DefaultDataStreamingConfig()) + _ = binary.Write(buf, binary.BigEndian, spherocommon.DefaultDataStreamingConfig()) assert.Equal(t, buf.Bytes(), data.body) @@ -128,7 +133,7 @@ func TestSpheroSetDataStreaming(t *testing.T) { assert.Nil(t, ret) data = <-d.packetChannel - dconfig := sphero.DataStreamingConfig{N: 100, M: 200, Mask: 300, Pcnt: 255, Mask2: 400} + dconfig := spherocommon.DataStreamingConfig{N: 100, M: 200, Mask: 300, Pcnt: 255, Mask2: 400} buf = new(bytes.Buffer) _ = binary.Write(buf, binary.BigEndian, dconfig) @@ -156,7 +161,7 @@ func TestSpheroConfigureLocator(t *testing.T) { assert.Nil(t, ret) data = <-d.packetChannel - lconfig := sphero.LocatorConfig{Flags: 1, X: 100, Y: 100, YawTare: 0} + lconfig := spherocommon.LocatorConfig{Flags: 1, X: 100, Y: 100, YawTare: 0} buf = new(bytes.Buffer) _ = binary.Write(buf, binary.BigEndian, lconfig) diff --git a/drivers/serial/testutil/testutil.go b/drivers/serial/testutil/testutil.go new file mode 100644 index 000000000..155a9ad7f --- /dev/null +++ b/drivers/serial/testutil/testutil.go @@ -0,0 +1,62 @@ +package testutil + +import "fmt" + +type serialTestAdaptor struct { + isConnected bool + name string + + simulateConnectErr bool + simulateReadErr bool + simulateWriteErr bool +} + +func NewSerialTestAdaptor() *serialTestAdaptor { + return &serialTestAdaptor{} +} + +func (t *serialTestAdaptor) SetSimulateConnectError(val bool) { + t.simulateConnectErr = val +} + +func (t *serialTestAdaptor) SetSimulateReadError(val bool) { + t.simulateReadErr = val +} + +func (t *serialTestAdaptor) SetSimulateWriteError(val bool) { + t.simulateWriteErr = val +} + +func (t *serialTestAdaptor) IsConnected() bool { + return t.isConnected +} + +func (t *serialTestAdaptor) SerialRead(b []byte) (int, error) { + if t.simulateReadErr { + return 0, fmt.Errorf("read error") + } + + return len(b), nil +} + +func (t *serialTestAdaptor) SerialWrite(b []byte) (int, error) { + if t.simulateWriteErr { + return 0, fmt.Errorf("write error") + } + + return len(b), nil +} + +// gobot.Adaptor interfaces +func (t *serialTestAdaptor) Connect() error { + if t.simulateConnectErr { + return fmt.Errorf("connect error") + } + + t.isConnected = true + return nil +} + +func (t *serialTestAdaptor) Finalize() error { return nil } +func (t *serialTestAdaptor) Name() string { return t.name } +func (t *serialTestAdaptor) SetName(n string) { t.name = n } diff --git a/drivers/spi/spi_driver.go b/drivers/spi/spi_driver.go index b25878596..9a5c284c7 100644 --- a/drivers/spi/spi_driver.go +++ b/drivers/spi/spi_driver.go @@ -12,7 +12,7 @@ const ( NotInitialized = -1 ) -// Connector lets Adaptors provide the interface for Drivers +// Connector lets adaptors provide the interface for Drivers // to get access to the SPI buses on platforms that support SPI. type Connector interface { // GetSpiConnection returns a connection to a SPI device at the specified bus and chip. diff --git a/examples/leap_sphero.go b/examples/leap_sphero.go index b4aae6170..07f6ea5ec 100644 --- a/examples/leap_sphero.go +++ b/examples/leap_sphero.go @@ -10,7 +10,7 @@ import ( "math" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/serial/sphero" "gobot.io/x/gobot/v2/platforms/leap" "gobot.io/x/gobot/v2/platforms/serialport" ) @@ -20,7 +20,7 @@ func main() { spheroAdaptor := serialport.NewAdaptor("/dev/tty.Sphero-YBW-RN-SPP") leapDriver := leap.NewDriver(leapAdaptor) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor) + spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) work := func() { _ = leapDriver.On(leap.MessageEvent, func(data interface{}) { diff --git a/examples/neurosky.go b/examples/serialport_mindwave.go similarity index 81% rename from examples/neurosky.go rename to examples/serialport_mindwave.go index 4c492230f..c27c685a5 100644 --- a/examples/neurosky.go +++ b/examples/serialport_mindwave.go @@ -10,12 +10,13 @@ import ( "fmt" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/neurosky" + "gobot.io/x/gobot/v2/drivers/serial/neurosky" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { - adaptor := neurosky.NewAdaptor("/dev/rfcomm0") - neuro := neurosky.NewDriver(adaptor) + adaptor := serialport.NewAdaptor("/dev/rfcomm0", serialport.WithName("Neurosky"), serialport.WithBaudRate(57600)) + neuro := neurosky.NewMindWaveDriver(adaptor) work := func() { _ = neuro.On(neuro.Event("extended"), func(data interface{}) { @@ -37,7 +38,7 @@ func main() { fmt.Println("Wave", data) }) _ = neuro.On(neuro.Event("eeg"), func(data interface{}) { - eeg := data.(neurosky.EEGData) + eeg := data.(neurosky.MindWaveEEGData) fmt.Println("Delta", eeg.Delta) fmt.Println("Theta", eeg.Theta) fmt.Println("LoAlpha", eeg.LoAlpha) diff --git a/examples/serial_sphero.go b/examples/serialport_sphero.go similarity index 68% rename from examples/serial_sphero.go rename to examples/serialport_sphero.go index d44143497..af709cc13 100644 --- a/examples/serial_sphero.go +++ b/examples/serialport_sphero.go @@ -11,23 +11,23 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/common/sphero" - "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" + "gobot.io/x/gobot/v2/drivers/serial/sphero" "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { adaptor := serialport.NewAdaptor("/dev/rfcomm0") - spheroDriver := serial.NewSpheroDriver(adaptor) + spheroDriver := sphero.NewSpheroDriver(adaptor) work := func() { - spheroDriver.SetDataStreaming(sphero.DefaultDataStreamingConfig()) + spheroDriver.SetDataStreaming(spherocommon.DefaultDataStreamingConfig()) - _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { + _ = spheroDriver.On(spherocommon.CollisionEvent, func(data interface{}) { fmt.Printf("Collision! %+v\n", data) }) - _ = spheroDriver.On(sphero.SensorDataEvent, func(data interface{}) { + _ = spheroDriver.On(spherocommon.SensorDataEvent, func(data interface{}) { fmt.Printf("Streaming Data! %+v\n", data) }) diff --git a/examples/serial_sphero_api.go b/examples/serialport_sphero_api.go similarity index 89% rename from examples/serial_sphero_api.go rename to examples/serialport_sphero_api.go index 558ae86d3..a6f2f3dfa 100644 --- a/examples/serial_sphero_api.go +++ b/examples/serialport_sphero_api.go @@ -9,7 +9,7 @@ package main import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/serial/sphero" "gobot.io/x/gobot/v2/platforms/serialport" ) @@ -23,7 +23,7 @@ func main() { for name, port := range spheros { spheroAdaptor := serialport.NewAdaptor(port) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor) + spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) work := func() { spheroDriver.SetRGB(uint8(255), uint8(0), uint8(0)) diff --git a/examples/serial_sphero_calibration.go b/examples/serialport_sphero_calibration.go similarity index 93% rename from examples/serial_sphero_calibration.go rename to examples/serialport_sphero_calibration.go index d81830b27..ee3f46bd7 100644 --- a/examples/serial_sphero_calibration.go +++ b/examples/serialport_sphero_calibration.go @@ -9,7 +9,7 @@ package main import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/serial/sphero" "gobot.io/x/gobot/v2/platforms/keyboard" "gobot.io/x/gobot/v2/platforms/serialport" ) @@ -20,7 +20,7 @@ func main() { a.Start() ballConn := serialport.NewAdaptor("/dev/rfcomm0") - ball := serial.NewSpheroDriver(ballConn) + ball := sphero.NewSpheroDriver(ballConn) keys := keyboard.NewDriver() diff --git a/examples/serial_sphero_conways.go b/examples/serialport_sphero_conways.go similarity index 88% rename from examples/serial_sphero_conways.go rename to examples/serialport_sphero_conways.go index d7acbf908..47af59964 100644 --- a/examples/serial_sphero_conways.go +++ b/examples/serialport_sphero_conways.go @@ -11,8 +11,9 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/serial/sphero" "gobot.io/x/gobot/v2/platforms/serialport" ) @@ -20,7 +21,7 @@ type conway struct { alive bool age int contacts int - cell *serial.SpheroDriver + cell *sphero.SpheroDriver } func main() { @@ -35,7 +36,7 @@ func main() { for _, port := range spheros { spheroAdaptor := serialport.NewAdaptor(port) - cell := serial.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero"+port)) + cell := sphero.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero"+port)) work := func() { conway := new(conway) @@ -43,7 +44,7 @@ func main() { conway.birth() - _ = cell.On(sphero.CollisionEvent, func(data interface{}) { + _ = cell.On(spherocommon.CollisionEvent, func(data interface{}) { conway.contact() }) diff --git a/examples/serial_sphero_dpad.go b/examples/serialport_sphero_dpad.go similarity index 91% rename from examples/serial_sphero_dpad.go rename to examples/serialport_sphero_dpad.go index d24673d81..a6206dec7 100644 --- a/examples/serial_sphero_dpad.go +++ b/examples/serialport_sphero_dpad.go @@ -11,7 +11,7 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/serial/sphero" "gobot.io/x/gobot/v2/platforms/serialport" ) @@ -21,7 +21,7 @@ func main() { a.Start() conn := serialport.NewAdaptor("/dev/rfcomm0") - ball := serial.NewSpheroDriver(conn) + ball := sphero.NewSpheroDriver(conn) robot := gobot.NewRobot("sphero-dpad", []gobot.Connection{conn}, diff --git a/examples/serial_sphero_master.go b/examples/serialport_sphero_master.go similarity index 82% rename from examples/serial_sphero_master.go rename to examples/serialport_sphero_master.go index d57be5d82..a4c0e42e8 100644 --- a/examples/serial_sphero_master.go +++ b/examples/serialport_sphero_master.go @@ -10,7 +10,7 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/serial/sphero" "gobot.io/x/gobot/v2/platforms/serialport" ) @@ -23,7 +23,7 @@ func main() { for name, port := range spheros { spheroAdaptor := serialport.NewAdaptor(port) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor) + spheroDriver := sphero.NewSpheroDriver(spheroAdaptor) work := func() { spheroDriver.SetRGB(uint8(255), uint8(0), uint8(0)) @@ -41,7 +41,7 @@ func main() { robot := gobot.NewRobot("", func() { gobot.Every(1*time.Second, func() { - sphero := master.Robot("Sphero-BPO").Device("sphero").(*serial.SpheroDriver) + sphero := master.Robot("Sphero-BPO").Device("sphero").(*sphero.SpheroDriver) sphero.SetRGB(uint8(gobot.Rand(255)), uint8(gobot.Rand(255)), uint8(gobot.Rand(255)), diff --git a/examples/serial_sphero_multiple.go b/examples/serialport_sphero_multiple.go similarity index 82% rename from examples/serial_sphero_multiple.go rename to examples/serialport_sphero_multiple.go index 04cd68339..65fef75dd 100644 --- a/examples/serial_sphero_multiple.go +++ b/examples/serialport_sphero_multiple.go @@ -12,19 +12,20 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/api" - "gobot.io/x/gobot/v2/drivers/common/sphero" + "gobot.io/x/gobot/v2/drivers/common/spherocommon" "gobot.io/x/gobot/v2/drivers/serial" + "gobot.io/x/gobot/v2/drivers/serial/sphero" "gobot.io/x/gobot/v2/platforms/serialport" ) func NewSwarmBot(port string) *gobot.Robot { spheroAdaptor := serialport.NewAdaptor(port) - spheroDriver := serial.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero"+port)) + spheroDriver := sphero.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero"+port)) work := func() { spheroDriver.Stop() - _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) { + _ = spheroDriver.On(spherocommon.CollisionEvent, func(data interface{}) { fmt.Println("Collision Detected!") }) diff --git a/platforms/bleclient/helper_test.go b/platforms/bleclient/helpers_test.go similarity index 100% rename from platforms/bleclient/helper_test.go rename to platforms/bleclient/helpers_test.go diff --git a/platforms/digispark/digispark_adaptor.go b/platforms/digispark/digispark_adaptor.go index 7d715ab8c..fd69498d5 100644 --- a/platforms/digispark/digispark_adaptor.go +++ b/platforms/digispark/digispark_adaptor.go @@ -37,10 +37,10 @@ func NewAdaptor() *Adaptor { } } -// Name returns the Digispark Adaptors name +// Name returns the Digispark adaptors name func (d *Adaptor) Name() string { return d.name } -// SetName sets the Digispark Adaptors name +// SetName sets the Digispark adaptors name func (d *Adaptor) SetName(n string) { d.name = n } // Connect starts a connection to the digispark diff --git a/platforms/firmata/firmata_adaptor.go b/platforms/firmata/firmata_adaptor.go index 24f64f9c5..888f6a13b 100644 --- a/platforms/firmata/firmata_adaptor.go +++ b/platforms/firmata/firmata_adaptor.go @@ -116,13 +116,13 @@ func (f *Adaptor) Finalize() error { return f.Disconnect() } -// Port returns the Firmata Adaptors port +// Port returns the Firmata adaptors port func (f *Adaptor) Port() string { return f.port } -// Name returns the Firmata Adaptors name +// Name returns the Firmata adaptors name func (f *Adaptor) Name() string { return f.name } -// SetName sets the Firmata Adaptors name +// SetName sets the Firmata adaptors name func (f *Adaptor) SetName(n string) { f.name = n } // ServoConfig sets the pulse width in microseconds for a pin attached to a servo diff --git a/platforms/intel-iot/edison/edison_adaptor.go b/platforms/intel-iot/edison/edison_adaptor.go index 87c2c33c2..fac93c0bd 100644 --- a/platforms/intel-iot/edison/edison_adaptor.go +++ b/platforms/intel-iot/edison/edison_adaptor.go @@ -83,10 +83,10 @@ func NewAdaptor(opts ...interface{}) *Adaptor { return a } -// Name returns the Adaptors name +// Name returns the adaptors name func (a *Adaptor) Name() string { return a.name } -// SetName sets the Adaptors name +// SetName sets the adaptors name func (a *Adaptor) SetName(n string) { a.name = n } // Connect initializes the Edison for use with the Arduino breakout board diff --git a/platforms/intel-iot/joule/joule_adaptor.go b/platforms/intel-iot/joule/joule_adaptor.go index 5706ac233..ba612e12a 100644 --- a/platforms/intel-iot/joule/joule_adaptor.go +++ b/platforms/intel-iot/joule/joule_adaptor.go @@ -62,10 +62,10 @@ func NewAdaptor(opts ...interface{}) *Adaptor { return a } -// Name returns the Adaptors name +// Name returns the adaptors name func (a *Adaptor) Name() string { return a.name } -// SetName sets the Adaptors name +// SetName sets the adaptors name func (a *Adaptor) SetName(n string) { a.name = n } // Connect create new connection to board and pins. diff --git a/platforms/jetson/jetson_adaptor.go b/platforms/jetson/jetson_adaptor.go index 6ef35239a..1d3160535 100644 --- a/platforms/jetson/jetson_adaptor.go +++ b/platforms/jetson/jetson_adaptor.go @@ -77,7 +77,7 @@ func NewAdaptor(opts ...interface{}) *Adaptor { return a } -// Name returns the Adaptor's name +// Name returns the adaptors name func (a *Adaptor) Name() string { a.mutex.Lock() defer a.mutex.Unlock() @@ -85,7 +85,7 @@ func (a *Adaptor) Name() string { return a.name } -// SetName sets the Adaptor's name +// SetName sets the adaptors name func (a *Adaptor) SetName(n string) { a.mutex.Lock() defer a.mutex.Unlock() diff --git a/platforms/joystick/joystick_adaptor.go b/platforms/joystick/joystick_adaptor.go index 38de67587..6950694ce 100644 --- a/platforms/joystick/joystick_adaptor.go +++ b/platforms/joystick/joystick_adaptor.go @@ -40,10 +40,10 @@ func NewAdaptor(id string) *Adaptor { } } -// Name returns the Adaptors name +// Name returns the adaptors name func (j *Adaptor) Name() string { return j.name } -// SetName sets the Adaptors name +// SetName sets the adaptors name func (j *Adaptor) SetName(n string) { j.name = n } // Connect connects to the joystick diff --git a/platforms/mqtt/mqtt_adaptor.go b/platforms/mqtt/mqtt_adaptor.go index 3e93efe46..b789292c6 100644 --- a/platforms/mqtt/mqtt_adaptor.go +++ b/platforms/mqtt/mqtt_adaptor.go @@ -60,10 +60,10 @@ func NewAdaptorWithAuth(host, clientID, username, password string) *Adaptor { } } -// Name returns the MQTT Adaptor's name +// Name returns the MQTT adaptors name func (a *Adaptor) Name() string { return a.name } -// SetName sets the MQTT Adaptor's name +// SetName sets the MQTT adaptors name func (a *Adaptor) SetName(n string) { a.name = n } // Port returns the Host name diff --git a/platforms/neurosky/README.md b/platforms/neurosky/README.md index b0cc9f33a..d21e32382 100644 --- a/platforms/neurosky/README.md +++ b/platforms/neurosky/README.md @@ -3,7 +3,7 @@ NeuroSky delivers fully integrated, single chip EEG biosensors. NeuroSky enables its partners and developers to bring their brainwave application ideas to market with the shortest amount of time, and lowest end consumer price. -This package contains the Gobot adaptor and driver for the [Neurosky Mindwave Mobile EEG](http://store.neurosky.com/products/mindwave-mobile). +This package contains the Gobot adaptor and driver for the [Neurosky MindWave Mobile EEG](http://store.neurosky.com/products/mindwave-mobile). ## How to Install @@ -13,31 +13,31 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r ### OSX -In order to allow Gobot running on your Mac to access the Mindwave, go to "Bluetooth > Open Bluetooth Preferences > Sharing Setup" +In order to allow Gobot running on your Mac to access the MindWave, go to "Bluetooth > Open Bluetooth Preferences > Sharing Setup" and make sure that "Bluetooth Sharing" is checked. -Now you must pair with the Mindwave. Open System Preferences > Bluetooth. Now with the Bluetooth devices windows open, hold -the On/Pair button on the Mindwave towards the On/Pair text until you see "Mindwave" pop up as available devices. Pair with -that device. Once paired your Mindwave will be accessable through the serial device similarly named as `/dev/tty.MindWaveMobile-DevA` +Now you must pair with the MindWave. Open System Preferences > Bluetooth. Now with the Bluetooth devices windows open, hold +the On/Pair button on the MindWave towards the On/Pair text until you see "MindWave" pop up as available devices. Pair with +that device. Once paired your MindWave will be accessable through the serial device similarly named as `/dev/tty.MindWaveMobile-DevA` ### Ubuntu -Connecting to the Mindwave from Ubuntu or any other Linux-based OS can be done entirely from the command line using [Gort](https://gobot.io/x/gort) +Connecting to the MindWave from Ubuntu or any other Linux-based OS can be done entirely from the command line using [Gort](https://gobot.io/x/gort) CLI commands. Here are the steps. -Find the address of the Mindwave, by using: +Find the address of the MindWave, by using: ```sh gort scan bluetooth ``` -Pair to Mindwave using this command (substituting the actual address of your Mindwave): +Pair to MindWave using this command (substituting the actual address of your MindWave): ```sh gort bluetooth pair
``` -Connect to the Mindwave using this command (substituting the actual address of your Mindwave): +Connect to the MindWave using this command (substituting the actual address of your MindWave): ```sh gort bluetooth connect
@@ -45,68 +45,9 @@ gort bluetooth connect
### Windows -You should be able to pair your Mindwave using your normal system tray applet for Bluetooth, and then connect to the +You should be able to pair your MindWave using your normal system tray applet for Bluetooth, and then connect to the COM port that is bound to the device, such as `COM3`. ## How to Use -This small program lets you connect the Neurosky an load data. - -```go -package main - -import ( - "fmt" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/neurosky" -) - -func main() { - adaptor := neurosky.NewAdaptor("/dev/rfcomm0") - neuro := neurosky.NewDriver(adaptor) - - work := func() { - _ = neuro.On(neuro.Event("extended"), func(data interface{}) { - fmt.Println("Extended", data) - }) - _ = neuro.On(neuro.Event("signal"), func(data interface{}) { - fmt.Println("Signal", data) - }) - _ = neuro.On(neuro.Event("attention"), func(data interface{}) { - fmt.Println("Attention", data) - }) - _ = neuro.On(neuro.Event("meditation"), func(data interface{}) { - fmt.Println("Meditation", data) - }) - _ = neuro.On(neuro.Event("blink"), func(data interface{}) { - fmt.Println("Blink", data) - }) - _ = neuro.On(neuro.Event("wave"), func(data interface{}) { - fmt.Println("Wave", data) - }) - _ = neuro.On(neuro.Event("eeg"), func(data interface{}) { - eeg := data.(neurosky.EEGData) - fmt.Println("Delta", eeg.Delta) - fmt.Println("Theta", eeg.Theta) - fmt.Println("LoAlpha", eeg.LoAlpha) - fmt.Println("HiAlpha", eeg.HiAlpha) - fmt.Println("LoBeta", eeg.LoBeta) - fmt.Println("HiBeta", eeg.HiBeta) - fmt.Println("LoGamma", eeg.LoGamma) - fmt.Println("MidGamma", eeg.MidGamma) - fmt.Println("\n") - }) - } - - robot := gobot.NewRobot("brainBot", - []gobot.Connection{adaptor}, - []gobot.Device{neuro}, - work, - ) - - if err := robot.Start(); err != nil { - panic(err) - } -} -``` +Please refer to the provided example `examples/serialport_neurosky.go`. diff --git a/platforms/neurosky/doc.go b/platforms/neurosky/doc.go deleted file mode 100644 index bee9e928a..000000000 --- a/platforms/neurosky/doc.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Package neurosky contains the Gobot adaptor and driver for the Neurosky Mindwave Mobile EEG. - -Installing: - - Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) - -Example: - - package main - - import ( - "fmt" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/neurosky" - ) - - func main() { - adaptor := neurosky.NewAdaptor("/dev/rfcomm0") - neuro := neurosky.NewDriver(adaptor) - - work := func() { - _ = neuro.On(neuro.Event("extended"), func(data interface{}) { - fmt.Println("Extended", data) - }) - _ = neuro.On(neuro.Event("signal"), func(data interface{}) { - fmt.Println("Signal", data) - }) - _ = neuro.On(neuro.Event("attention"), func(data interface{}) { - fmt.Println("Attention", data) - }) - _ = neuro.On(neuro.Event("meditation"), func(data interface{}) { - fmt.Println("Meditation", data) - }) - _ = neuro.On(neuro.Event("blink"), func(data interface{}) { - fmt.Println("Blink", data) - }) - _ = neuro.On(neuro.Event("wave"), func(data interface{}) { - fmt.Println("Wave", data) - }) - _ = neuro.On(neuro.Event("eeg"), func(data interface{}) { - eeg := data.(neurosky.EEGData) - fmt.Println("Delta", eeg.Delta) - fmt.Println("Theta", eeg.Theta) - fmt.Println("LoAlpha", eeg.LoAlpha) - fmt.Println("HiAlpha", eeg.HiAlpha) - fmt.Println("LoBeta", eeg.LoBeta) - fmt.Println("HiBeta", eeg.HiBeta) - fmt.Println("LoGamma", eeg.LoGamma) - fmt.Println("MidGamma", eeg.MidGamma) - fmt.Println("\n") - }) - } - - robot := gobot.NewRobot("brainBot", - []gobot.Connection{adaptor}, - []gobot.Device{neuro}, - work, - ) - - if err := robot.Start(); err != nil { - panic(err) - } - } - -For further information refer to neuroky README: -https://github.com/hybridgroup/gobot/blob/master/platforms/neurosky/README.md -*/ -package neurosky // import "gobot.io/x/gobot/v2/platforms/neurosky" diff --git a/platforms/neurosky/neurosky_adaptor.go b/platforms/neurosky/neurosky_adaptor.go deleted file mode 100644 index a0bac066f..000000000 --- a/platforms/neurosky/neurosky_adaptor.go +++ /dev/null @@ -1,52 +0,0 @@ -// Package neurosky is the Gobot platform for the Neurosky Mindwave EEG -package neurosky - -import ( - "io" - - "go.bug.st/serial" -) - -// Adaptor is the Gobot Adaptor for the Neurosky Mindwave -type Adaptor struct { - name string - port string - sp io.ReadWriteCloser - connect func(*Adaptor) (io.ReadWriteCloser, error) -} - -// NewAdaptor creates a neurosky adaptor with specified port -func NewAdaptor(port string) *Adaptor { - return &Adaptor{ - name: "Neurosky", - port: port, - connect: func(n *Adaptor) (io.ReadWriteCloser, error) { - return serial.Open(n.Port(), &serial.Mode{BaudRate: 57600}) - }, - } -} - -// Name returns the Adaptor Name -func (n *Adaptor) Name() string { return n.name } - -// SetName sets the Adaptor Name -func (n *Adaptor) SetName(name string) { n.name = name } - -// Port returns the Adaptor port -func (n *Adaptor) Port() string { return n.port } - -// Connect returns true if connection to device is successful -func (n *Adaptor) Connect() error { - sp, err := n.connect(n) - if err != nil { - return err - } - - n.sp = sp - return nil -} - -// Finalize returns true if device finalization is successful -func (n *Adaptor) Finalize() error { - return n.sp.Close() -} diff --git a/platforms/neurosky/neurosky_adaptor_test.go b/platforms/neurosky/neurosky_adaptor_test.go deleted file mode 100644 index e80ca31e5..000000000 --- a/platforms/neurosky/neurosky_adaptor_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package neurosky - -import ( - "errors" - "io" - "strings" - "sync" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gobot.io/x/gobot/v2" -) - -var _ gobot.Adaptor = (*Adaptor)(nil) - -type NullReadWriteCloser struct { - mtx sync.Mutex - readError error - closeError error -} - -func (n *NullReadWriteCloser) ReadError(e error) { - n.mtx.Lock() - defer n.mtx.Unlock() - n.readError = e -} - -func (n *NullReadWriteCloser) CloseError(e error) { - n.mtx.Lock() - defer n.mtx.Unlock() - n.closeError = e -} - -func (n *NullReadWriteCloser) Write(p []byte) (int, error) { - return len(p), nil -} - -func (n *NullReadWriteCloser) Read(b []byte) (int, error) { - n.mtx.Lock() - defer n.mtx.Unlock() - return len(b), n.readError -} - -func (n *NullReadWriteCloser) Close() error { - n.mtx.Lock() - defer n.mtx.Unlock() - return n.closeError -} - -func initTestNeuroskyAdaptor() *Adaptor { - a := NewAdaptor("/dev/null") - a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { - return &NullReadWriteCloser{}, nil - } - return a -} - -func TestNeuroskyAdaptor(t *testing.T) { - a := NewAdaptor("/dev/null") - assert.Equal(t, "/dev/null", a.Port()) -} - -func TestNeuroskyAdaptorName(t *testing.T) { - a := NewAdaptor("/dev/null") - assert.True(t, strings.HasPrefix(a.Name(), "Neurosky")) - a.SetName("NewName") - assert.Equal(t, "NewName", a.Name()) -} - -func TestNeuroskyAdaptorConnect(t *testing.T) { - a := initTestNeuroskyAdaptor() - require.NoError(t, a.Connect()) - - a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { - return nil, errors.New("connection error") - } - require.ErrorContains(t, a.Connect(), "connection error") -} - -func TestNeuroskyAdaptorFinalize(t *testing.T) { - rwc := &NullReadWriteCloser{} - a := NewAdaptor("/dev/null") - a.connect = func(n *Adaptor) (io.ReadWriteCloser, error) { - return rwc, nil - } - _ = a.Connect() - require.NoError(t, a.Finalize()) - - rwc.CloseError(errors.New("close error")) - _ = a.Connect() - require.ErrorContains(t, a.Finalize(), "close error") -} diff --git a/platforms/neurosky/neurosky_driver.go b/platforms/neurosky/neurosky_driver.go deleted file mode 100644 index 893f28bdb..000000000 --- a/platforms/neurosky/neurosky_driver.go +++ /dev/null @@ -1,222 +0,0 @@ -package neurosky - -import ( - "bytes" - - "gobot.io/x/gobot/v2" -) - -const ( - // BTSync is the sync code - BTSync byte = 0xAA - - // CodeEx Extended code - CodeEx byte = 0x55 - - // CodeSignalQuality POOR_SIGNAL quality 0-255 - CodeSignalQuality byte = 0x02 - - // CodeAttention ATTENTION eSense 0-100 - CodeAttention byte = 0x04 - - // CodeMeditation MEDITATION eSense 0-100 - CodeMeditation byte = 0x05 - - // CodeBlink BLINK strength 0-255 - CodeBlink byte = 0x16 - - // CodeWave RAW wave value: 2-byte big-endian 2s-complement - CodeWave byte = 0x80 - - // CodeAsicEEG ASIC EEG POWER 8 3-byte big-endian integers - CodeAsicEEG byte = 0x83 - - // Extended event - Extended = "extended" - - // Signal event - Signal = "signal" - - // Attention event - Attention = "attention" - - // Meditation event - Meditation = "meditation" - - // Blink event - Blink = "blink" - - // Wave event - Wave = "wave" - - // EEG event - EEG = "eeg" - - // Error event - Error = "error" -) - -// Driver is the Gobot Driver for the Mindwave -type Driver struct { - name string - connection gobot.Connection - gobot.Eventer -} - -// EEGData is the EEG raw data returned from the Mindwave -type EEGData struct { - Delta int - Theta int - LoAlpha int - HiAlpha int - LoBeta int - HiBeta int - LoGamma int - MidGamma int -} - -// NewDriver creates a Neurosky Driver -// and adds the following events: -// -// extended - user's current extended level -// signal - shows signal strength -// attention - user's current attention level -// meditation - user's current meditation level -// blink - user's current blink level -// wave - shows wave data -// eeg - showing eeg data -func NewDriver(a *Adaptor) *Driver { - n := &Driver{ - name: "Neurosky", - connection: a, - Eventer: gobot.NewEventer(), - } - - n.AddEvent(Extended) - n.AddEvent(Signal) - n.AddEvent(Attention) - n.AddEvent(Meditation) - n.AddEvent(Blink) - n.AddEvent(Wave) - n.AddEvent(EEG) - n.AddEvent(Error) - - return n -} - -// Connection returns the Driver's connection -func (n *Driver) Connection() gobot.Connection { return n.connection } - -// Name returns the Driver name -func (n *Driver) Name() string { return n.name } - -// SetName sets the Driver name -func (n *Driver) SetName(name string) { n.name = name } - -// adaptor returns neurosky adaptor -func (n *Driver) adaptor() *Adaptor { - //nolint:forcetypeassert // ok here - return n.Connection().(*Adaptor) -} - -// Start creates a go routine to listen from serial port -// and parse buffer readings -func (n *Driver) Start() error { - go func() { - for { - buff := make([]byte, 1024) - _, err := n.adaptor().sp.Read(buff) - if err != nil { - n.Publish(n.Event("error"), err) - } else { - if err := n.parse(bytes.NewBuffer(buff)); err != nil { - panic(err) - } - } - } - }() - return nil -} - -// Halt stops neurosky driver (void) -func (n *Driver) Halt() error { return nil } - -// parse converts bytes buffer into packets until no more data is present -func (n *Driver) parse(buf *bytes.Buffer) error { - for buf.Len() > 2 { - b1, _ := buf.ReadByte() - b2, _ := buf.ReadByte() - if b1 == BTSync && b2 == BTSync { - length, _ := buf.ReadByte() - payload := make([]byte, length) - if _, err := buf.Read(payload); err != nil { - return err - } - // checksum, _ := buf.ReadByte() - buf.Next(1) - if err := n.parsePacket(bytes.NewBuffer(payload)); err != nil { - panic(err) - } - } - } - - return nil -} - -// parsePacket publishes event according to data parsed -func (n *Driver) parsePacket(buf *bytes.Buffer) error { - for buf.Len() > 0 { - b, _ := buf.ReadByte() - switch b { - case CodeEx: - n.Publish(n.Event("extended"), nil) - case CodeSignalQuality: - ret, _ := buf.ReadByte() - n.Publish(n.Event("signal"), ret) - case CodeAttention: - ret, _ := buf.ReadByte() - n.Publish(n.Event("attention"), ret) - case CodeMeditation: - ret, _ := buf.ReadByte() - n.Publish(n.Event("meditation"), ret) - case CodeBlink: - ret, _ := buf.ReadByte() - n.Publish(n.Event("blink"), ret) - case CodeWave: - buf.Next(1) - ret := make([]byte, 2) - if _, err := buf.Read(ret); err != nil { - return err - } - n.Publish(n.Event("wave"), int16(ret[0])<<8|int16(ret[1])) - case CodeAsicEEG: - ret := make([]byte, 25) - i, _ := buf.Read(ret) - if i == 25 { - n.Publish(n.Event("eeg"), n.parseEEG(ret)) - } - } - } - - return nil -} - -// parseEEG returns data converted into EEG map -func (n *Driver) parseEEG(data []byte) EEGData { - return EEGData{ - Delta: n.parse3ByteInteger(data[0:3]), - Theta: n.parse3ByteInteger(data[3:6]), - LoAlpha: n.parse3ByteInteger(data[6:9]), - HiAlpha: n.parse3ByteInteger(data[9:12]), - LoBeta: n.parse3ByteInteger(data[12:15]), - HiBeta: n.parse3ByteInteger(data[15:18]), - LoGamma: n.parse3ByteInteger(data[18:21]), - MidGamma: n.parse3ByteInteger(data[21:25]), - } -} - -func (n *Driver) parse3ByteInteger(data []byte) int { - return ((int(data[0]) << 16) | - (((1 << 16) - 1) & (int(data[1]) << 8)) | - (((1 << 8) - 1) & int(data[2]))) -} diff --git a/platforms/parrot/bebop/bebop_adaptor.go b/platforms/parrot/bebop/bebop_adaptor.go index b094b8803..7f78eccb4 100644 --- a/platforms/parrot/bebop/bebop_adaptor.go +++ b/platforms/parrot/bebop/bebop_adaptor.go @@ -46,10 +46,10 @@ func NewAdaptor() *Adaptor { } } -// Name returns the Bebop Adaptors Name +// Name returns the Bebop adaptors Name func (a *Adaptor) Name() string { return a.name } -// SetName sets the Bebop Adaptors Name +// SetName sets the Bebop adaptors Name func (a *Adaptor) SetName(n string) { a.name = n } // Connect establishes a connection to the ardrone diff --git a/platforms/raspi/raspi_adaptor.go b/platforms/raspi/raspi_adaptor.go index 1d917b19a..e8b25bd7f 100644 --- a/platforms/raspi/raspi_adaptor.go +++ b/platforms/raspi/raspi_adaptor.go @@ -83,7 +83,7 @@ func NewAdaptor(opts ...interface{}) *Adaptor { return a } -// Name returns the Adaptor's name +// Name returns the adaptors name func (a *Adaptor) Name() string { a.mutex.Lock() defer a.mutex.Unlock() @@ -91,7 +91,7 @@ func (a *Adaptor) Name() string { return a.name } -// SetName sets the Adaptor's name +// SetName sets the adaptors name func (a *Adaptor) SetName(n string) { a.mutex.Lock() defer a.mutex.Unlock() diff --git a/platforms/rockpi/rockpi_adaptor.go b/platforms/rockpi/rockpi_adaptor.go index cf159a716..de76717ee 100644 --- a/platforms/rockpi/rockpi_adaptor.go +++ b/platforms/rockpi/rockpi_adaptor.go @@ -57,7 +57,7 @@ func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { return c } -// Name returns the Adaptor's name +// Name returns the adaptors name func (c *Adaptor) Name() string { c.mutex.Lock() defer c.mutex.Unlock() @@ -65,7 +65,7 @@ func (c *Adaptor) Name() string { return c.name } -// SetName sets the Adaptor's name +// SetName sets the adaptors name func (c *Adaptor) SetName(n string) { c.mutex.Lock() defer c.mutex.Unlock() diff --git a/platforms/serialport/README.md b/platforms/serialport/README.md index 2209a52a4..a8cadcc60 100644 --- a/platforms/serialport/README.md +++ b/platforms/serialport/README.md @@ -8,4 +8,5 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r ## How to Use -See documentation for [Sphero](https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/sphero/README.md) +See documentation for [Sphero](https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/sphero/README.md) or +[Neurosky MindWave](https://github.com/hybridgroup/gobot/blob/master/platforms/neurosky/README.md). diff --git a/platforms/serialport/adaptor.go b/platforms/serialport/adaptor.go index 688ca3571..04901f505 100644 --- a/platforms/serialport/adaptor.go +++ b/platforms/serialport/adaptor.go @@ -1,6 +1,7 @@ package serialport import ( + "fmt" "io" "go.bug.st/serial" @@ -8,35 +9,72 @@ import ( "gobot.io/x/gobot/v2" ) +// configuration contains all changeable attributes of the driver. +type configuration struct { + name string + baudRate int +} + // Adaptor represents a Gobot Adaptor for the Serial Communication type Adaptor struct { - name string - port string - sp io.ReadWriteCloser - connected bool - connect func(string) (io.ReadWriteCloser, error) + port string + cfg *configuration + + sp io.ReadWriteCloser + connected bool + connectFunc func(string, int) (io.ReadWriteCloser, error) } // NewAdaptor returns a new adaptor given a port for the serial communication -func NewAdaptor(port string) *Adaptor { - return &Adaptor{ - name: gobot.DefaultName("Serial"), +func NewAdaptor(port string, opts ...optionApplier) *Adaptor { + cfg := configuration{ + name: gobot.DefaultName("Serial"), + baudRate: 115200, + } + + a := Adaptor{ + cfg: &cfg, port: port, - connect: func(port string) (io.ReadWriteCloser, error) { - return serial.Open(port, &serial.Mode{BaudRate: 115200}) + connectFunc: func(port string, baudRate int) (io.ReadWriteCloser, error) { + return serial.Open(port, &serial.Mode{BaudRate: baudRate}) }, } + + for _, o := range opts { + o.apply(a.cfg) + } + + return &a } -// Name returns the Adaptor's name -func (a *Adaptor) Name() string { return a.name } +// WithName is used to replace the default name of the driver. +func WithName(name string) optionApplier { + return nameOption(name) +} -// SetName sets the Adaptor's name -func (a *Adaptor) SetName(n string) { a.name = n } +// WithName is used to replace the default name of the driver. +func WithBaudRate(baudRate int) optionApplier { + return baudRateOption(baudRate) +} + +// Name returns the adaptors name +func (a *Adaptor) Name() string { + return a.cfg.name +} + +// SetName sets the adaptors name +// Deprecated: Please use option [serialport.WithName] instead. +func (a *Adaptor) SetName(n string) { + WithName(n).apply(a.cfg) +} // Connect initiates a connection to the serial port. func (a *Adaptor) Connect() error { - sp, err := a.connect(a.Port()) + if a.connected { + return fmt.Errorf("serial port is already connected, try reconnect or run disconnect first") + } + + sp, err := a.connectFunc(a.port, a.cfg.baudRate) if err != nil { return err } @@ -73,7 +111,7 @@ func (a *Adaptor) Reconnect() error { return a.Connect() } -// Port returns the Adaptor's port +// Port returns the adaptors port func (a *Adaptor) Port() string { return a.port } // IsConnected returns the connection state @@ -81,12 +119,12 @@ func (a *Adaptor) IsConnected() bool { return a.connected } -// SerialRead reads from the port -func (a *Adaptor) SerialRead(p []byte) (int, error) { - return a.sp.Read(p) +// SerialRead reads from the port to the given reference +func (a *Adaptor) SerialRead(pData []byte) (int, error) { + return a.sp.Read(pData) } // SerialWrite writes to the port -func (a *Adaptor) SerialWrite(p []byte) (int, error) { - return a.sp.Write(p) +func (a *Adaptor) SerialWrite(data []byte) (int, error) { + return a.sp.Write(data) } diff --git a/platforms/serialport/adaptor_options.go b/platforms/serialport/adaptor_options.go new file mode 100644 index 000000000..6df21d44e --- /dev/null +++ b/platforms/serialport/adaptor_options.go @@ -0,0 +1,28 @@ +package serialport + +// optionApplier needs to be implemented by each configurable option type +type optionApplier interface { + apply(cfg *configuration) +} + +// nameOption is the type for applying another name to the configuration +type nameOption string + +// baudRateOption is the type for applying another baud rate than the default 115200 +type baudRateOption int + +func (o nameOption) String() string { + return "name option for Serial Port adaptors" +} + +func (o baudRateOption) String() string { + return "baud rate option for Serial Port adaptors" +} + +func (o nameOption) apply(cfg *configuration) { + cfg.name = string(o) +} + +func (o baudRateOption) apply(cfg *configuration) { + cfg.baudRate = int(o) +} diff --git a/platforms/serialport/adaptor_options_test.go b/platforms/serialport/adaptor_options_test.go new file mode 100644 index 000000000..d5a21f765 --- /dev/null +++ b/platforms/serialport/adaptor_options_test.go @@ -0,0 +1,27 @@ +package serialport + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestWithName(t *testing.T) { + // This is a general test, that options are applied by using the WithName() option. + // All other configuration options can also be tested by With..(val).apply(cfg). + // arrange & act + const newName = "new name" + a := NewAdaptor("port", WithName(newName)) + // assert + assert.Equal(t, newName, a.cfg.name) +} + +func TestWithBaudRate(t *testing.T) { + // arrange + newBaudRate := 5432 + cfg := &configuration{baudRate: 1234} + // act + WithBaudRate(newBaudRate).apply(cfg) + // assert + assert.Equal(t, newBaudRate, cfg.baudRate) +} diff --git a/platforms/serialport/adaptor_test.go b/platforms/serialport/adaptor_test.go index dd5321e8e..47ebea684 100644 --- a/platforms/serialport/adaptor_test.go +++ b/platforms/serialport/adaptor_test.go @@ -14,93 +14,142 @@ import ( var _ gobot.Adaptor = (*Adaptor)(nil) -type nullReadWriteCloser struct { - testAdaptorRead func(p []byte) (int, error) - testAdaptorWrite func(b []byte) (int, error) - testAdaptorClose func() error -} +func initTestAdaptor() (*Adaptor, *nullReadWriteCloser) { + a := NewAdaptor("/dev/null") + rwc := newNullReadWriteCloser() -func (n *nullReadWriteCloser) Write(p []byte) (int, error) { - return n.testAdaptorWrite(p) -} + a.connectFunc = func(string, int) (io.ReadWriteCloser, error) { + return rwc, nil + } -func (n *nullReadWriteCloser) Read(b []byte) (int, error) { - return n.testAdaptorRead(b) + if err := a.Connect(); err != nil { + panic(err) + } + return a, rwc } -func (n *nullReadWriteCloser) Close() error { - return n.testAdaptorClose() +func TestNewAdaptor(t *testing.T) { + // arrange + a := NewAdaptor("/dev/null") + assert.Equal(t, "/dev/null", a.Port()) + require.NotNil(t, a.cfg) + assert.Equal(t, 115200, a.cfg.baudRate) + assert.True(t, strings.HasPrefix(a.Name(), "Serial")) } -func NewNullReadWriteCloser() *nullReadWriteCloser { - return &nullReadWriteCloser{ - testAdaptorRead: func(p []byte) (int, error) { - return len(p), nil +func TestSerialRead(t *testing.T) { + tests := map[string]struct { + readDataBuffer []byte + simReadErr bool + wantCount int + wantErr string + }{ + "read_ok": { + readDataBuffer: []byte{0, 0}, + wantCount: 2, }, - testAdaptorWrite: func(b []byte) (int, error) { - return len(b), nil - }, - testAdaptorClose: func() error { - return nil + "error_read": { + readDataBuffer: []byte{}, + simReadErr: true, + wantErr: "read error", }, } -} - -func initTestAdaptor() (*Adaptor, *nullReadWriteCloser) { - a := NewAdaptor("/dev/null") - rwc := NewNullReadWriteCloser() - - a.connect = func(string) (io.ReadWriteCloser, error) { - return rwc, nil + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a, rwc := initTestAdaptor() + rwc.simulateReadErr = tc.simReadErr + // act + gotCount, err := a.SerialRead(tc.readDataBuffer) + // assert + if tc.wantErr == "" { + require.NoError(t, err) + } else { + require.EqualError(t, err, tc.wantErr) + } + assert.Equal(t, tc.wantCount, gotCount) + }) } - return a, rwc } -func TestNewAdaptor(t *testing.T) { - a := NewAdaptor("/dev/null") - assert.True(t, strings.HasPrefix(a.Name(), "Serial")) - assert.Equal(t, "/dev/null", a.Port()) +func TestSerialWrite(t *testing.T) { + tests := map[string]struct { + writeDataBuffer []byte + simWriteErr bool + wantCount int + wantWritten []byte + wantErr string + }{ + "write_ok": { + writeDataBuffer: []byte{1, 3, 6}, + wantWritten: []byte{1, 3, 6}, + wantCount: 3, + }, + "error_write": { + writeDataBuffer: []byte{}, + simWriteErr: true, + wantErr: "write error", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // arrange + a, rwc := initTestAdaptor() + rwc.simulateWriteErr = tc.simWriteErr + // act + gotCount, err := a.SerialWrite(tc.writeDataBuffer) + // assert + if tc.wantErr == "" { + require.NoError(t, err) + assert.Equal(t, tc.wantWritten, rwc.written) + } else { + require.EqualError(t, err, tc.wantErr) + } + assert.Equal(t, tc.wantCount, gotCount) + }) + } } -func TestName(t *testing.T) { +func TestConnect(t *testing.T) { + // arrange a, _ := initTestAdaptor() - assert.True(t, strings.HasPrefix(a.Name(), "Serial")) - a.SetName("NewName") - assert.Equal(t, "NewName", a.Name()) + require.True(t, a.IsConnected()) + // act & assert + require.EqualError(t, a.Connect(), "serial port is already connected, try reconnect or run disconnect first") + // re-arrange error + a.connected = false + a.connectFunc = func(string, int) (io.ReadWriteCloser, error) { + return nil, errors.New("connect error") + } + // act & assert + require.ErrorContains(t, a.Connect(), "connect error") + assert.False(t, a.IsConnected()) } func TestReconnect(t *testing.T) { + // arrange a, _ := initTestAdaptor() - require.NoError(t, a.Connect()) - assert.True(t, a.connected) + require.True(t, a.connected) + // act & assert require.NoError(t, a.Reconnect()) assert.True(t, a.connected) + // act & assert require.NoError(t, a.Disconnect()) assert.False(t, a.connected) + // act & assert require.NoError(t, a.Reconnect()) assert.True(t, a.connected) } func TestFinalize(t *testing.T) { + // arrange a, rwc := initTestAdaptor() - require.NoError(t, a.Connect()) + // act & assert require.NoError(t, a.Finalize()) - - rwc.testAdaptorClose = func() error { - return errors.New("close error") - } - + assert.False(t, a.IsConnected()) + // re-arrange error + rwc.simulateCloseErr = true a.connected = true + // act & assert require.ErrorContains(t, a.Finalize(), "close error") } - -func TestConnect(t *testing.T) { - a, _ := initTestAdaptor() - require.NoError(t, a.Connect()) - - a.connect = func(string) (io.ReadWriteCloser, error) { - return nil, errors.New("connect error") - } - - require.ErrorContains(t, a.Connect(), "connect error") -} diff --git a/platforms/serialport/helpers_test.go b/platforms/serialport/helpers_test.go new file mode 100644 index 000000000..b4b63f484 --- /dev/null +++ b/platforms/serialport/helpers_test.go @@ -0,0 +1,36 @@ +package serialport + +import "fmt" + +type nullReadWriteCloser struct { + written []byte + simulateReadErr bool + simulateWriteErr bool + simulateCloseErr bool +} + +func newNullReadWriteCloser() *nullReadWriteCloser { + return &nullReadWriteCloser{} +} + +func (rwc *nullReadWriteCloser) Write(data []byte) (int, error) { + if rwc.simulateWriteErr { + return 0, fmt.Errorf("write error") + } + rwc.written = append(rwc.written, data...) + return len(data), nil +} + +func (rwc *nullReadWriteCloser) Read(p []byte) (int, error) { + if rwc.simulateReadErr { + return 0, fmt.Errorf("read error") + } + return len(p), nil +} + +func (rwc *nullReadWriteCloser) Close() error { + if rwc.simulateCloseErr { + return fmt.Errorf("close error") + } + return nil +} diff --git a/platforms/sphero/sphero/README.md b/platforms/sphero/sphero/README.md index d156bce53..b7ff9c62e 100644 --- a/platforms/sphero/sphero/README.md +++ b/platforms/sphero/sphero/README.md @@ -70,7 +70,7 @@ import ( func main() { adaptor := serialport.NewAdaptor("/dev/rfcomm0") - driver := serial.NewSpheroDriver(adaptor) + driver := sphero.NewSpheroDriver(adaptor) work := func() { gobot.Every(3*time.Second, func() { From cb1f952d27ac6eb59a77b74745303a9f6f195911 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Mon, 12 Feb 2024 18:19:20 +0100 Subject: [PATCH 45/57] megapi: use serialport adaptor and move driver to drivers/serial (#1062) --- README.md | 1 + drivers/MIGRATION.md | 33 ++++- drivers/serial/README.md | 1 + drivers/serial/megapi/motor_driver.go | 130 ++++++++++++++++++ ...pi_motor.go => serialport_megapi_motor.go} | 9 +- platforms/megapi/README.md | 17 ++- platforms/megapi/megapi_adaptor.go | 88 ------------ platforms/megapi/motor_driver.go | 97 ------------- platforms/serialport/adaptor.go | 12 +- platforms/serialport/adaptor_test.go | 12 +- 10 files changed, 190 insertions(+), 210 deletions(-) create mode 100644 drivers/serial/megapi/motor_driver.go rename examples/{megapi_motor.go => serialport_megapi_motor.go} (74%) delete mode 100644 platforms/megapi/megapi_adaptor.go delete mode 100644 platforms/megapi/motor_driver.go diff --git a/README.md b/README.md index 0af24c298..55fe6232c 100644 --- a/README.md +++ b/README.md @@ -391,6 +391,7 @@ the `gobot/drivers/serial` package: - [UART](https://en.wikipedia.org/wiki/Serial_port) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/serial) - Sphero: Sphero - Neurosky: MindWave + - MegaPi: MotorDriver Support for devices that use Serial Peripheral Interface (SPI) have a shared set of drivers provided using the `gobot/drivers/spi` package: diff --git a/drivers/MIGRATION.md b/drivers/MIGRATION.md index 02b12da32..2eb43e50c 100644 --- a/drivers/MIGRATION.md +++ b/drivers/MIGRATION.md @@ -115,7 +115,7 @@ import( ### Neurosky adaptor split off -The Neurosky adaptor now us the generic serial adaptor. The driver part was moved. With this, the imports needs to be +The Neurosky adaptor now use the generic serial adaptor. The driver part was moved. With this, the imports needs to be adjusted. In addition all events now have a suffix "Event", see below. ```go @@ -148,6 +148,37 @@ import( ... ``` +### MegaPi adaptor split off + +The MegaPi adaptor now use the generic serial adaptor. The driver part was moved. With this, the imports needs to be +adjusted. + +```go +// old +import( + ... + "gobot.io/x/gobot/v2/platforms/megapi" + ... +) + +... + megaPiAdaptor := megapi.NewAdaptor("/dev/ttyS0") + motor := megapi.NewMotorDriver(megaPiAdaptor, 1) +... + +// new +import( + ... + "gobot.io/x/gobot/v2/drivers/serial/megapi" + "gobot.io/x/gobot/v2/platforms/serialport" + ... +) +... + adaptor := serialport.NewAdaptor("/dev/ttyS0", serialport.WithName("MegaPi")) + motor := megapi.NewMotorDriver(adaptor, 1) +... +``` + ## Switch from version 2.2.0 (gpio drivers affected) ### gpio.ButtonDriver, gpio.PIRMotionDriver: substitute parameter "v time.duration" diff --git a/drivers/serial/README.md b/drivers/serial/README.md index a8ec27b0c..207c83b11 100644 --- a/drivers/serial/README.md +++ b/drivers/serial/README.md @@ -14,3 +14,4 @@ Gobot has a extensible system for connecting to hardware devices. The following - Sphero: Sphero - Neurosky: MindWave +- MegaPi: MotorDriver diff --git a/drivers/serial/megapi/motor_driver.go b/drivers/serial/megapi/motor_driver.go new file mode 100644 index 000000000..371ee6c68 --- /dev/null +++ b/drivers/serial/megapi/motor_driver.go @@ -0,0 +1,130 @@ +package megapi + +import ( + "bytes" + "encoding/binary" + "log" + "sync" + "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/serial" +) + +var _ gobot.Driver = (*MotorDriver)(nil) + +type megapiMotorSerialAdaptor interface { + gobot.Adaptor + serial.SerialWriter +} + +// MotorDriver represents a motor +type MotorDriver struct { + *serial.Driver + port byte + halted bool + writeBytesChannel chan []byte + finalizeChannel chan struct{} + syncRoot *sync.Mutex +} + +// NewMotorDriver creates a new MotorDriver at the given port +func NewMotorDriver(a megapiMotorSerialAdaptor, port byte, opts ...serial.OptionApplier) *MotorDriver { + d := &MotorDriver{ + port: port, + halted: true, + syncRoot: &sync.Mutex{}, + writeBytesChannel: make(chan []byte), + finalizeChannel: make(chan struct{}), + } + d.Driver = serial.NewDriver(a, "MegaPiMotor", d.initialize, d.shutdown, opts...) + + return d +} + +// Speed sets the motors speed to the specified value +func (d *MotorDriver) Speed(speed int16) error { + d.syncRoot.Lock() + defer d.syncRoot.Unlock() + + if d.halted { + return nil + } + return d.speedHelper(speed) +} + +// initialize implements the Driver interface +func (d *MotorDriver) initialize() error { + d.syncRoot.Lock() + defer d.syncRoot.Unlock() + + // sleeping is required to give the board a chance to reset after connection is done + time.Sleep(2 * time.Second) + + // kick off thread to send bytes to the board + go func() { + for { + select { + case bytes := <-d.writeBytesChannel: + if _, err := d.adaptor().SerialWrite(bytes); err != nil { + panic(err) + } + time.Sleep(10 * time.Millisecond) + case <-d.finalizeChannel: + d.finalizeChannel <- struct{}{} + return + default: + time.Sleep(10 * time.Millisecond) + } + } + }() + + d.halted = false + return d.speedHelper(0) +} + +// Halt terminates the Driver interface +func (d *MotorDriver) shutdown() error { + d.syncRoot.Lock() + defer d.syncRoot.Unlock() + + d.finalizeChannel <- struct{}{} + <-d.finalizeChannel + + d.halted = true + return d.speedHelper(0) +} + +// there is some sort of bug on the hardware such that you cannot +// send the exact same speed to 2 different motors consecutively +// hence we ensure we always alternate speeds +func (d *MotorDriver) speedHelper(speed int16) error { + if err := d.sendSpeed(speed - 1); err != nil { + return err + } + return d.sendSpeed(speed) +} + +// sendSpeed sets the motors speed to the specified value +func (d *MotorDriver) sendSpeed(speed int16) error { + bufOut := new(bytes.Buffer) + + // byte sequence: 0xff, 0x55, id, action, device, port + bufOut.Write([]byte{0xff, 0x55, 0x6, 0x0, 0x2, 0xa, d.port}) + if err := binary.Write(bufOut, binary.LittleEndian, speed); err != nil { + return err + } + bufOut.Write([]byte{0xa}) + d.writeBytesChannel <- bufOut.Bytes() + + return nil +} + +func (d *MotorDriver) adaptor() megapiMotorSerialAdaptor { + if a, ok := d.Connection().(megapiMotorSerialAdaptor); ok { + return a + } + + log.Printf("%s has no MegaPi serial connector\n", d.Name()) + return nil +} diff --git a/examples/megapi_motor.go b/examples/serialport_megapi_motor.go similarity index 74% rename from examples/megapi_motor.go rename to examples/serialport_megapi_motor.go index fba251446..54fbd3191 100644 --- a/examples/megapi_motor.go +++ b/examples/serialport_megapi_motor.go @@ -11,14 +11,15 @@ import ( "time" "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/megapi" + "gobot.io/x/gobot/v2/drivers/serial/megapi" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { // use "/dev/ttyUSB0" if connecting with USB cable // use "/dev/ttyAMA0" on devices older than Raspberry Pi 3 Model B - megaPiAdaptor := megapi.NewAdaptor("/dev/ttyS0") - motor := megapi.NewMotorDriver(megaPiAdaptor, 1) + adaptor := serialport.NewAdaptor("/dev/ttyS0", serialport.WithName("MegaPi")) + motor := megapi.NewMotorDriver(adaptor, 1) work := func() { speed := int16(0) @@ -36,7 +37,7 @@ func main() { } robot := gobot.NewRobot("megaPiBot", - []gobot.Connection{megaPiAdaptor}, + []gobot.Connection{adaptor}, []gobot.Device{motor}, work, ) diff --git a/platforms/megapi/README.md b/platforms/megapi/README.md index 29db58c1b..c95aaaff9 100644 --- a/platforms/megapi/README.md +++ b/platforms/megapi/README.md @@ -15,16 +15,19 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r package main import ( - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/platforms/megapi" + "fmt" "time" + + "gobot.io/x/gobot/v2" + "gobot.io/x/gobot/v2/drivers/serial/megapi" + "gobot.io/x/gobot/v2/platforms/serialport" ) func main() { // use "/dev/ttyUSB0" if connecting with USB cable // use "/dev/ttyAMA0" on devices older than Raspberry Pi 3 Model B - megaPiAdaptor := megapi.NewAdaptor("/dev/ttyS0") - motor := megapi.NewMotorDriver(megaPiAdaptor, 1) + adaptor := serialport.NewAdaptor("/dev/ttyS0", serialport.WithName("MegaPi")) + motor := megapi.NewMotorDriver(adaptor, 1) work := func() { speed := int16(0) @@ -40,13 +43,13 @@ func main() { } robot := gobot.NewRobot("megaPiBot", - []gobot.Connection{megaPiAdaptor}, + []gobot.Connection{adaptor}, []gobot.Device{motor}, work, ) if err := robot.Start(); err != nil { - panic(err) - } + panic(err) + } } ``` diff --git a/platforms/megapi/megapi_adaptor.go b/platforms/megapi/megapi_adaptor.go deleted file mode 100644 index fb8767e44..000000000 --- a/platforms/megapi/megapi_adaptor.go +++ /dev/null @@ -1,88 +0,0 @@ -package megapi - -import ( - "io" - "time" - - "go.bug.st/serial" - - "gobot.io/x/gobot/v2" -) - -var _ gobot.Adaptor = (*Adaptor)(nil) - -// Adaptor is the Gobot adaptor for the MakeBlock MegaPi board -type Adaptor struct { - name string - port string - connection io.ReadWriteCloser - serialMode *serial.Mode - writeBytesChannel chan []byte - finalizeChannel chan struct{} -} - -// NewAdaptor returns a new Adaptor with specified serial port used to talk to the MegaPi with a baud rate of 115200 -func NewAdaptor(device string) *Adaptor { - c := &serial.Mode{BaudRate: 115200} - return &Adaptor{ - name: "MegaPi", - connection: nil, - port: device, - serialMode: c, - writeBytesChannel: make(chan []byte), - finalizeChannel: make(chan struct{}), - } -} - -// Name returns the name of this adaptor -func (megaPi *Adaptor) Name() string { - return megaPi.name -} - -// SetName sets the name of this adaptor -func (megaPi *Adaptor) SetName(n string) { - megaPi.name = n -} - -// Connect starts a connection to the board -func (megaPi *Adaptor) Connect() error { - if megaPi.connection == nil { - sp, err := serial.Open(megaPi.port, megaPi.serialMode) - if err != nil { - return err - } - - // sleeping is required to give the board a chance to reset - time.Sleep(2 * time.Second) - megaPi.connection = sp - } - - // kick off thread to send bytes to the board - go func() { - for { - select { - case bytes := <-megaPi.writeBytesChannel: - if _, err := megaPi.connection.Write(bytes); err != nil { - panic(err) - } - time.Sleep(10 * time.Millisecond) - case <-megaPi.finalizeChannel: - megaPi.finalizeChannel <- struct{}{} - return - default: - time.Sleep(10 * time.Millisecond) - } - } - }() - return nil -} - -// Finalize terminates the connection to the board -func (megaPi *Adaptor) Finalize() error { - megaPi.finalizeChannel <- struct{}{} - <-megaPi.finalizeChannel - if err := megaPi.connection.Close(); err != nil { - return err - } - return nil -} diff --git a/platforms/megapi/motor_driver.go b/platforms/megapi/motor_driver.go deleted file mode 100644 index ff6709cdf..000000000 --- a/platforms/megapi/motor_driver.go +++ /dev/null @@ -1,97 +0,0 @@ -package megapi - -import ( - "bytes" - "encoding/binary" - "sync" - - "gobot.io/x/gobot/v2" -) - -var _ gobot.Driver = (*MotorDriver)(nil) - -// MotorDriver represents a motor -type MotorDriver struct { - name string - megaPi *Adaptor - port byte - halted bool - syncRoot *sync.Mutex -} - -// NewMotorDriver creates a new MotorDriver at the given port -func NewMotorDriver(megaPi *Adaptor, port byte) *MotorDriver { - return &MotorDriver{ - name: "MegaPiMotor", - megaPi: megaPi, - port: port, - halted: true, - syncRoot: &sync.Mutex{}, - } -} - -// Name returns the name of this motor -func (d *MotorDriver) Name() string { - return d.name -} - -// SetName sets the name of this motor -func (d *MotorDriver) SetName(n string) { - d.name = n -} - -// Start implements the Driver interface -func (d *MotorDriver) Start() error { - d.syncRoot.Lock() - defer d.syncRoot.Unlock() - d.halted = false - return d.speedHelper(0) -} - -// Halt terminates the Driver interface -func (d *MotorDriver) Halt() error { - d.syncRoot.Lock() - defer d.syncRoot.Unlock() - d.halted = true - return d.speedHelper(0) -} - -// Connection returns the Connection associated with the Driver -func (d *MotorDriver) Connection() gobot.Connection { - return gobot.Connection(d.megaPi) -} - -// Speed sets the motors speed to the specified value -func (d *MotorDriver) Speed(speed int16) error { - d.syncRoot.Lock() - defer d.syncRoot.Unlock() - if d.halted { - return nil - } - return d.speedHelper(speed) -} - -// there is some sort of bug on the hardware such that you cannot -// send the exact same speed to 2 different motors consecutively -// hence we ensure we always alternate speeds -func (d *MotorDriver) speedHelper(speed int16) error { - if err := d.sendSpeed(speed - 1); err != nil { - return err - } - return d.sendSpeed(speed) -} - -// sendSpeed sets the motors speed to the specified value -func (d *MotorDriver) sendSpeed(speed int16) error { - bufOut := new(bytes.Buffer) - - // byte sequence: 0xff, 0x55, id, action, device, port - bufOut.Write([]byte{0xff, 0x55, 0x6, 0x0, 0x2, 0xa, d.port}) - if err := binary.Write(bufOut, binary.LittleEndian, speed); err != nil { - return err - } - bufOut.Write([]byte{0xa}) - d.megaPi.writeBytesChannel <- bufOut.Bytes() - - return nil -} diff --git a/platforms/serialport/adaptor.go b/platforms/serialport/adaptor.go index 04901f505..8af566039 100644 --- a/platforms/serialport/adaptor.go +++ b/platforms/serialport/adaptor.go @@ -21,7 +21,6 @@ type Adaptor struct { cfg *configuration sp io.ReadWriteCloser - connected bool connectFunc func(string, int) (io.ReadWriteCloser, error) } @@ -70,7 +69,7 @@ func (a *Adaptor) SetName(n string) { // Connect initiates a connection to the serial port. func (a *Adaptor) Connect() error { - if a.connected { + if a.sp != nil { return fmt.Errorf("serial port is already connected, try reconnect or run disconnect first") } @@ -80,7 +79,6 @@ func (a *Adaptor) Connect() error { } a.sp = sp - a.connected = true return nil } @@ -91,11 +89,11 @@ func (a *Adaptor) Finalize() error { // Disconnect terminates the connection to the port. func (a *Adaptor) Disconnect() error { - if a.connected { + if a.sp != nil { if err := a.sp.Close(); err != nil { return err } - a.connected = false + a.sp = nil } return nil } @@ -103,7 +101,7 @@ func (a *Adaptor) Disconnect() error { // Reconnect attempts to reconnect to the port. If the port is connected it will first close // that connection and then establish a new connection. func (a *Adaptor) Reconnect() error { - if a.connected { + if a.sp != nil { if err := a.Disconnect(); err != nil { return err } @@ -116,7 +114,7 @@ func (a *Adaptor) Port() string { return a.port } // IsConnected returns the connection state func (a *Adaptor) IsConnected() bool { - return a.connected + return a.sp != nil } // SerialRead reads from the port to the given reference diff --git a/platforms/serialport/adaptor_test.go b/platforms/serialport/adaptor_test.go index 47ebea684..972011415 100644 --- a/platforms/serialport/adaptor_test.go +++ b/platforms/serialport/adaptor_test.go @@ -117,7 +117,7 @@ func TestConnect(t *testing.T) { // act & assert require.EqualError(t, a.Connect(), "serial port is already connected, try reconnect or run disconnect first") // re-arrange error - a.connected = false + a.sp = nil a.connectFunc = func(string, int) (io.ReadWriteCloser, error) { return nil, errors.New("connect error") } @@ -129,16 +129,16 @@ func TestConnect(t *testing.T) { func TestReconnect(t *testing.T) { // arrange a, _ := initTestAdaptor() - require.True(t, a.connected) + require.NotNil(t, a.sp) // act & assert require.NoError(t, a.Reconnect()) - assert.True(t, a.connected) + require.NotNil(t, a.sp) // act & assert require.NoError(t, a.Disconnect()) - assert.False(t, a.connected) + require.Nil(t, a.sp) // act & assert require.NoError(t, a.Reconnect()) - assert.True(t, a.connected) + require.NotNil(t, a.sp) } func TestFinalize(t *testing.T) { @@ -149,7 +149,7 @@ func TestFinalize(t *testing.T) { assert.False(t, a.IsConnected()) // re-arrange error rwc.simulateCloseErr = true - a.connected = true + require.NoError(t, a.Connect()) // act & assert require.ErrorContains(t, a.Finalize(), "close error") } From 244f69987f27129605a64375a85ec61295d130ba Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Mon, 12 Feb 2024 20:18:51 +0100 Subject: [PATCH 46/57] bebop: fix concurrent map writes (#1063) --- platforms/parrot/bebop/client/client.go | 118 ++++++------------ .../bebop/client/networkframegenerator.go | 63 ++++++++++ 2 files changed, 100 insertions(+), 81 deletions(-) create mode 100644 platforms/parrot/bebop/client/networkframegenerator.go diff --git a/platforms/parrot/bebop/client/client.go b/platforms/parrot/bebop/client/client.go index 08451c1b4..6813fe773 100644 --- a/platforms/parrot/bebop/client/client.go +++ b/platforms/parrot/bebop/client/client.go @@ -107,50 +107,6 @@ func NewNetworkFrame(buf []byte) NetworkFrame { return frame } -func networkFrameGenerator() func(*bytes.Buffer, byte, byte) *bytes.Buffer { - // func networkFrameGenerator() func(*bytes.Buffer, byte, byte) NetworkFrame { - // - // ARNETWORKAL_Frame_t - // - // uint8 type - frame type ARNETWORK_FRAME_TYPE - // uint8 id - identifier of the buffer sending the frame - // uint8 seq - sequence number of the frame - // uint32 size - size of the frame - // - - // each frame id has it's own sequence number - seq := make(map[byte]byte) - - hlen := 7 // size of ARNETWORKAL_Frame_t header - - return func(cmd *bytes.Buffer, frameType byte, id byte) *bytes.Buffer { - if _, ok := seq[id]; !ok { - seq[id] = 0 - } - - seq[id]++ - - if seq[id] > 255 { - seq[id] = 0 - } - - ret := &bytes.Buffer{} - ret.WriteByte(frameType) - ret.WriteByte(id) - ret.WriteByte(seq[id]) - - size := &bytes.Buffer{} - if err := binary.Write(size, binary.LittleEndian, uint32(cmd.Len()+hlen)); err != nil { - panic(err) - } - - ret.Write(size.Bytes()) - ret.Write(cmd.Bytes()) - - return ret - } -} - type Pcmd struct { Flag int Roll int @@ -161,33 +117,33 @@ type Pcmd struct { } type Bebop struct { - IP string - NavData map[string]string - Pcmd Pcmd - tmpFrame tmpFrame - C2dPort int - D2cPort int - RTPStreamPort int - RTPControlPort int - DiscoveryPort int - c2dClient *net.UDPConn - d2cClient *net.UDPConn - discoveryClient *net.TCPConn - networkFrameGenerator func(*bytes.Buffer, byte, byte) *bytes.Buffer - video chan []byte - writeChan chan []byte + IP string + NavData map[string]string + Pcmd Pcmd + tmpFrame tmpFrame + C2dPort int + D2cPort int + RTPStreamPort int + RTPControlPort int + DiscoveryPort int + c2dClient *net.UDPConn + d2cClient *net.UDPConn + discoveryClient *net.TCPConn + nwFrameGenerator *nwFrameGenerator + video chan []byte + writeChan chan []byte } func New() *Bebop { return &Bebop{ - IP: "192.168.42.1", - NavData: make(map[string]string), - C2dPort: 54321, - D2cPort: 43210, - RTPStreamPort: 55004, - RTPControlPort: 55005, - DiscoveryPort: 44444, - networkFrameGenerator: networkFrameGenerator(), + IP: "192.168.42.1", + NavData: make(map[string]string), + C2dPort: 54321, + D2cPort: 43210, + RTPStreamPort: 55004, + RTPControlPort: 55005, + DiscoveryPort: 44444, + nwFrameGenerator: newNetworkFrameGenerator(), Pcmd: Pcmd{ Flag: 0, Roll: 0, @@ -332,7 +288,7 @@ func (b *Bebop) FlatTrim() error { cmd.Write(tmp.Bytes()) - return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) GenerateAllStates() error { @@ -352,7 +308,7 @@ func (b *Bebop) GenerateAllStates() error { cmd.Write(tmp.Bytes()) - return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) TakeOff() error { @@ -372,7 +328,7 @@ func (b *Bebop) TakeOff() error { cmd.Write(tmp.Bytes()) - return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) Land() error { @@ -392,7 +348,7 @@ func (b *Bebop) Land() error { cmd.Write(tmp.Bytes()) - return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) Up(val int) error { @@ -516,7 +472,7 @@ func (b *Bebop) generatePcmd() *bytes.Buffer { } cmd.Write(tmp.Bytes()) - return b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID) + return b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID) } func (b *Bebop) createAck(frame NetworkFrame) *bytes.Buffer { @@ -528,14 +484,14 @@ func (b *Bebop) createAck(frame NetworkFrame) *bytes.Buffer { // libARNetwork/Sources/ARNETWORK_Manager.h#ARNETWORK_Manager_IDOutputToIDAck // - return b.networkFrameGenerator(bytes.NewBuffer([]byte{uint8(frame.Seq)}), + return b.nwFrameGenerator.generate(bytes.NewBuffer([]byte{uint8(frame.Seq)}), ARNETWORKAL_FRAME_TYPE_ACK, byte(uint16(frame.Id)+(ARNETWORKAL_MANAGER_DEFAULT_ID_MAX/2)), ) } func (b *Bebop) createPong(frame NetworkFrame) *bytes.Buffer { - return b.networkFrameGenerator(bytes.NewBuffer(frame.Data), + return b.nwFrameGenerator.generate(bytes.NewBuffer(frame.Data), ARNETWORKAL_FRAME_TYPE_DATA, ARNETWORK_MANAGER_INTERNAL_BUFFER_ID_PONG, ) @@ -579,13 +535,13 @@ func (b *Bebop) packetReceiver(buf []byte) { func (b *Bebop) StartRecording() error { buf := b.videoRecord(ARCOMMANDS_ARDRONE3_MEDIARECORD_VIDEO_RECORD_START) - return b.write(b.networkFrameGenerator(buf, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(buf, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) StopRecording() error { buf := b.videoRecord(ARCOMMANDS_ARDRONE3_MEDIARECORD_VIDEO_RECORD_STOP) - return b.write(b.networkFrameGenerator(buf, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(buf, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) videoRecord(state byte) *bytes.Buffer { @@ -650,7 +606,7 @@ func (b *Bebop) HullProtection(protect bool) error { } cmd.Write(tmp.Bytes()) - return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) Outdoor(outdoor bool) error { @@ -679,7 +635,7 @@ func (b *Bebop) Outdoor(outdoor bool) error { } cmd.Write(tmp.Bytes()) - return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) VideoEnable(enable bool) error { @@ -704,7 +660,7 @@ func (b *Bebop) VideoEnable(enable bool) error { } cmd.Write(tmp.Bytes()) - return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func (b *Bebop) VideoStreamMode(mode int8) error { @@ -729,7 +685,7 @@ func (b *Bebop) VideoStreamMode(mode int8) error { } cmd.Write(tmp.Bytes()) - return b.write(b.networkFrameGenerator(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) + return b.write(b.nwFrameGenerator.generate(cmd, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_NONACK_ID).Bytes()) } func bool2int8(b bool) int8 { @@ -826,5 +782,5 @@ func (b *Bebop) createARStreamACK(frame ARStreamFrame) *bytes.Buffer { } ackPacket.Write(tmp.Bytes()) - return b.networkFrameGenerator(ackPacket, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_VIDEO_ACK_ID) + return b.nwFrameGenerator.generate(ackPacket, ARNETWORKAL_FRAME_TYPE_DATA, BD_NET_CD_VIDEO_ACK_ID) } diff --git a/platforms/parrot/bebop/client/networkframegenerator.go b/platforms/parrot/bebop/client/networkframegenerator.go new file mode 100644 index 000000000..af06e356b --- /dev/null +++ b/platforms/parrot/bebop/client/networkframegenerator.go @@ -0,0 +1,63 @@ +package client + +import ( + "bytes" + "encoding/binary" + "sync" +) + +type nwFrameGenerator struct { + seq map[byte]byte + hlen int + mutex *sync.Mutex +} + +func newNetworkFrameGenerator() *nwFrameGenerator { + nwg := nwFrameGenerator{ + seq: make(map[byte]byte), // each frame id has it's own sequence number + hlen: 7, // size of ARNETWORKAL_Frame_t header + mutex: &sync.Mutex{}, + } + return &nwg +} + +// generate the "NetworkFrame" as bytes buffer +func (nwg *nwFrameGenerator) generate(cmd *bytes.Buffer, frameType byte, id byte) *bytes.Buffer { + nwg.mutex.Lock() + defer nwg.mutex.Unlock() + + // func networkFrameGenerator() func(*bytes.Buffer, byte, byte) NetworkFrame { + // + // ARNETWORKAL_Frame_t + // + // uint8 type - frame type ARNETWORK_FRAME_TYPE + // uint8 id - identifier of the buffer sending the frame + // uint8 seq - sequence number of the frame + // uint32 size - size of the frame + // + + if _, ok := nwg.seq[id]; !ok { + nwg.seq[id] = 0 + } + + nwg.seq[id]++ + + if nwg.seq[id] > 255 { + nwg.seq[id] = 0 + } + + ret := &bytes.Buffer{} + ret.WriteByte(frameType) + ret.WriteByte(id) + ret.WriteByte(nwg.seq[id]) + + size := &bytes.Buffer{} + if err := binary.Write(size, binary.LittleEndian, uint32(cmd.Len()+nwg.hlen)); err != nil { + panic(err) + } + + ret.Write(size.Bytes()) + ret.Write(cmd.Bytes()) + + return ret +} From 026fd0353274cdd9b8e5345d17614ae1079a7046 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 13 Feb 2024 10:33:46 +0100 Subject: [PATCH 47/57] test: try to stabilize eventer tests (#1066) --- drivers/aio/analog_sensor_driver_test.go | 8 ++--- drivers/aio/grove_drivers_test.go | 4 +-- .../grove_temperature_sensor_driver_test.go | 2 +- drivers/aio/temperature_sensor_driver_test.go | 6 ++-- drivers/aio/thermalzone_driver_test.go | 2 +- .../ble/microbit/accelerometer_driver_test.go | 2 +- drivers/ble/microbit/button_driver_test.go | 2 +- .../ble/microbit/magnetometer_driver_test.go | 2 +- .../ble/microbit/temperature_driver_test.go | 2 +- .../common/spherocommon/spherocommon_test.go | 8 +++-- drivers/gpio/grove_drivers_test.go | 4 +-- drivers/gpio/pir_motion_driver_test.go | 8 ++--- drivers/i2c/adafruit1109_driver_test.go | 2 +- drivers/i2c/ads1x15_driver_1015_test.go | 2 +- drivers/i2c/ads1x15_driver_1115_test.go | 2 +- drivers/i2c/adxl345_driver_test.go | 2 +- drivers/i2c/bh1750_driver_test.go | 2 +- drivers/i2c/blinkm_driver_test.go | 2 +- drivers/i2c/bme280_driver_test.go | 2 +- drivers/i2c/bmp180_driver_test.go | 2 +- drivers/i2c/bmp280_driver_test.go | 2 +- drivers/i2c/bmp388_driver_test.go | 2 +- drivers/i2c/ccs811_driver_test.go | 2 +- drivers/i2c/drv2605l_driver_test.go | 2 +- drivers/i2c/generic_driver_test.go | 3 +- drivers/i2c/grovepi_driver_test.go | 6 ++-- drivers/i2c/hmc5883l_driver_test.go | 2 +- drivers/i2c/hmc6352_driver_test.go | 2 +- drivers/i2c/i2c_config_test.go | 3 +- drivers/i2c/i2c_driver_test.go | 2 +- drivers/i2c/jhd1313m1_driver_test.go | 2 +- drivers/i2c/l3gd20h_driver_test.go | 2 +- drivers/i2c/lidarlite_driver_test.go | 2 +- drivers/i2c/mcp23017_driver_test.go | 2 +- drivers/i2c/mma7660_driver_test.go | 2 +- drivers/i2c/mpl115a2_driver_test.go | 2 +- drivers/i2c/mpu6050_driver_test.go | 2 +- drivers/i2c/pca9501_driver_test.go | 2 +- drivers/i2c/pca953x_driver_test.go | 2 +- drivers/i2c/pcf8583_driver_test.go | 2 +- drivers/i2c/pcf8591_driver_test.go | 2 +- drivers/i2c/sht2x_driver_test.go | 2 +- drivers/i2c/sht3x_driver_test.go | 2 +- drivers/i2c/ssd1306_driver_test.go | 6 ++-- drivers/i2c/th02_driver_test.go | 4 +-- drivers/i2c/tsl2561_driver_test.go | 2 +- drivers/i2c/wiichuck_driver_test.go | 10 +++--- .../serial/neurosky/mindwave_driver_test.go | 4 +-- drivers/spi/apa102_test.go | 2 +- drivers/spi/mcp3002_test.go | 2 +- drivers/spi/mcp3004_test.go | 2 +- drivers/spi/mcp3008_test.go | 2 +- drivers/spi/mcp3202_test.go | 2 +- drivers/spi/mcp3204_test.go | 2 +- drivers/spi/mcp3208_test.go | 2 +- drivers/spi/mcp3304_test.go | 2 +- drivers/spi/mfrc522_driver_test.go | 2 +- drivers/spi/spi_driver_test.go | 2 +- eventer_test.go | 32 +++++++++---------- platforms/dji/tello/driver_test.go | 4 +-- platforms/firmata/client/client_test.go | 20 ++++++------ platforms/joystick/joystick_driver_test.go | 24 +++++++------- platforms/leap/leap_motion_driver_test.go | 2 +- platforms/mavlink/mavlink_driver_test.go | 6 ++-- platforms/opencv/camera_driver_test.go | 2 +- platforms/particle/adaptor_test.go | 8 ++--- platforms/pebble/pebble_driver_test.go | 4 +-- utils_test.go | 7 ++-- 68 files changed, 140 insertions(+), 133 deletions(-) diff --git a/drivers/aio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go index f4918e55a..5ae1be920 100644 --- a/drivers/aio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -193,7 +193,7 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) { select { case <-semDone: case <-time.After(readTimeout): - t.Errorf("AnalogSensor Event \"Data\" was not published") + require.Fail(t, "AnalogSensor Event \"Data\" was not published") } // arrange: for error to be received @@ -206,7 +206,7 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) { select { case <-semDone: case <-time.After(readTimeout): - t.Errorf("AnalogSensor Event \"Error\" was not published") + require.Fail(t, "AnalogSensor Event \"Error\" was not published") } // arrange: for halt message @@ -224,9 +224,9 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) { // assert: no event select { case <-semData: - t.Errorf("AnalogSensor Event for data should not published") + require.Fail(t, "AnalogSensor Event for data should not published") case <-semDone: - t.Errorf("AnalogSensor Event for value should not published") + require.Fail(t, "AnalogSensor Event for value should not published") case <-time.After(readTimeout): } } diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go index a161b4fe5..776e366dc 100644 --- a/drivers/aio/grove_drivers_test.go +++ b/drivers/aio/grove_drivers_test.go @@ -153,7 +153,7 @@ func TestGroveDriverHalt_WithSensorCyclicRead(t *testing.T) { time.Sleep(20 * time.Millisecond) // note: if a reading is already in progress, it will be finished before halt have an impact if atomic.LoadInt32(&callCount) > lastCallCount+1 { - t.Errorf("AnalogRead was called more than once after driver was halted") + require.Fail(t, "AnalogRead was called more than once after driver was halted") } } } @@ -188,7 +188,7 @@ func TestGroveDriverWithSensorCyclicReadPublishesError(t *testing.T) { select { case <-sem: case <-time.After(time.Second): - t.Errorf("%s Event \"Error\" was not published", groveGetType(driver)) + require.Fail(t, "%s Event \"Error\" was not published", groveGetType(driver)) } // Cleanup diff --git a/drivers/aio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go index ce8dc66ff..d7e76bbd0 100644 --- a/drivers/aio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -116,7 +116,7 @@ func TestGroveTemperatureSensor_publishesTemperatureInCelsius(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Grove Temperature Sensor Event \"Value\" was not published") + require.Fail(t, "Grove Temperature Sensor Event \"Value\" was not published") } assert.InDelta(t, 31.61532462352477, d.Temperature(), 0.0) diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index 0b9d2b3d5..43857b1fa 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -149,7 +149,7 @@ func TestTemperatureSensorWithSensorCyclicRead_PublishesTemperatureInCelsius(t * select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf(" Temperature Sensor Event \"Data\" was not published") + require.Fail(t, " Temperature Sensor Event \"Data\" was not published") } assert.InDelta(t, 31.61532462352477, d.Value(), 0.0) @@ -177,7 +177,7 @@ func TestTemperatureSensorWithSensorCyclicRead_PublishesError(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf(" Temperature Sensor Event \"Error\" was not published") + require.Fail(t, " Temperature Sensor Event \"Error\" was not published") } } @@ -195,7 +195,7 @@ func TestTemperatureSensorHalt_WithSensorCyclicRead(t *testing.T) { select { case <-done: case <-time.After(100 * time.Millisecond): - t.Errorf("Temperature Sensor was not halted") + require.Fail(t, "Temperature Sensor was not halted") } } diff --git a/drivers/aio/thermalzone_driver_test.go b/drivers/aio/thermalzone_driver_test.go index 1a3f92d1d..031e12031 100644 --- a/drivers/aio/thermalzone_driver_test.go +++ b/drivers/aio/thermalzone_driver_test.go @@ -84,7 +84,7 @@ func TestThermalZoneWithSensorCyclicRead_PublishesTemperatureInFahrenheit(t *tes select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf(" Temperature Sensor Event \"Data\" was not published") + require.Fail(t, " Temperature Sensor Event \"Data\" was not published") } assert.InDelta(t, -148.0, d.Value(), 0.0) diff --git a/drivers/ble/microbit/accelerometer_driver_test.go b/drivers/ble/microbit/accelerometer_driver_test.go index f0db11a3d..e783a7bc4 100644 --- a/drivers/ble/microbit/accelerometer_driver_test.go +++ b/drivers/ble/microbit/accelerometer_driver_test.go @@ -61,6 +61,6 @@ func TestAccelerometerReadData(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("Microbit Event \"Accelerometer\" was not published") + require.Fail(t, "Microbit Event \"Accelerometer\" was not published") } } diff --git a/drivers/ble/microbit/button_driver_test.go b/drivers/ble/microbit/button_driver_test.go index 0e6303511..d5d44de16 100644 --- a/drivers/ble/microbit/button_driver_test.go +++ b/drivers/ble/microbit/button_driver_test.go @@ -56,6 +56,6 @@ func TestButtonReadData(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("Microbit Event \"ButtonB\" was not published") + require.Fail(t, "Microbit Event \"ButtonB\" was not published") } } diff --git a/drivers/ble/microbit/magnetometer_driver_test.go b/drivers/ble/microbit/magnetometer_driver_test.go index d2d8c6639..8f14dc8ca 100644 --- a/drivers/ble/microbit/magnetometer_driver_test.go +++ b/drivers/ble/microbit/magnetometer_driver_test.go @@ -64,6 +64,6 @@ func TestMagnetometerReadData(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("Microbit Event \"Magnetometer\" was not published") + require.Fail(t, "Microbit Event \"Magnetometer\" was not published") } } diff --git a/drivers/ble/microbit/temperature_driver_test.go b/drivers/ble/microbit/temperature_driver_test.go index ea8984b4c..ca49650ab 100644 --- a/drivers/ble/microbit/temperature_driver_test.go +++ b/drivers/ble/microbit/temperature_driver_test.go @@ -61,6 +61,6 @@ func TestTemperatureReadData(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("Microbit Event \"Temperature\" was not published") + require.Fail(t, "Microbit Event \"Temperature\" was not published") } } diff --git a/drivers/common/spherocommon/spherocommon_test.go b/drivers/common/spherocommon/spherocommon_test.go index baa5941b0..3ee8b2a82 100644 --- a/drivers/common/spherocommon/spherocommon_test.go +++ b/drivers/common/spherocommon/spherocommon_test.go @@ -1,6 +1,10 @@ package spherocommon -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/require" +) func TestCalculateChecksum(t *testing.T) { tests := []struct { @@ -14,7 +18,7 @@ func TestCalculateChecksum(t *testing.T) { for _, tt := range tests { actual := CalculateChecksum(tt.data) if actual != tt.checksum { - t.Errorf("Expected %x, got %x for data %x.", tt.checksum, actual, tt.data) + require.Fail(t, "Expected %x, got %x for data %x.", tt.checksum, actual, tt.data) } } } diff --git a/drivers/gpio/grove_drivers_test.go b/drivers/gpio/grove_drivers_test.go index f705ded4f..59020ee62 100644 --- a/drivers/gpio/grove_drivers_test.go +++ b/drivers/gpio/grove_drivers_test.go @@ -71,7 +71,7 @@ func TestDigitalDriverHalt(t *testing.T) { time.Sleep(20 * time.Millisecond) // note: if a reading is already in progress, it will be finished before halt have an impact if atomic.LoadInt32(&callCount) > lastCallCount+1 { - t.Errorf("DigitalRead was called more than once after driver was halted") + require.Fail(t, "DigitalRead was called more than once after driver was halted") } } } @@ -105,7 +105,7 @@ func TestDriverPublishesError(t *testing.T) { select { case <-sem: case <-time.After(time.Second): - t.Errorf("%s Event \"Error\" was not published", getType(driver)) + require.Fail(t, "%s Event \"Error\" was not published", getType(driver)) } // Cleanup diff --git a/drivers/gpio/pir_motion_driver_test.go b/drivers/gpio/pir_motion_driver_test.go index 2b4ba4695..2f026bc50 100644 --- a/drivers/gpio/pir_motion_driver_test.go +++ b/drivers/gpio/pir_motion_driver_test.go @@ -104,7 +104,7 @@ func TestPIRMotionStart(t *testing.T) { select { case <-sem: case <-time.After(motionTestDelay * time.Millisecond): - t.Errorf("PIRMotionDriver Event \"MotionDetected\" was not published") + require.Fail(t, "PIRMotionDriver Event \"MotionDetected\" was not published") } _ = d.Once(MotionStopped, func(data interface{}) { @@ -116,7 +116,7 @@ func TestPIRMotionStart(t *testing.T) { select { case <-sem: case <-time.After(motionTestDelay * time.Millisecond): - t.Errorf("PIRMotionDriver Event \"MotionStopped\" was not published") + require.Fail(t, "PIRMotionDriver Event \"MotionStopped\" was not published") } _ = d.Once(Error, func(data interface{}) { @@ -126,7 +126,7 @@ func TestPIRMotionStart(t *testing.T) { select { case <-sem: case <-time.After(motionTestDelay * time.Millisecond): - t.Errorf("PIRMotionDriver Event \"Error\" was not published") + require.Fail(t, "PIRMotionDriver Event \"Error\" was not published") } _ = d.Once(MotionDetected, func(data interface{}) { @@ -138,7 +138,7 @@ func TestPIRMotionStart(t *testing.T) { select { case <-sem: - t.Errorf("PIRMotion Event \"MotionDetected\" should not published") + require.Fail(t, "PIRMotion Event \"MotionDetected\" should not published") case <-time.After(motionTestDelay * time.Millisecond): } } diff --git a/drivers/i2c/adafruit1109_driver_test.go b/drivers/i2c/adafruit1109_driver_test.go index 6b1a61b62..388bc89ce 100644 --- a/drivers/i2c/adafruit1109_driver_test.go +++ b/drivers/i2c/adafruit1109_driver_test.go @@ -23,7 +23,7 @@ func TestNewAdafruit1109Driver(t *testing.T) { var di interface{} = NewAdafruit1109Driver(newI2cTestAdaptor()) d, ok := di.(*Adafruit1109Driver) if !ok { - t.Errorf("NewAdafruit1109Driver() should have returned a *Adafruit1109Driver") + require.Fail(t, "NewAdafruit1109Driver() should have returned a *Adafruit1109Driver") } assert.NotNil(t, d.Driver) assert.NotNil(t, d.Connection()) diff --git a/drivers/i2c/ads1x15_driver_1015_test.go b/drivers/i2c/ads1x15_driver_1015_test.go index c06018a96..322faf554 100644 --- a/drivers/i2c/ads1x15_driver_1015_test.go +++ b/drivers/i2c/ads1x15_driver_1015_test.go @@ -22,7 +22,7 @@ func TestNewADS1015Driver(t *testing.T) { var di interface{} = NewADS1015Driver(newI2cTestAdaptor()) d, ok := di.(*ADS1x15Driver) if !ok { - t.Errorf("NewADS1015Driver() should have returned a *ADS1x15Driver") + require.Fail(t, "NewADS1015Driver() should have returned a *ADS1x15Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "ADS1015")) diff --git a/drivers/i2c/ads1x15_driver_1115_test.go b/drivers/i2c/ads1x15_driver_1115_test.go index ade8579fe..952105506 100644 --- a/drivers/i2c/ads1x15_driver_1115_test.go +++ b/drivers/i2c/ads1x15_driver_1115_test.go @@ -22,7 +22,7 @@ func TestNewADS1115Driver(t *testing.T) { var di interface{} = NewADS1115Driver(newI2cTestAdaptor()) d, ok := di.(*ADS1x15Driver) if !ok { - t.Errorf("NewADS1115Driver() should have returned a *ADS1x15Driver") + require.Fail(t, "NewADS1115Driver() should have returned a *ADS1x15Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "ADS1115")) diff --git a/drivers/i2c/adxl345_driver_test.go b/drivers/i2c/adxl345_driver_test.go index 4fc14d959..53e0695b2 100644 --- a/drivers/i2c/adxl345_driver_test.go +++ b/drivers/i2c/adxl345_driver_test.go @@ -25,7 +25,7 @@ func TestNewADXL345Driver(t *testing.T) { var di interface{} = NewADXL345Driver(newI2cTestAdaptor()) d, ok := di.(*ADXL345Driver) if !ok { - t.Errorf("NewADXL345Driver() should have returned a *ADXL345Driver") + require.Fail(t, "NewADXL345Driver() should have returned a *ADXL345Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "ADXL345")) diff --git a/drivers/i2c/bh1750_driver_test.go b/drivers/i2c/bh1750_driver_test.go index 9a8e5cbd5..39b00e550 100644 --- a/drivers/i2c/bh1750_driver_test.go +++ b/drivers/i2c/bh1750_driver_test.go @@ -29,7 +29,7 @@ func TestNewBH1750Driver(t *testing.T) { var di interface{} = NewBH1750Driver(newI2cTestAdaptor()) d, ok := di.(*BH1750Driver) if !ok { - t.Errorf("NewBH1750Driver() should have returned a *BH1750Driver") + require.Fail(t, "NewBH1750Driver() should have returned a *BH1750Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "BH1750")) diff --git a/drivers/i2c/blinkm_driver_test.go b/drivers/i2c/blinkm_driver_test.go index e10cebdfb..2532f06c2 100644 --- a/drivers/i2c/blinkm_driver_test.go +++ b/drivers/i2c/blinkm_driver_test.go @@ -29,7 +29,7 @@ func TestNewBlinkMDriver(t *testing.T) { var di interface{} = NewBlinkMDriver(newI2cTestAdaptor()) d, ok := di.(*BlinkMDriver) if !ok { - t.Errorf("NewBlinkMDriver() should have returned a *BlinkMDriver") + require.Fail(t, "NewBlinkMDriver() should have returned a *BlinkMDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "BlinkM")) diff --git a/drivers/i2c/bme280_driver_test.go b/drivers/i2c/bme280_driver_test.go index f89e45be2..d20c730f1 100644 --- a/drivers/i2c/bme280_driver_test.go +++ b/drivers/i2c/bme280_driver_test.go @@ -25,7 +25,7 @@ func TestNewBME280Driver(t *testing.T) { var di interface{} = NewBME280Driver(newI2cTestAdaptor()) d, ok := di.(*BME280Driver) if !ok { - t.Errorf("NewBME280Driver() should have returned a *BME280Driver") + require.Fail(t, "NewBME280Driver() should have returned a *BME280Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "BMP280")) diff --git a/drivers/i2c/bmp180_driver_test.go b/drivers/i2c/bmp180_driver_test.go index 374e42fd1..604dd2aa2 100644 --- a/drivers/i2c/bmp180_driver_test.go +++ b/drivers/i2c/bmp180_driver_test.go @@ -28,7 +28,7 @@ func TestNewBMP180Driver(t *testing.T) { var di interface{} = NewBMP180Driver(newI2cTestAdaptor()) d, ok := di.(*BMP180Driver) if !ok { - t.Errorf("NewBMP180Driver() should have returned a *BMP180Driver") + require.Fail(t, "NewBMP180Driver() should have returned a *BMP180Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "BMP180")) diff --git a/drivers/i2c/bmp280_driver_test.go b/drivers/i2c/bmp280_driver_test.go index 17bdec308..87b038904 100644 --- a/drivers/i2c/bmp280_driver_test.go +++ b/drivers/i2c/bmp280_driver_test.go @@ -25,7 +25,7 @@ func TestNewBMP280Driver(t *testing.T) { var di interface{} = NewBMP280Driver(newI2cTestAdaptor()) d, ok := di.(*BMP280Driver) if !ok { - t.Errorf("NewBMP280Driver() should have returned a *BMP280Driver") + require.Fail(t, "NewBMP280Driver() should have returned a *BMP280Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "BMP280")) diff --git a/drivers/i2c/bmp388_driver_test.go b/drivers/i2c/bmp388_driver_test.go index 41fb6cb79..b2a7001c8 100644 --- a/drivers/i2c/bmp388_driver_test.go +++ b/drivers/i2c/bmp388_driver_test.go @@ -44,7 +44,7 @@ func TestNewBMP388Driver(t *testing.T) { var di interface{} = NewBMP388Driver(newI2cTestAdaptor()) d, ok := di.(*BMP388Driver) if !ok { - t.Errorf("NewBMP388Driver() should have returned a *BMP388Driver") + require.Fail(t, "NewBMP388Driver() should have returned a *BMP388Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "BMP388")) diff --git a/drivers/i2c/ccs811_driver_test.go b/drivers/i2c/ccs811_driver_test.go index d205a19b3..a2792f810 100644 --- a/drivers/i2c/ccs811_driver_test.go +++ b/drivers/i2c/ccs811_driver_test.go @@ -24,7 +24,7 @@ func TestNewCCS811Driver(t *testing.T) { var di interface{} = NewCCS811Driver(newI2cTestAdaptor()) d, ok := di.(*CCS811Driver) if !ok { - t.Errorf("NewCCS811Driver() should have returned a *CCS811Driver") + require.Fail(t, "NewCCS811Driver() should have returned a *CCS811Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "CCS811")) diff --git a/drivers/i2c/drv2605l_driver_test.go b/drivers/i2c/drv2605l_driver_test.go index 0c9b6b54b..6784b3f00 100644 --- a/drivers/i2c/drv2605l_driver_test.go +++ b/drivers/i2c/drv2605l_driver_test.go @@ -37,7 +37,7 @@ func TestNewDRV2605LDriver(t *testing.T) { var di interface{} = NewDRV2605LDriver(newI2cTestAdaptor()) d, ok := di.(*DRV2605LDriver) if !ok { - t.Errorf("NewDRV2605LDriver() should have returned a *DRV2605LDriver") + require.Fail(t, "NewDRV2605LDriver() should have returned a *DRV2605LDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "DRV2605L")) diff --git a/drivers/i2c/generic_driver_test.go b/drivers/i2c/generic_driver_test.go index e522b216d..bdee1f7f1 100644 --- a/drivers/i2c/generic_driver_test.go +++ b/drivers/i2c/generic_driver_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gobot.io/x/gobot/v2" ) @@ -19,7 +20,7 @@ func TestNewGenericDriver(t *testing.T) { // assert d, ok := di.(*GenericDriver) if !ok { - t.Errorf("NewGenericDriver() should have returned a *GenericDriver") + require.Fail(t, "NewGenericDriver() should have returned a *GenericDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "GenericI2C")) diff --git a/drivers/i2c/grovepi_driver_test.go b/drivers/i2c/grovepi_driver_test.go index ae8a1b97b..fce08ce43 100644 --- a/drivers/i2c/grovepi_driver_test.go +++ b/drivers/i2c/grovepi_driver_test.go @@ -42,7 +42,7 @@ func TestNewGrovePiDriver(t *testing.T) { var di interface{} = NewGrovePiDriver(newI2cTestAdaptor()) d, ok := di.(*GrovePiDriver) if !ok { - t.Errorf("NewGrovePiDriver() should have returned a *GrovePiDriver") + require.Fail(t, "NewGrovePiDriver() should have returned a *GrovePiDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "GrovePi")) @@ -165,7 +165,7 @@ func TestGrovePiSomeRead(t *testing.T) { case strings.Contains(name, "DHTRead"): gotF1, gotF2, err = g.DHTRead(strconv.Itoa(tc.usedPin), 1, 2) default: - t.Errorf("unknown command %s", name) + require.Fail(t, "unknown command %s", name) return } // assert @@ -218,7 +218,7 @@ func TestGrovePiSomeWrite(t *testing.T) { case "AnalogWrite": err = g.AnalogWrite(strconv.Itoa(tc.usedPin), tc.usedValue) default: - t.Errorf("unknown command %s", name) + require.Fail(t, "unknown command %s", name) return } // assert diff --git a/drivers/i2c/hmc5883l_driver_test.go b/drivers/i2c/hmc5883l_driver_test.go index 1b512ff20..5e021b6c3 100644 --- a/drivers/i2c/hmc5883l_driver_test.go +++ b/drivers/i2c/hmc5883l_driver_test.go @@ -23,7 +23,7 @@ func TestNewHMC5883LDriver(t *testing.T) { var di interface{} = NewHMC5883LDriver(newI2cTestAdaptor()) d, ok := di.(*HMC5883LDriver) if !ok { - t.Errorf("NewHMC5883LDriver() should have returned a *HMC5883LDriver") + require.Fail(t, "NewHMC5883LDriver() should have returned a *HMC5883LDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.name, "HMC5883L")) diff --git a/drivers/i2c/hmc6352_driver_test.go b/drivers/i2c/hmc6352_driver_test.go index 770d1c446..7634ed2a8 100644 --- a/drivers/i2c/hmc6352_driver_test.go +++ b/drivers/i2c/hmc6352_driver_test.go @@ -28,7 +28,7 @@ func TestNewHMC6352Driver(t *testing.T) { var di interface{} = NewHMC6352Driver(newI2cTestAdaptor()) d, ok := di.(*HMC6352Driver) if !ok { - t.Errorf("NewHMC6352Driver() should have returned a *HMC6352Driver") + require.Fail(t, "NewHMC6352Driver() should have returned a *HMC6352Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "HMC6352")) diff --git a/drivers/i2c/i2c_config_test.go b/drivers/i2c/i2c_config_test.go index 28dc37eeb..4c63757fd 100644 --- a/drivers/i2c/i2c_config_test.go +++ b/drivers/i2c/i2c_config_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNewConfig(t *testing.T) { @@ -13,7 +14,7 @@ func TestNewConfig(t *testing.T) { // assert c, ok := ci.(*i2cConfig) if !ok { - t.Errorf("NewConfig() should have returned a *i2cConfig") + require.Fail(t, "NewConfig() should have returned a *i2cConfig") } assert.Equal(t, BusNotInitialized, c.bus) assert.Equal(t, AddressNotInitialized, c.address) diff --git a/drivers/i2c/i2c_driver_test.go b/drivers/i2c/i2c_driver_test.go index 28abcb388..6a96181f7 100644 --- a/drivers/i2c/i2c_driver_test.go +++ b/drivers/i2c/i2c_driver_test.go @@ -30,7 +30,7 @@ func TestNewDriver(t *testing.T) { // assert d, ok := di.(*Driver) if !ok { - t.Errorf("NewDriver() should have returned a *Driver") + require.Fail(t, "NewDriver() should have returned a *Driver") } assert.Contains(t, d.name, "I2C_BASIC") assert.Equal(t, 0x15, d.defaultAddress) diff --git a/drivers/i2c/jhd1313m1_driver_test.go b/drivers/i2c/jhd1313m1_driver_test.go index e6ffc273f..6cd4357ec 100644 --- a/drivers/i2c/jhd1313m1_driver_test.go +++ b/drivers/i2c/jhd1313m1_driver_test.go @@ -31,7 +31,7 @@ func TestNewJHD1313M1Driver(t *testing.T) { var mpl interface{} = NewJHD1313M1Driver(newI2cTestAdaptor()) _, ok := mpl.(*JHD1313M1Driver) if !ok { - t.Errorf("NewJHD1313M1Driver() should have returned a *JHD1313M1Driver") + require.Fail(t, "NewJHD1313M1Driver() should have returned a *JHD1313M1Driver") } } diff --git a/drivers/i2c/l3gd20h_driver_test.go b/drivers/i2c/l3gd20h_driver_test.go index 392ddb886..4abe0bc60 100644 --- a/drivers/i2c/l3gd20h_driver_test.go +++ b/drivers/i2c/l3gd20h_driver_test.go @@ -33,7 +33,7 @@ func TestNewL3GD20HDriver(t *testing.T) { var di interface{} = NewL3GD20HDriver(newI2cTestAdaptor()) d, ok := di.(*L3GD20HDriver) if !ok { - t.Errorf("NewL3GD20HDriver() should have returned a *L3GD20HDriver") + require.Fail(t, "NewL3GD20HDriver() should have returned a *L3GD20HDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "L3GD20H")) diff --git a/drivers/i2c/lidarlite_driver_test.go b/drivers/i2c/lidarlite_driver_test.go index 8354b2648..c956173e9 100644 --- a/drivers/i2c/lidarlite_driver_test.go +++ b/drivers/i2c/lidarlite_driver_test.go @@ -34,7 +34,7 @@ func TestNewLIDARLiteDriver(t *testing.T) { var di interface{} = NewLIDARLiteDriver(newI2cTestAdaptor()) d, ok := di.(*LIDARLiteDriver) if !ok { - t.Errorf("NewLIDARLiteDriver() should have returned a *LIDARLiteDriver") + require.Fail(t, "NewLIDARLiteDriver() should have returned a *LIDARLiteDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "LIDARLite")) diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index 5723c46d8..0228d982b 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -46,7 +46,7 @@ func TestNewMCP23017Driver(t *testing.T) { var di interface{} = NewMCP23017Driver(newI2cTestAdaptor()) d, ok := di.(*MCP23017Driver) if !ok { - t.Errorf("NewMCP23017Driver() should have returned a *MCP23017Driver") + require.Fail(t, "NewMCP23017Driver() should have returned a *MCP23017Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MCP23017")) diff --git a/drivers/i2c/mma7660_driver_test.go b/drivers/i2c/mma7660_driver_test.go index 7f2b05b6a..a58dde978 100644 --- a/drivers/i2c/mma7660_driver_test.go +++ b/drivers/i2c/mma7660_driver_test.go @@ -29,7 +29,7 @@ func TestNewMMA7660Driver(t *testing.T) { var di interface{} = NewMMA7660Driver(newI2cTestAdaptor()) d, ok := di.(*MMA7660Driver) if !ok { - t.Errorf("NewMMA7660Driver() should have returned a *MMA7660Driver") + require.Fail(t, "NewMMA7660Driver() should have returned a *MMA7660Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MMA7660")) diff --git a/drivers/i2c/mpl115a2_driver_test.go b/drivers/i2c/mpl115a2_driver_test.go index 7ae72b516..0b2d94691 100644 --- a/drivers/i2c/mpl115a2_driver_test.go +++ b/drivers/i2c/mpl115a2_driver_test.go @@ -24,7 +24,7 @@ func TestNewMPL115A2Driver(t *testing.T) { var di interface{} = NewMPL115A2Driver(newI2cTestAdaptor()) d, ok := di.(*MPL115A2Driver) if !ok { - t.Errorf("NewMPL115A2Driver() should have returned a *MPL115A2Driver") + require.Fail(t, "NewMPL115A2Driver() should have returned a *MPL115A2Driver") } assert.NotNil(t, d.Connection()) assert.True(t, strings.HasPrefix(d.Name(), "MPL115A2")) diff --git a/drivers/i2c/mpu6050_driver_test.go b/drivers/i2c/mpu6050_driver_test.go index 8ba6a3668..da173cec5 100644 --- a/drivers/i2c/mpu6050_driver_test.go +++ b/drivers/i2c/mpu6050_driver_test.go @@ -28,7 +28,7 @@ func TestNewMPU6050Driver(t *testing.T) { var di interface{} = NewMPU6050Driver(newI2cTestAdaptor()) d, ok := di.(*MPU6050Driver) if !ok { - t.Errorf("NewMPU6050Driver() should have returned a *MPU6050Driver") + require.Fail(t, "NewMPU6050Driver() should have returned a *MPU6050Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.name, "MPU6050")) diff --git a/drivers/i2c/pca9501_driver_test.go b/drivers/i2c/pca9501_driver_test.go index d214f3538..ad60ec4f2 100644 --- a/drivers/i2c/pca9501_driver_test.go +++ b/drivers/i2c/pca9501_driver_test.go @@ -48,7 +48,7 @@ func TestNewPCA9501Driver(t *testing.T) { // assert d, ok := di.(*PCA9501Driver) if !ok { - t.Errorf("NewPCA9501Driver() should have returned a *PCA9501Driver") + require.Fail(t, "NewPCA9501Driver() should have returned a *PCA9501Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "PCA9501")) diff --git a/drivers/i2c/pca953x_driver_test.go b/drivers/i2c/pca953x_driver_test.go index a28e950e7..882554431 100644 --- a/drivers/i2c/pca953x_driver_test.go +++ b/drivers/i2c/pca953x_driver_test.go @@ -29,7 +29,7 @@ func TestNewPCA953xDriver(t *testing.T) { // assert d, ok := di.(*PCA953xDriver) if !ok { - t.Errorf("NewPCA953xDriver() should have returned a *PCA953xDriver") + require.Fail(t, "NewPCA953xDriver() should have returned a *PCA953xDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "PCA953x")) diff --git a/drivers/i2c/pcf8583_driver_test.go b/drivers/i2c/pcf8583_driver_test.go index f91cd3e0c..8b980648c 100644 --- a/drivers/i2c/pcf8583_driver_test.go +++ b/drivers/i2c/pcf8583_driver_test.go @@ -27,7 +27,7 @@ func TestNewPCF8583Driver(t *testing.T) { var di interface{} = NewPCF8583Driver(newI2cTestAdaptor()) d, ok := di.(*PCF8583Driver) if !ok { - t.Errorf("NewPCF8583Driver() should have returned a *PCF8583Driver") + require.Fail(t, "NewPCF8583Driver() should have returned a *PCF8583Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.name, "PCF8583")) diff --git a/drivers/i2c/pcf8591_driver_test.go b/drivers/i2c/pcf8591_driver_test.go index a0eedf1ab..3fd8c91bd 100644 --- a/drivers/i2c/pcf8591_driver_test.go +++ b/drivers/i2c/pcf8591_driver_test.go @@ -28,7 +28,7 @@ func TestNewPCF8591Driver(t *testing.T) { var di interface{} = NewPCF8591Driver(newI2cTestAdaptor()) d, ok := di.(*PCF8591Driver) if !ok { - t.Errorf("NewPCF8591Driver() should have returned a *PCF8591Driver") + require.Fail(t, "NewPCF8591Driver() should have returned a *PCF8591Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "PCF8591")) diff --git a/drivers/i2c/sht2x_driver_test.go b/drivers/i2c/sht2x_driver_test.go index 5c870c63f..9add0b175 100644 --- a/drivers/i2c/sht2x_driver_test.go +++ b/drivers/i2c/sht2x_driver_test.go @@ -28,7 +28,7 @@ func TestNewSHT2xDriver(t *testing.T) { var di interface{} = NewSHT2xDriver(newI2cTestAdaptor()) d, ok := di.(*SHT2xDriver) if !ok { - t.Errorf("NewSHT2xDriver() should have returned a *SHT2xDriver") + require.Fail(t, "NewSHT2xDriver() should have returned a *SHT2xDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "SHT2x")) diff --git a/drivers/i2c/sht3x_driver_test.go b/drivers/i2c/sht3x_driver_test.go index 9174cd544..66aecdc14 100644 --- a/drivers/i2c/sht3x_driver_test.go +++ b/drivers/i2c/sht3x_driver_test.go @@ -28,7 +28,7 @@ func TestNewSHT3xDriver(t *testing.T) { var di interface{} = NewSHT3xDriver(newI2cTestAdaptor()) d, ok := di.(*SHT3xDriver) if !ok { - t.Errorf("NewSHT3xDriver() should have returned a *SHT3xDriver") + require.Fail(t, "NewSHT3xDriver() should have returned a *SHT3xDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "SHT3x")) diff --git a/drivers/i2c/ssd1306_driver_test.go b/drivers/i2c/ssd1306_driver_test.go index 58cec23ef..22e5459dc 100644 --- a/drivers/i2c/ssd1306_driver_test.go +++ b/drivers/i2c/ssd1306_driver_test.go @@ -35,7 +35,7 @@ func TestNewSSD1306Driver(t *testing.T) { var di interface{} = NewSSD1306Driver(newI2cTestAdaptor()) d, ok := di.(*SSD1306Driver) if !ok { - t.Errorf("new should have returned a *SSD1306Driver") + require.Fail(t, "new should have returned a *SSD1306Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "SSD1306")) @@ -271,11 +271,11 @@ func TestDisplayBuffer(t *testing.T) { display := NewDisplayBuffer(width, height, 8) if display.Size() != size { - t.Errorf("invalid Size() (%d, expected %d)", + require.Fail(t, "invalid Size() (%d, expected %d)", display.Size(), size) } if len(display.buffer) != size { - t.Errorf("allocated buffer size invalid (%d, expected %d)", + require.Fail(t, "allocated buffer size invalid (%d, expected %d)", len(display.buffer), size) } diff --git a/drivers/i2c/th02_driver_test.go b/drivers/i2c/th02_driver_test.go index ca8bc5392..dea8c0aea 100644 --- a/drivers/i2c/th02_driver_test.go +++ b/drivers/i2c/th02_driver_test.go @@ -29,7 +29,7 @@ func TestNewTH02Driver(t *testing.T) { var di interface{} = NewTH02Driver(newI2cTestAdaptor()) d, ok := di.(*TH02Driver) if !ok { - t.Errorf("NewTH02Driver() should have returned a *NewTH02Driver") + require.Fail(t, "NewTH02Driver() should have returned a *NewTH02Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "TH02")) @@ -56,7 +56,7 @@ func TestTH02SetAccuracy(t *testing.T) { } if acc := b.Accuracy(); acc != TH02LowAccuracy { - t.Errorf("Accuracy() didn't return what was expected") + require.Fail(t, "Accuracy() didn't return what was expected") } } diff --git a/drivers/i2c/tsl2561_driver_test.go b/drivers/i2c/tsl2561_driver_test.go index 573a2c89f..2e021b350 100644 --- a/drivers/i2c/tsl2561_driver_test.go +++ b/drivers/i2c/tsl2561_driver_test.go @@ -39,7 +39,7 @@ func TestNewTSL2561Driver(t *testing.T) { var di interface{} = NewTSL2561Driver(newI2cTestAdaptor()) d, ok := di.(*TSL2561Driver) if !ok { - t.Errorf("NewTSL2561Driver() should have returned a *TSL2561Driver") + require.Fail(t, "NewTSL2561Driver() should have returned a *TSL2561Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "TSL2561")) diff --git a/drivers/i2c/wiichuck_driver_test.go b/drivers/i2c/wiichuck_driver_test.go index 0f2b40109..82cf3db4a 100644 --- a/drivers/i2c/wiichuck_driver_test.go +++ b/drivers/i2c/wiichuck_driver_test.go @@ -27,7 +27,7 @@ func TestNewWiichuckDriver(t *testing.T) { var di interface{} = NewWiichuckDriver(newI2cTestAdaptor()) d, ok := di.(*WiichuckDriver) if !ok { - t.Errorf("NewWiichuckDriver() should have returned a *WiichuckDriver") + require.Fail(t, "NewWiichuckDriver() should have returned a *WiichuckDriver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "Wiichuck")) @@ -63,7 +63,7 @@ func TestWiichuckDriverStart(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("origin not read correctly") + require.Fail(t, "origin not read correctly") } } @@ -118,7 +118,7 @@ func TestWiichuckDriverCButton(t *testing.T) { select { case <-done: case <-time.After(10 * time.Second): - t.Errorf("Did not receive 'C' event") + require.Fail(t, "Did not receive 'C' event") } } @@ -141,7 +141,7 @@ func TestWiichuckDriverZButton(t *testing.T) { select { case <-done: case <-time.After(10 * time.Second): - t.Errorf("Did not receive 'Z' event") + require.Fail(t, "Did not receive 'Z' event") } } @@ -169,7 +169,7 @@ func TestWiichuckDriverUpdateJoystick(t *testing.T) { select { case <-done: case <-time.After(10 * time.Second): - t.Errorf("Did not receive 'Joystick' event") + require.Fail(t, "Did not receive 'Joystick' event") } } diff --git a/drivers/serial/neurosky/mindwave_driver_test.go b/drivers/serial/neurosky/mindwave_driver_test.go index 4e9eae5f0..5236eccde 100644 --- a/drivers/serial/neurosky/mindwave_driver_test.go +++ b/drivers/serial/neurosky/mindwave_driver_test.go @@ -56,7 +56,7 @@ func TestNeuroskyDriverStart(t *testing.T) { case <-sem: case <-time.After(100 * time.Millisecond): { - t.Errorf("error was not emitted") + require.Fail(t, "error was not emitted") } } @@ -84,7 +84,7 @@ func TestNeuroskyDriverParse(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("Event \"extended\" was not published") + require.Fail(t, "Event \"extended\" was not published") } // mindWaveCodeSignalQuality diff --git a/drivers/spi/apa102_test.go b/drivers/spi/apa102_test.go index 5a032d95d..4bd2156ff 100644 --- a/drivers/spi/apa102_test.go +++ b/drivers/spi/apa102_test.go @@ -28,7 +28,7 @@ func TestNewAPA102Driver(t *testing.T) { var di interface{} = NewAPA102Driver(newSpiTestAdaptor(), 10, 31) d, ok := di.(*APA102Driver) if !ok { - t.Errorf("NewAPA102Driver() should have returned a *APA102Driver") + require.Fail(t, "NewAPA102Driver() should have returned a *APA102Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "APA102")) diff --git a/drivers/spi/mcp3002_test.go b/drivers/spi/mcp3002_test.go index 1b8c5f914..5b4901d65 100644 --- a/drivers/spi/mcp3002_test.go +++ b/drivers/spi/mcp3002_test.go @@ -32,7 +32,7 @@ func TestNewMCP3002Driver(t *testing.T) { var di interface{} = NewMCP3002Driver(newSpiTestAdaptor()) d, ok := di.(*MCP3002Driver) if !ok { - t.Errorf("NewMCP3002Driver() should have returned a *MCP3002Driver") + require.Fail(t, "NewMCP3002Driver() should have returned a *MCP3002Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MCP3002")) diff --git a/drivers/spi/mcp3004_test.go b/drivers/spi/mcp3004_test.go index 2eeb69408..8e4fa3b6f 100644 --- a/drivers/spi/mcp3004_test.go +++ b/drivers/spi/mcp3004_test.go @@ -32,7 +32,7 @@ func TestNewMCP3004Driver(t *testing.T) { var di interface{} = NewMCP3004Driver(newSpiTestAdaptor()) d, ok := di.(*MCP3004Driver) if !ok { - t.Errorf("NewMCP3004Driver() should have returned a *MCP3004Driver") + require.Fail(t, "NewMCP3004Driver() should have returned a *MCP3004Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MCP3004")) diff --git a/drivers/spi/mcp3008_test.go b/drivers/spi/mcp3008_test.go index 6c85a9b91..a28941e4b 100644 --- a/drivers/spi/mcp3008_test.go +++ b/drivers/spi/mcp3008_test.go @@ -32,7 +32,7 @@ func TestNewMCP3008Driver(t *testing.T) { var di interface{} = NewMCP3008Driver(newSpiTestAdaptor()) d, ok := di.(*MCP3008Driver) if !ok { - t.Errorf("NewMCP3008Driver() should have returned a *MCP3008Driver") + require.Fail(t, "NewMCP3008Driver() should have returned a *MCP3008Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MCP3008")) diff --git a/drivers/spi/mcp3202_test.go b/drivers/spi/mcp3202_test.go index 15729617f..c60651702 100644 --- a/drivers/spi/mcp3202_test.go +++ b/drivers/spi/mcp3202_test.go @@ -32,7 +32,7 @@ func TestNewMCP3202Driver(t *testing.T) { var di interface{} = NewMCP3202Driver(newSpiTestAdaptor()) d, ok := di.(*MCP3202Driver) if !ok { - t.Errorf("NewMCP3202Driver() should have returned a *MCP3202Driver") + require.Fail(t, "NewMCP3202Driver() should have returned a *MCP3202Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MCP3202")) diff --git a/drivers/spi/mcp3204_test.go b/drivers/spi/mcp3204_test.go index 11fc103e3..358818cfd 100644 --- a/drivers/spi/mcp3204_test.go +++ b/drivers/spi/mcp3204_test.go @@ -32,7 +32,7 @@ func TestNewMCP3204Driver(t *testing.T) { var di interface{} = NewMCP3204Driver(newSpiTestAdaptor()) d, ok := di.(*MCP3204Driver) if !ok { - t.Errorf("NewMCP3204Driver() should have returned a *MCP3204Driver") + require.Fail(t, "NewMCP3204Driver() should have returned a *MCP3204Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MCP3204")) diff --git a/drivers/spi/mcp3208_test.go b/drivers/spi/mcp3208_test.go index 7bfe0d32f..ca3defa1f 100644 --- a/drivers/spi/mcp3208_test.go +++ b/drivers/spi/mcp3208_test.go @@ -32,7 +32,7 @@ func TestNewMCP3208Driver(t *testing.T) { var di interface{} = NewMCP3208Driver(newSpiTestAdaptor()) d, ok := di.(*MCP3208Driver) if !ok { - t.Errorf("NewMCP3208Driver() should have returned a *MCP3208Driver") + require.Fail(t, "NewMCP3208Driver() should have returned a *MCP3208Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MCP3208")) diff --git a/drivers/spi/mcp3304_test.go b/drivers/spi/mcp3304_test.go index e928795fe..ccadf86ff 100644 --- a/drivers/spi/mcp3304_test.go +++ b/drivers/spi/mcp3304_test.go @@ -32,7 +32,7 @@ func TestNewMCP3304Driver(t *testing.T) { var di interface{} = NewMCP3304Driver(newSpiTestAdaptor()) d, ok := di.(*MCP3304Driver) if !ok { - t.Errorf("NewMCP3304Driver() should have returned a *MCP3304Driver") + require.Fail(t, "NewMCP3304Driver() should have returned a *MCP3304Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MCP3304")) diff --git a/drivers/spi/mfrc522_driver_test.go b/drivers/spi/mfrc522_driver_test.go index 1bd88baca..9e0b315ef 100644 --- a/drivers/spi/mfrc522_driver_test.go +++ b/drivers/spi/mfrc522_driver_test.go @@ -29,7 +29,7 @@ func TestNewMFRC522Driver(t *testing.T) { var di interface{} = NewMFRC522Driver(newSpiTestAdaptor()) d, ok := di.(*MFRC522Driver) if !ok { - t.Errorf("NewMFRC522Driver() should have returned a *MFRC522Driver") + require.Fail(t, "NewMFRC522Driver() should have returned a *MFRC522Driver") } assert.NotNil(t, d.Driver) assert.True(t, strings.HasPrefix(d.Name(), "MFRC522")) diff --git a/drivers/spi/spi_driver_test.go b/drivers/spi/spi_driver_test.go index 9f35c5591..288346adc 100644 --- a/drivers/spi/spi_driver_test.go +++ b/drivers/spi/spi_driver_test.go @@ -25,7 +25,7 @@ func TestNewDriver(t *testing.T) { var di interface{} = NewDriver(newSpiTestAdaptor(), "SPI_BASIC") d, ok := di.(*Driver) if !ok { - t.Errorf("NewDriver() should have returned a *Driver") + require.Fail(t, "NewDriver() should have returned a *Driver") } assert.True(t, strings.HasPrefix(d.Name(), "SPI_BASIC")) } diff --git a/eventer_test.go b/eventer_test.go index d91554242..2a58f5ede 100644 --- a/eventer_test.go +++ b/eventer_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestEventerAddEvent(t *testing.T) { @@ -12,9 +13,10 @@ func TestEventerAddEvent(t *testing.T) { e.AddEvent("test") if _, ok := e.Events()["test"]; !ok { - t.Errorf("Could not add event to list of Event names") + require.Fail(t, "Could not add event to list of Event names") } assert.Equal(t, "test", e.Event("test")) + assert.Equal(t, "", e.Event("unknown")) } func TestEventerDeleteEvent(t *testing.T) { @@ -23,56 +25,54 @@ func TestEventerDeleteEvent(t *testing.T) { e.DeleteEvent("test1") if _, ok := e.Events()["test1"]; ok { - t.Errorf("Could not add delete event from list of Event names") + require.Fail(t, "Could not add delete event from list of Event names") } } func TestEventerOn(t *testing.T) { e := NewEventer() - e.AddEvent("test") sem := make(chan bool) _ = e.On("test", func(data interface{}) { sem <- true }) - go func() { - e.Publish("test", true) - }() + // wait some time to ensure the eventer go routine is working + time.Sleep(10 * time.Millisecond) + + e.Publish("test", true) select { case <-sem: case <-time.After(10 * time.Millisecond): - t.Errorf("On was not called") + require.Fail(t, "On was not called") } } func TestEventerOnce(t *testing.T) { e := NewEventer() - e.AddEvent("test") sem := make(chan bool) _ = e.Once("test", func(data interface{}) { sem <- true }) - go func() { - e.Publish("test", true) - }() + // wait some time to ensure the eventer go routine is working + time.Sleep(10 * time.Millisecond) + + e.Publish("test", true) select { case <-sem: case <-time.After(10 * time.Millisecond): - t.Errorf("Once was not called") + require.Fail(t, "Once was not called") } - go func() { - e.Publish("test", true) - }() + e.Publish("test", true) select { case <-sem: - t.Errorf("Once was called twice") + require.Fail(t, "Once was called twice") case <-time.After(10 * time.Millisecond): } } diff --git a/platforms/dji/tello/driver_test.go b/platforms/dji/tello/driver_test.go index cef8c2c08..90ec280d5 100644 --- a/platforms/dji/tello/driver_test.go +++ b/platforms/dji/tello/driver_test.go @@ -123,12 +123,12 @@ func Test_handleResponse(t *testing.T) { t.Error("subscription channel is closed") } if ev.Name != tc.wantEvent { - t.Errorf("\ngot: %s\nwant: %s\n", ev.Name, tc.wantEvent) + require.Fail(t, "\ngot: %s\nwant: %s\n", ev.Name, tc.wantEvent) } got := fmt.Sprintf("%T %+[1]v", ev.Data) want := fmt.Sprintf("%T %+[1]v", tc.wantData) if got != want { - t.Errorf("\ngot: %s\nwant: %s\n", got, want) + require.Fail(t, "\ngot: %s\nwant: %s\n", got, want) } case <-time.After(time.Millisecond): t.Error("subscription channel seems empty") diff --git a/platforms/firmata/client/client_test.go b/platforms/firmata/client/client_test.go index 63f08457b..c903b6374 100644 --- a/platforms/firmata/client/client_test.go +++ b/platforms/firmata/client/client_test.go @@ -149,7 +149,7 @@ func TestProcessProtocolVersion(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("ProtocolVersion was not published") + require.Fail(t, "ProtocolVersion was not published") } } @@ -168,7 +168,7 @@ func TestProcessAnalogRead0(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("AnalogRead0 was not published") + require.Fail(t, "AnalogRead0 was not published") } } @@ -187,7 +187,7 @@ func TestProcessAnalogRead1(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("AnalogRead1 was not published") + require.Fail(t, "AnalogRead1 was not published") } } @@ -207,7 +207,7 @@ func TestProcessDigitalRead2(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("DigitalRead2 was not published") + require.Fail(t, "DigitalRead2 was not published") } } @@ -227,7 +227,7 @@ func TestProcessDigitalRead4(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("DigitalRead4 was not published") + require.Fail(t, "DigitalRead4 was not published") } } @@ -267,7 +267,7 @@ func TestProcessPinState13(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("PinState13 was not published") + require.Fail(t, "PinState13 was not published") } } @@ -310,7 +310,7 @@ func TestProcessI2cReply(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("I2cReply was not published") + require.Fail(t, "I2cReply was not published") } } @@ -329,7 +329,7 @@ func TestProcessFirmwareQuery(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("FirmwareQuery was not published") + require.Fail(t, "FirmwareQuery was not published") } } @@ -348,7 +348,7 @@ func TestProcessStringData(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("StringData was not published") + require.Fail(t, "StringData was not published") } } @@ -433,6 +433,6 @@ func TestProcessSysexData(t *testing.T) { select { case <-sem: case <-time.After(semPublishWait): - t.Errorf("SysexResponse was not published") + require.Fail(t, "SysexResponse was not published") } } diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index 48965d3db..0f1f72b0f 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -56,7 +56,7 @@ func TestDriverHandleEventDS3(t *testing.T) { tj.buttonCount = 17 if err := d.initConfig(); err != nil { - t.Errorf("initConfig() error: %v", err) + require.Fail(t, "initConfig() error: %v", err) } d.initEvents() @@ -73,7 +73,7 @@ func TestDriverHandleEventDS3(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"left_x\" was not published") + require.Fail(t, "Button Event \"left_x\" was not published") } // square button press @@ -87,7 +87,7 @@ func TestDriverHandleEventDS3(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"square_press\" was not published") + require.Fail(t, "Button Event \"square_press\" was not published") } // square button release @@ -101,7 +101,7 @@ func TestDriverHandleEventDS3(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"square_release\" was not published") + require.Fail(t, "Button Event \"square_release\" was not published") } } @@ -112,7 +112,7 @@ func TestDriverHandleEventJSONDS3(t *testing.T) { tj.buttonCount = 17 if err := d.initConfig(); err != nil { - t.Errorf("initConfig() error: %v", err) + require.Fail(t, "initConfig() error: %v", err) } d.initEvents() @@ -129,7 +129,7 @@ func TestDriverHandleEventJSONDS3(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"left_x\" was not published") + require.Fail(t, "Button Event \"left_x\" was not published") } // square button press @@ -143,7 +143,7 @@ func TestDriverHandleEventJSONDS3(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"square_press\" was not published") + require.Fail(t, "Button Event \"square_press\" was not published") } // square button release @@ -157,7 +157,7 @@ func TestDriverHandleEventJSONDS3(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"square_release\" was not published") + require.Fail(t, "Button Event \"square_release\" was not published") } } @@ -168,7 +168,7 @@ func TestDriverHandleEventDS4(t *testing.T) { tj.buttonCount = 17 if err := d.initConfig(); err != nil { - t.Errorf("initConfig() error: %v", err) + require.Fail(t, "initConfig() error: %v", err) } d.initEvents() @@ -185,7 +185,7 @@ func TestDriverHandleEventDS4(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"left_x\" was not published") + require.Fail(t, "Button Event \"left_x\" was not published") } // square button press @@ -199,7 +199,7 @@ func TestDriverHandleEventDS4(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"square_press\" was not published") + require.Fail(t, "Button Event \"square_press\" was not published") } // square button release @@ -213,7 +213,7 @@ func TestDriverHandleEventDS4(t *testing.T) { select { case <-sem: case <-time.After(1 * time.Second): - t.Errorf("Button Event \"square_release\" was not published") + require.Fail(t, "Button Event \"square_release\" was not published") } } diff --git a/platforms/leap/leap_motion_driver_test.go b/platforms/leap/leap_motion_driver_test.go index f7ecb0f5b..daee1d0ee 100644 --- a/platforms/leap/leap_motion_driver_test.go +++ b/platforms/leap/leap_motion_driver_test.go @@ -90,7 +90,7 @@ func TestLeapMotionDriverParser(t *testing.T) { parsedFrame, _ := d.ParseFrame(file) if parsedFrame.Hands == nil || parsedFrame.Pointables == nil || parsedFrame.Gestures == nil { - t.Errorf("ParseFrame incorrectly parsed frame") + require.Fail(t, "ParseFrame incorrectly parsed frame") } assert.Equal(t, uint64(134211791358), parsedFrame.Timestamp) diff --git a/platforms/mavlink/mavlink_driver_test.go b/platforms/mavlink/mavlink_driver_test.go index abc0a675e..f1efef54b 100644 --- a/platforms/mavlink/mavlink_driver_test.go +++ b/platforms/mavlink/mavlink_driver_test.go @@ -69,17 +69,17 @@ func TestMavlinkDriverStart(t *testing.T) { require.NoError(t, d.SendPacket(p)) case <-time.After(100 * time.Millisecond): - t.Errorf("packet was not emitted") + require.Fail(t, "packet was not emitted") } select { case <-message: case <-time.After(100 * time.Millisecond): - t.Errorf("message was not emitted") + require.Fail(t, "message was not emitted") } select { case <-err: case <-time.After(100 * time.Millisecond): - t.Errorf("error was not emitted") + require.Fail(t, "error was not emitted") } } diff --git a/platforms/opencv/camera_driver_test.go b/platforms/opencv/camera_driver_test.go index 9a475bcc9..81ecacb7f 100644 --- a/platforms/opencv/camera_driver_test.go +++ b/platforms/opencv/camera_driver_test.go @@ -45,7 +45,7 @@ func TestCameraDriverStart(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("Event \"frame\" was not published") + require.Fail(t, "Event \"frame\" was not published") } d = NewCameraDriver("") diff --git a/platforms/particle/adaptor_test.go b/platforms/particle/adaptor_test.go index ee79d51ec..69fc29675 100644 --- a/platforms/particle/adaptor_test.go +++ b/platforms/particle/adaptor_test.go @@ -29,7 +29,7 @@ func getDummyResponseForPath(t *testing.T, path string, dummyResponse string) *h return createTestServer(func(w http.ResponseWriter, r *http.Request) { actualPath := "/v1/devices" + path if r.URL.Path != actualPath { - t.Errorf("Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path) + require.Fail(t, "Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path) } _, _ = w.Write(dummyData) }) @@ -48,7 +48,7 @@ func getDummyResponseForPathWithParams( return createTestServer(func(w http.ResponseWriter, r *http.Request) { actualPath := "/v1/devices" + path if r.URL.Path != actualPath { - t.Errorf("Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path) + require.Fail(t, "Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path) } _ = r.ParseForm() @@ -78,7 +78,7 @@ func TestAdaptor(t *testing.T) { var a interface{} = initTestAdaptor() _, ok := a.(gobot.Adaptor) if !ok { - t.Errorf("Adaptor{} should be a gobot.Adaptor") + require.Fail(t, "Adaptor{} should be a gobot.Adaptor") } } @@ -87,7 +87,7 @@ func TestNewAdaptor(t *testing.T) { var a interface{} = initTestAdaptor() core, ok := a.(*Adaptor) if !ok { - t.Errorf("NewAdaptor() should have returned a *Adaptor") + require.Fail(t, "NewAdaptor() should have returned a *Adaptor") } assert.Equal(t, "https://api.particle.io", core.APIServer) diff --git a/platforms/pebble/pebble_driver_test.go b/platforms/pebble/pebble_driver_test.go index 1c6d1ae4a..b770021c8 100644 --- a/platforms/pebble/pebble_driver_test.go +++ b/platforms/pebble/pebble_driver_test.go @@ -50,7 +50,7 @@ func TestDriver(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("Button Event was not published") + require.Fail(t, "Button Event was not published") } _ = d.On(d.Event("accel"), func(data interface{}) { @@ -62,7 +62,7 @@ func TestDriver(t *testing.T) { select { case <-sem: case <-time.After(100 * time.Millisecond): - t.Errorf("Accel Event was not published") + require.Fail(t, "Accel Event was not published") } d.Command("send_notification")(map[string]interface{}{"message": "Hey buddy!"}) diff --git a/utils_test.go b/utils_test.go index 19238a501..3dc0cf690 100644 --- a/utils_test.go +++ b/utils_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestEvery(t *testing.T) { @@ -35,7 +36,7 @@ func TestEveryWhenStopped(t *testing.T) { done.Stop() case <-time.After(190 * time.Millisecond): done.Stop() - t.Errorf("Every was not called") + require.Fail(t, "Every was not called") } select { @@ -57,7 +58,7 @@ func TestAfter(t *testing.T) { select { case <-sem: case <-time.After(190 * time.Millisecond): - t.Errorf("After was not called") + require.Fail(t, "After was not called") } assert.Equal(t, 1, i) @@ -82,7 +83,7 @@ func TestRand(t *testing.T) { a := Rand(10000) b := Rand(10000) if a == b { - t.Errorf("%v should not equal %v", a, b) + require.Fail(t, "%v should not equal %v", a, b) } } From 1a66f4b44d866a1499b81cba5ff0582851368d8b Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 13 Feb 2024 12:06:59 +0100 Subject: [PATCH 48/57] build(go, deps): switch to Go 1.20 and update modules (#1067) --- .circleci/config.yml | 6 +++--- .github/workflows/golangci-lint.yml | 2 +- go.mod | 16 ++++++++-------- go.sum | 28 ++++++++++++++-------------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6ccfb5b0d..749a8d123 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ version: 2 jobs: "test_core_and_drivers_with_coverage": docker: - - image: cimg/go:1.19 + - image: cimg/go:1.20 steps: - checkout - run: @@ -31,7 +31,7 @@ jobs: "test_platforms": docker: - - image: cimg/go:1.19 + - image: cimg/go:1.20 steps: - checkout - run: @@ -45,7 +45,7 @@ jobs: "check_examples": docker: - - image: cimg/go:1.19 + - image: cimg/go:1.20 steps: - checkout - run: diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index dd454656b..0e7a965c6 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '1.19' + go-version: '1.20' cache: false - name: golangci-lint uses: golangci/golangci-lint-action@v3 diff --git a/go.mod b/go.mod index 8a5b93b70..d00bf9181 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module gobot.io/x/gobot/v2 -go 1.19 +go 1.20 require ( github.com/0xcafed00d/joystick v1.0.1 @@ -11,15 +11,15 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e - github.com/nats-io/nats.go v1.31.0 + github.com/nats-io/nats.go v1.32.0 github.com/nsf/termbox-go v1.1.1 github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f github.com/stretchr/testify v1.8.4 github.com/warthog618/gpiod v0.8.2 go.bug.st/serial v1.6.1 gocv.io/x/gocv v0.35.0 - golang.org/x/net v0.19.0 - golang.org/x/sys v0.16.0 + golang.org/x/net v0.21.0 + golang.org/x/sys v0.17.0 periph.io/x/conn/v3 v3.7.0 periph.io/x/host/v3 v3.8.2 tinygo.org/x/bluetooth v0.8.0 @@ -33,16 +33,16 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.4 // indirect + github.com/klauspost/compress v1.17.6 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 // indirect + github.com/muka/go-bluetooth v0.0.0-20240115085408-dfdf79b8f61d // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/saltosystems/winrt-go v0.0.0-20231011131235-9071442c0c84 // indirect + github.com/saltosystems/winrt-go v0.0.0-20240110120258-ad49e9790c38 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/tinygo-org/cbgo v0.0.4 // indirect - golang.org/x/crypto v0.17.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/sync v0.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5a87cda0a..d6278d132 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 h1:7of6LJZ4 github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78/go.mod h1:YllNbhGM1UEcySxCv1BWK5lre7QLmJJ+O0ADUOo2nbc= github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e h1:xCcwD5FOXul+j1dn8xD16nbrhJkkum/Cn+jTd/u1LhY= github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM805MRKrioHYuU7iKLUyFPVKqVV6um5DAvCkUtXs= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= +github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -41,10 +41,10 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 h1:BuVRHr4HHJbk1DHyWkArJ7E8J/VA8ncCr/VLnQFazBo= -github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= -github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= -github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= +github.com/muka/go-bluetooth v0.0.0-20240115085408-dfdf79b8f61d h1:7ZjEBZo3QkT5hu4koEPrNJ5SKQ2NdHjpB+uJpxUcWDc= +github.com/muka/go-bluetooth v0.0.0-20240115085408-dfdf79b8f61d/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= +github.com/nats-io/nats.go v1.32.0 h1:Bx9BZS+aXYlxW08k8Gd3yR2s73pV5XSoAQUyp1Kwvp0= +github.com/nats-io/nats.go v1.32.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -59,8 +59,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/saltosystems/winrt-go v0.0.0-20231011131235-9071442c0c84 h1:LX7qSkrsG8fKKVubiUnqfGdi/yBBnVTBR13LkqXycog= -github.com/saltosystems/winrt-go v0.0.0-20231011131235-9071442c0c84/go.mod h1:CIltaIm7qaANUIvzr0Vmz71lmQMAIbGJ7cvgzX7FMfA= +github.com/saltosystems/winrt-go v0.0.0-20240110120258-ad49e9790c38 h1:YcsdT0vhLMBWScwoO9FHZdjcFqjIWfQENMzq0PNxODs= +github.com/saltosystems/winrt-go v0.0.0-20240110120258-ad49e9790c38/go.mod h1:CIltaIm7qaANUIvzr0Vmz71lmQMAIbGJ7cvgzX7FMfA= github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f h1:1R9KdKjCNSd7F8iGTxIpoID9prlYH8nuNYKt0XvweHA= github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f/go.mod h1:vQhwQ4meQEDfahT5kd61wLAF5AAeh5ZPLVI4JJ/tYo8= github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= @@ -87,14 +87,14 @@ gocv.io/x/gocv v0.35.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= @@ -106,8 +106,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= From d76143ccb88b74bfc13468843aeb318f49d89354 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 13 Feb 2024 14:19:03 +0100 Subject: [PATCH 49/57] build(linter): update linter to v1.56.1 and fix issues (#1068) --- .circleci/config.yml | 2 +- .github/workflows/golangci-lint.yml | 2 +- .golangci.yml | 8 ++++++++ drivers/aio/temperature_sensor_driver_test.go | 9 +++++---- drivers/i2c/ads1x15_driver_test.go | 8 ++++---- drivers/i2c/wiichuck_driver_test.go | 4 ++-- platforms/joystick/bin/scanner.go | 2 +- platforms/joystick/joystick_driver.go | 8 ++++---- platforms/parrot/bebop/client/client.go | 2 -- robot_test.go | 9 ++++++++- 10 files changed, 34 insertions(+), 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 749a8d123..168a145fb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -61,7 +61,7 @@ jobs: "fmt_check_examples": docker: - - image: golangci/golangci-lint:v1.55.2 + - image: golangci/golangci-lint:v1.56.1 steps: - checkout - run: diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 0e7a965c6..e1489e644 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -24,7 +24,7 @@ jobs: uses: golangci/golangci-lint-action@v3 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.55.2 + version: v1.56.1 # Optional: working directory, useful for monorepos # working-directory: v2 diff --git a/.golangci.yml b/.golangci.yml index cced8fe17..f826bb4c0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -168,6 +168,14 @@ linters-settings: # Default: false require-specific: true + perfsprint: + # Optimizes `fmt.Errorf`. + # Default: true + errorf: false + # Optimizes `fmt.Sprintf` with only one argument + # Default: true + sprintf1: false + revive: rules: # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return diff --git a/drivers/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go index 43857b1fa..a1662c1bb 100644 --- a/drivers/aio/temperature_sensor_driver_test.go +++ b/drivers/aio/temperature_sensor_driver_test.go @@ -184,16 +184,17 @@ func TestTemperatureSensorWithSensorCyclicRead_PublishesError(t *testing.T) { func TestTemperatureSensorHalt_WithSensorCyclicRead(t *testing.T) { // arrange d := NewTemperatureSensorDriver(newAioTestAdaptor(), "1", WithSensorCyclicRead(10*time.Millisecond)) - done := make(chan struct{}) require.NoError(t, d.Start()) + errChan := make(chan error, 1) // act & assert go func() { - require.NoError(t, d.Halt()) - close(done) + errChan <- d.Halt() }() + // test that the halt is not blocked by any deadlock with mutex and/or channel select { - case <-done: + case err := <-errChan: + require.NoError(t, err) case <-time.After(100 * time.Millisecond): require.Fail(t, "Temperature Sensor was not halted") } diff --git a/drivers/i2c/ads1x15_driver_test.go b/drivers/i2c/ads1x15_driver_test.go index ba524af5b..6df3ea8f4 100644 --- a/drivers/i2c/ads1x15_driver_test.go +++ b/drivers/i2c/ads1x15_driver_test.go @@ -51,7 +51,7 @@ func TestADS1x15CommandsReadDifferenceWithDefaults(t *testing.T) { result := d.Command("ReadDifferenceWithDefaults")(ads1x15TestChannel) // assert assert.Nil(t, result.(map[string]interface{})["err"]) - assert.Equal(t, -4.096, result.(map[string]interface{})["val"]) + assert.InDelta(t, -4.096, result.(map[string]interface{})["val"], 0.0) } func TestADS1x15CommandsReadDifference(t *testing.T) { @@ -61,7 +61,7 @@ func TestADS1x15CommandsReadDifference(t *testing.T) { result := d.Command("ReadDifference")(ads1x15TestChannelGainDataRate) // assert assert.Nil(t, result.(map[string]interface{})["err"]) - assert.Equal(t, -2.048, result.(map[string]interface{})["val"]) + assert.InDelta(t, -2.048, result.(map[string]interface{})["val"], 0.0) } func TestADS1x15CommandsReadWithDefaults(t *testing.T) { @@ -71,7 +71,7 @@ func TestADS1x15CommandsReadWithDefaults(t *testing.T) { result := d.Command("ReadWithDefaults")(ads1x15TestChannel) // assert assert.Nil(t, result.(map[string]interface{})["err"]) - assert.Equal(t, -4.096, result.(map[string]interface{})["val"]) + assert.InDelta(t, -4.096, result.(map[string]interface{})["val"], 0.0) } func TestADS1x15CommandsRead(t *testing.T) { @@ -81,7 +81,7 @@ func TestADS1x15CommandsRead(t *testing.T) { result := d.Command("Read")(ads1x15TestChannelGainDataRate) // assert assert.Nil(t, result.(map[string]interface{})["err"]) - assert.Equal(t, -2.048, result.(map[string]interface{})["val"]) + assert.InDelta(t, -2.048, result.(map[string]interface{})["val"], 0.0) } func TestADS1x15CommandsAnalogRead(t *testing.T) { diff --git a/drivers/i2c/wiichuck_driver_test.go b/drivers/i2c/wiichuck_driver_test.go index 82cf3db4a..654c7ced2 100644 --- a/drivers/i2c/wiichuck_driver_test.go +++ b/drivers/i2c/wiichuck_driver_test.go @@ -109,7 +109,7 @@ func TestWiichuckDriverCButton(t *testing.T) { done := make(chan bool) _ = d.On(d.Event(C), func(data interface{}) { - assert.Equal(t, true, data) //nolint:testifylint // data is an interface + assert.Equal(t, true, data) done <- true }) @@ -132,7 +132,7 @@ func TestWiichuckDriverZButton(t *testing.T) { done := make(chan bool) _ = d.On(d.Event(Z), func(data interface{}) { - assert.Equal(t, true, data) //nolint:testifylint // data is an interface + assert.Equal(t, true, data) done <- true }) diff --git a/platforms/joystick/bin/scanner.go b/platforms/joystick/bin/scanner.go index 2940ed605..6bda8e447 100644 --- a/platforms/joystick/bin/scanner.go +++ b/platforms/joystick/bin/scanner.go @@ -99,7 +99,7 @@ func main() { case <-ticker.C: printAt(1, 0, "-- Press 'q' to Exit --") - printAt(1, 1, fmt.Sprintf("Joystick Name: %s", js.Name())) + printAt(1, 1, fmt.Sprintf("Joystick Name: %s", js.Name())) //nolint:perfsprint // ok here printAt(1, 2, fmt.Sprintf(" Axis Count: %d", js.AxisCount())) printAt(1, 3, fmt.Sprintf(" Button Count: %d", js.ButtonCount())) readJoystick(js) diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index 3af42505e..22b254149 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -189,8 +189,8 @@ func (j *Driver) initConfig() error { func (j *Driver) initEvents() { for _, value := range j.config.Buttons { - j.AddEvent(fmt.Sprintf("%s_press", value.Name)) - j.AddEvent(fmt.Sprintf("%s_release", value.Name)) + j.AddEvent(fmt.Sprintf("%s_press", value.Name)) //nolint:perfsprint // ok here + j.AddEvent(fmt.Sprintf("%s_release", value.Name)) //nolint:perfsprint // ok here } for _, value := range j.config.Axis { j.AddEvent(value.Name) @@ -214,9 +214,9 @@ func (j *Driver) handleButtons(state js.State) error { } if buttonPressed { - j.Publish(j.Event(fmt.Sprintf("%s_press", name)), nil) + j.Publish(j.Event(fmt.Sprintf("%s_press", name)), nil) //nolint:perfsprint // ok here } else { - j.Publish(j.Event(fmt.Sprintf("%s_release", name)), nil) + j.Publish(j.Event(fmt.Sprintf("%s_release", name)), nil) //nolint:perfsprint // ok here } } } diff --git a/platforms/parrot/bebop/client/client.go b/platforms/parrot/bebop/client/client.go index 6813fe773..fc4c391c6 100644 --- a/platforms/parrot/bebop/client/client.go +++ b/platforms/parrot/bebop/client/client.go @@ -194,7 +194,6 @@ func (b *Bebop) Discover() error { data := make([]byte, 10240) _, err = b.discoveryClient.Read(data) - if err != nil { return err } @@ -214,7 +213,6 @@ func (b *Bebop) Connect() error { } b.c2dClient, err = net.DialUDP("udp", nil, c2daddr) - if err != nil { return err } diff --git a/robot_test.go b/robot_test.go index 2c7571621..15d4765a7 100644 --- a/robot_test.go +++ b/robot_test.go @@ -55,8 +55,9 @@ func TestRobotStartAutoRun(t *testing.T) { // work, ) + errChan := make(chan error, 1) go func() { - require.NoError(t, r.Start()) + errChan <- r.Start() // if no strange things happen, this runs until os.signal occurs }() time.Sleep(10 * time.Millisecond) @@ -65,4 +66,10 @@ func TestRobotStartAutoRun(t *testing.T) { // stop it require.NoError(t, r.Stop()) assert.False(t, r.Running()) + select { + case err := <-errChan: + require.NoError(t, err) + case <-time.After(10 * time.Millisecond): + // because the Start() will run forever, until os.Signal, this is ok here + } } From 27d0b2164c1929b85f7332ec9b84419fb34d2317 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 13 Feb 2024 15:58:31 +0100 Subject: [PATCH 50/57] doc: update links to release or tagged branch (#1069) --- CONTRIBUTING.md | 5 +- README.md | 102 +++++++++--------- api/basic_auth.go | 2 +- drivers/aio/doc.go | 2 +- drivers/ble/sphero/doc.go | 6 +- .../spherocommon/spherocommon_packets.go | 11 +- drivers/gpio/doc.go | 2 +- drivers/i2c/doc.go | 2 +- drivers/i2c/grovepi_driver.go | 4 +- drivers/i2c/mpl115a2_driver_test.go | 2 +- drivers/i2c/sht2x_driver.go | 8 +- drivers/serial/doc.go | 2 +- drivers/spi/doc.go | 2 +- platforms/audio/doc.go | 2 +- platforms/beaglebone/doc.go | 2 +- platforms/bleclient/doc.go | 2 +- platforms/chip/doc.go | 2 +- platforms/dexter/dexter.go | 2 +- platforms/digispark/doc.go | 2 +- platforms/dragonboard/doc.go | 2 +- platforms/firmata/doc.go | 2 +- platforms/intel-iot/curie/README.md | 16 ++- platforms/intel-iot/curie/doc.go | 2 +- platforms/intel-iot/edison/doc.go | 2 +- platforms/intel-iot/intel-iot.go | 2 +- platforms/intel-iot/joule/doc.go | 2 +- platforms/jetson/doc.go | 2 +- platforms/joystick/doc.go | 2 +- platforms/keyboard/doc.go | 2 +- platforms/leap/doc.go | 2 +- platforms/mavlink/doc.go | 2 +- platforms/megapi/doc.go | 2 +- platforms/mqtt/doc.go | 2 +- platforms/nanopi/doc.go | 2 +- platforms/nats/doc.go | 2 +- platforms/opencv/doc.go | 2 +- platforms/parrot/ardrone/doc.go | 2 +- platforms/parrot/bebop/doc.go | 2 +- platforms/particle/doc.go | 2 +- platforms/pebble/doc.go | 2 +- platforms/raspi/doc.go | 2 +- platforms/rockpi/doc.go | 2 +- platforms/serialport/README.md | 4 +- platforms/serialport/doc.go | 2 +- platforms/tinkerboard/doc.go | 2 +- platforms/upboard/up2/doc.go | 2 +- platforms/upboard/upboard.go | 2 +- 47 files changed, 116 insertions(+), 118 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a86a9ff4d..179d186d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,8 +29,7 @@ Descriptions for each of these will eventually be provided below. ## General Guidelines -* All active development is in the `dev` branch. New or updated features must be added to the `dev` branch. Hotfixes - will be considered on the `master` branch in situations where it does not alter behavior or features, only fixes a bug. +* All active development is in the `dev` branch. New or updated features must be added to the `dev` branch. * All patches must be provided under the Apache 2.0 License * Please use the -S option in git to "sign off" that the commit is your work and you are providing it under the Apache 2.0 License @@ -142,4 +141,4 @@ Gobot is released with a Contributor Code of Conduct. By participating in this p ## Origins -This document is based on the original [io.js contribution guidelines](https://github.com/nodejs/io.js/blob/master/CONTRIBUTING.md) +This document is based on the original [io.js contribution guidelines](https://github.com/nodejs/io.js/blob/main/CONTRIBUTING.md) diff --git a/README.md b/README.md index 55fe6232c..f4d720fc2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/ix29evnbdrhkr7ud/branch/dev?svg=true)](https://ci.appveyor.com/project/deadprogram/gobot/branch/dev) [![codecov](https://codecov.io/gh/hybridgroup/gobot/branch/dev/graph/badge.svg)](https://codecov.io/gh/hybridgroup/gobot) [![Go Report Card](https://goreportcard.com/badge/hybridgroup/gobot)](https://goreportcard.com/report/hybridgroup/gobot) -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/hybridgroup/gobot/blob/master/LICENSE.txt) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/hybridgroup/gobot/blob/release/LICENSE.txt) Gobot () is a framework using the Go programming language () for robotics, physical computing, and the Internet of Things. @@ -241,52 +241,52 @@ func main() { Gobot has a extensible system for connecting to hardware devices. The following robotics and physical computing platforms are currently supported: -- [Arduino](http://www.arduino.cc/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/firmata) -- Audio <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/audio) -- [Beaglebone Black](http://beagleboard.org/boards) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/beaglebone) -- [Beaglebone PocketBeagle](http://beagleboard.org/pocket/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/beaglebone) -- [Bluetooth LE](https://www.bluetooth.com/what-is-bluetooth-technology/bluetooth-technology-basics/low-energy) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/bleclient) -- [C.H.I.P](http://www.nextthing.co/pages/chip) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/chip) -- [C.H.I.P Pro](https://docs.getchip.com/chip_pro.html) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/chip) -- [Digispark](http://digistump.com/products/1) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/digispark) -- [DJI Tello](https://www.ryzerobotics.com/tello) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/dji/tello) -- [DragonBoard](https://developer.qualcomm.com/hardware/dragonboard-410c) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/dragonboard) -- [ESP8266](http://esp8266.net/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/firmata) -- [GoPiGo 3](https://www.dexterindustries.com/gopigo3/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/dexter/gopigo3) -- [Intel Curie](https://www.intel.com/content/www/us/en/products/boards-kits/curie.html) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/intel-iot/curie) -- [Intel Edison](http://www.intel.com/content/www/us/en/do-it-yourself/edison.html) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/intel-iot/edison) -- [Intel Joule](http://intel.com/joule/getstarted) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/intel-iot/joule) -- [Jetson Nano](https://developer.nvidia.com/embedded/jetson-nano/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/jetson) -- [Joystick](http://en.wikipedia.org/wiki/Joystick) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/joystick) -- [Keyboard](https://en.wikipedia.org/wiki/Computer_keyboard) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/keyboard) -- [Leap Motion](https://www.leapmotion.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/leap) -- [MavLink](http://qgroundcontrol.org/mavlink/start) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/mavlink) -- [MegaPi](http://www.makeblock.com/megapi) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/megapi) -- [Microbit](http://microbit.org/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/microbit) -- [MQTT](http://mqtt.org/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/mqtt) -- [NanoPi NEO](https://wiki.friendlyelec.com/wiki/index.php/NanoPi_NEO) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/nanopi) -- [NATS](http://nats.io/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/nats) -- [Neurosky](http://neurosky.com/products-markets/eeg-biosensors/hardware/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/neurosky) -- [OpenCV](http://opencv.org/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/opencv) -- [Particle](https://www.particle.io/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/particle) -- [Parrot ARDrone 2.0](http://ardrone2.parrot.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/parrot/ardrone) -- [Parrot Bebop](http://www.parrot.com/usa/products/bebop-drone/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/parrot/bebop) -- [Parrot Minidrone](https://www.parrot.com/us/minidrones) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/parrot/minidrone) -- [Pebble](https://www.getpebble.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/pebble) -- [Radxa Rock Pi 4](https://wiki.radxa.com/Rock4/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/rockpi) -- [Raspberry Pi](http://www.raspberrypi.org/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/raspi) -- [Serial Port](https://en.wikipedia.org/wiki/Serial_port) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/serialport) -- [Sphero](http://www.sphero.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero/sphero) -- [Sphero BB-8](http://www.sphero.com/bb8) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero/bb8) -- [Sphero Ollie](http://www.sphero.com/ollie) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero/ollie) -- [Sphero SPRK+](http://www.sphero.com/sprk-plus) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/sphero/sprkplus) -- [Tinker Board](https://www.asus.com/us/Single-Board-Computer/Tinker-Board/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/tinkerboard) -- [UP2](http://www.up-board.org/upsquared/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/upboard/up2) +- [Arduino](http://www.arduino.cc/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/firmata) +- Audio <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/audio) +- [Beaglebone Black](http://beagleboard.org/boards) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/beaglebone) +- [Beaglebone PocketBeagle](http://beagleboard.org/pocket/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/beaglebone) +- [Bluetooth LE](https://www.bluetooth.com/what-is-bluetooth-technology/bluetooth-technology-basics/low-energy) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/bleclient) +- [C.H.I.P](http://www.nextthing.co/pages/chip) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/chip) +- [C.H.I.P Pro](https://docs.getchip.com/chip_pro.html) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/chip) +- [Digispark](http://digistump.com/products/1) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/digispark) +- [DJI Tello](https://www.ryzerobotics.com/tello) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/dji/tello) +- [DragonBoard](https://developer.qualcomm.com/hardware/dragonboard-410c) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/dragonboard) +- [ESP8266](http://esp8266.net/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/firmata) +- [GoPiGo 3](https://www.dexterindustries.com/gopigo3/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/dexter/gopigo3) +- [Intel Curie](https://www.intel.com/content/www/us/en/products/boards-kits/curie.html) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/intel-iot/curie) +- [Intel Edison](http://www.intel.com/content/www/us/en/do-it-yourself/edison.html) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/intel-iot/edison) +- [Intel Joule](http://intel.com/joule/getstarted) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/intel-iot/joule) +- [Jetson Nano](https://developer.nvidia.com/embedded/jetson-nano/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/jetson) +- [Joystick](http://en.wikipedia.org/wiki/Joystick) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/joystick) +- [Keyboard](https://en.wikipedia.org/wiki/Computer_keyboard) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/keyboard) +- [Leap Motion](https://www.leapmotion.com/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/leap) +- [MavLink](http://qgroundcontrol.org/mavlink/start) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/mavlink) +- [MegaPi](http://www.makeblock.com/megapi) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/megapi) +- [Microbit](http://microbit.org/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/microbit) +- [MQTT](http://mqtt.org/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/mqtt) +- [NanoPi NEO](https://wiki.friendlyelec.com/wiki/index.php/NanoPi_NEO) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/nanopi) +- [NATS](http://nats.io/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/nats) +- [Neurosky](http://neurosky.com/products-markets/eeg-biosensors/hardware/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/neurosky) +- [OpenCV](http://opencv.org/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/opencv) +- [Particle](https://www.particle.io/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/particle) +- [Parrot ARDrone 2.0](http://ardrone2.parrot.com/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/ardrone) +- [Parrot Bebop](http://www.parrot.com/usa/products/bebop-drone/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/bebop) +- [Parrot Minidrone](https://www.parrot.com/us/minidrones) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/minidrone) +- [Pebble](https://www.getpebble.com/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/pebble) +- [Radxa Rock Pi 4](https://wiki.radxa.com/Rock4/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/rockpi) +- [Raspberry Pi](http://www.raspberrypi.org/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/raspi) +- [Serial Port](https://en.wikipedia.org/wiki/Serial_port) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/serialport) +- [Sphero](http://www.sphero.com/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/sphero/sphero) +- [Sphero BB-8](http://www.sphero.com/bb8) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/sphero/bb8) +- [Sphero Ollie](http://www.sphero.com/ollie) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/sphero/ollie) +- [Sphero SPRK+](http://www.sphero.com/sprk-plus) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/sphero/sprkplus) +- [Tinker Board](https://www.asus.com/us/Single-Board-Computer/Tinker-Board/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/tinkerboard) +- [UP2](http://www.up-board.org/upsquared/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/upboard/up2) Support for many devices that use Analog Input/Output (AIO) have a shared set of drivers provided using the `gobot/drivers/aio` package: -- [AIO](https://en.wikipedia.org/wiki/Analog-to-digital_converter) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/aio) +- [AIO](https://en.wikipedia.org/wiki/Analog-to-digital_converter) <=> [Drivers](https://github.com/hybridgroup/gobot/blob/release/drivers/aio) - Analog Actuator - Analog Sensor - Grove Light Sensor @@ -300,7 +300,7 @@ the `gobot/drivers/aio` package: Support for many devices that use Bluetooth LE (BLE) have a shared set of drivers provided using the `gobot/drivers/ble` package: -- [BLE](http://en.wikipedia.org/wiki/Bluetooth_low_energy) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/ble) +- [BLE](http://en.wikipedia.org/wiki/Bluetooth_low_energy) <=> [Drivers](https://github.com/hybridgroup/gobot/blob/release/drivers/ble) - Battery Service - Device Information Service - Generic Access Service @@ -317,7 +317,7 @@ the `gobot/drivers/ble` package: Support for many devices that use General Purpose Input/Output (GPIO) have a shared set of drivers provided using the `gobot/drivers/gpio` package: -- [GPIO](https://en.wikipedia.org/wiki/General_Purpose_Input/Output) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/gpio) +- [GPIO](https://en.wikipedia.org/wiki/General_Purpose_Input/Output) <=> [Drivers](https://github.com/hybridgroup/gobot/blob/release/drivers/gpio) - AIP1640 LED Dot Matrix/7 Segment Controller - Button - Buzzer @@ -345,7 +345,7 @@ the `gobot/drivers/gpio` package: Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of drivers provided using the `gobot/drivers/i2c` package: -- [I2C](https://en.wikipedia.org/wiki/I%C2%B2C) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/i2c) +- [I2C](https://en.wikipedia.org/wiki/I%C2%B2C) <=> [Drivers](https://github.com/hybridgroup/gobot/blob/release/drivers/i2c) - Adafruit 1109 2x16 RGB-LCD with 5 keys - Adafruit 2327 16-Channel PWM/Servo HAT Hat - Adafruit 2348 DC and Stepper Motor Hat @@ -388,7 +388,7 @@ the `gobot/drivers/i2c` package: Support for many devices that use Serial communication (UART) have a shared set of drivers provided using the `gobot/drivers/serial` package: -- [UART](https://en.wikipedia.org/wiki/Serial_port) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/serial) +- [UART](https://en.wikipedia.org/wiki/Serial_port) <=> [Drivers](https://github.com/hybridgroup/gobot/blob/release/drivers/serial) - Sphero: Sphero - Neurosky: MindWave - MegaPi: MotorDriver @@ -396,7 +396,7 @@ the `gobot/drivers/serial` package: Support for devices that use Serial Peripheral Interface (SPI) have a shared set of drivers provided using the `gobot/drivers/spi` package: -- [SPI](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/spi) +- [SPI](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus) <=> [Drivers](https://github.com/hybridgroup/gobot/blob/release/drivers/spi) - APA102 Programmable LEDs - MCP3002 Analog/Digital Converter - MCP3004 Analog/Digital Converter @@ -453,12 +453,12 @@ Thank you! ## Contributing -For our contribution guidelines, please go to [https://github.com/hybridgroup/gobot/blob/master/CONTRIBUTING.md -](https://github.com/hybridgroup/gobot/blob/master/CONTRIBUTING.md +For our contribution guidelines, please go to [https://github.com/hybridgroup/gobot/blob/release/CONTRIBUTING.md +](https://github.com/hybridgroup/gobot/blob/release/CONTRIBUTING.md ). Gobot is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. -[You can read about it here](https://github.com/hybridgroup/gobot/tree/master/CODE_OF_CONDUCT.md). +[You can read about it here](https://github.com/hybridgroup/gobot/blob/release/CODE_OF_CONDUCT.md). ## License diff --git a/api/basic_auth.go b/api/basic_auth.go index 698a00657..260d2c357 100644 --- a/api/basic_auth.go +++ b/api/basic_auth.go @@ -8,7 +8,7 @@ import ( // BasicAuth returns basic auth handler. func BasicAuth(username, password string) http.HandlerFunc { - // Inspired by https://github.com/codegangsta/martini-contrib/blob/master/auth/ + // Inspired by https://github.com/codegangsta/martini-contrib/tree/v0.1/auth return func(res http.ResponseWriter, req *http.Request) { if !secureCompare(req.Header.Get("Authorization"), "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)), diff --git a/drivers/aio/doc.go b/drivers/aio/doc.go index 10f8facd8..9b7129668 100644 --- a/drivers/aio/doc.go +++ b/drivers/aio/doc.go @@ -6,6 +6,6 @@ Installing: Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For further information refer to aio README: -https://github.com/hybridgroup/gobot/blob/master/platforms/aio/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/aio/README.md */ package aio // import "gobot.io/x/gobot/v2/drivers/aio" diff --git a/drivers/ble/sphero/doc.go b/drivers/ble/sphero/doc.go index eac84dd14..7a75f9964 100644 --- a/drivers/ble/sphero/doc.go +++ b/drivers/ble/sphero/doc.go @@ -2,8 +2,8 @@ Package sphero provides the Gobot drivers for the Sphero BLE based platforms. For further information refer to sphero readme files: -https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/bb8/README.md -https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/ollie/README.md -https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/sprkplus/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/sphero/bb8/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/sphero/ollie/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/sphero/sprkplus/README.md */ package sphero // import "gobot.io/x/gobot/v2/drivers/ble/sphero" diff --git a/drivers/common/spherocommon/spherocommon_packets.go b/drivers/common/spherocommon/spherocommon_packets.go index 6693aa9af..d06d08469 100644 --- a/drivers/common/spherocommon/spherocommon_packets.go +++ b/drivers/common/spherocommon/spherocommon_packets.go @@ -1,7 +1,8 @@ package spherocommon // LocatorConfig provides configuration for the Location api. -// https://github.com/orbotix/DeveloperResources/blob/master/docs/Sphero_API_1.50.pdf +// For more information refer to the api specification of "Orbotix Communication API" +// see also: http://wiki.mark-toma.com/view/Sphero_API_Tutorial // The current (X,Y) coordinates of Sphero on the ground plane in centimeters. type LocatorConfig struct { // Determines whether calibrate commands automatically correct the yaw tare value @@ -15,8 +16,8 @@ type LocatorConfig struct { } // CollisionConfig provides configuration for the collision detection alogorithm. -// For more information refer to the official api specification -// https://github.com/orbotix/DeveloperResources/blob/master/docs/Collision%20detection%201.2.pdf. +// For more information refer to the api specification of "Orbotix Communication API" +// see also: http://wiki.mark-toma.com/view/Sphero_API_Tutorial type CollisionConfig struct { // Detection method type to use. Methods 01h and 02h are supported as // of FW ver 1.42. Use 00h to completely disable this service. @@ -39,8 +40,8 @@ type CollisionConfig struct { } // DataStreamingConfig provides configuration for Sensor Data Streaming. -// For more information refer to the official api specification -// https://github.com/orbotix/DeveloperResources/blob/master/docs/Sphero_API_1.50.pdf page 28 +// For more information refer to the api specification of "Orbotix Communication API" +// see also: http://wiki.mark-toma.com/view/Sphero_API_Tutorial type DataStreamingConfig struct { // Divisor of the maximum sensor sampling rate N uint16 diff --git a/drivers/gpio/doc.go b/drivers/gpio/doc.go index 39a488ee9..fdabc313f 100644 --- a/drivers/gpio/doc.go +++ b/drivers/gpio/doc.go @@ -6,6 +6,6 @@ Installing: Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For further information refer to gpio README: -https://github.com/hybridgroup/gobot/blob/master/platforms/gpio/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/gpio/README.md */ package gpio // import "gobot.io/x/gobot/v2/drivers/gpio" diff --git a/drivers/i2c/doc.go b/drivers/i2c/doc.go index 907dcf013..610b0c738 100644 --- a/drivers/i2c/doc.go +++ b/drivers/i2c/doc.go @@ -6,6 +6,6 @@ Installing: Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For further information refer to i2c README: -https://github.com/hybridgroup/gobot/blob/master/drivers/i2c/README.md +https://github.com/hybridgroup/gobot/blob/release/drivers/i2c/README.md */ package i2c // import "gobot.io/x/gobot/v2/drivers/i2c" diff --git a/drivers/i2c/grovepi_driver.go b/drivers/i2c/grovepi_driver.go index 204ba51e0..451c63ed7 100644 --- a/drivers/i2c/grovepi_driver.go +++ b/drivers/i2c/grovepi_driver.go @@ -14,7 +14,7 @@ const grovePiDefaultAddress = 0x04 // commands, see: // * https://www.dexterindustries.com/GrovePi/programming/grovepi-protocol-adding-custom-sensors/ -// * https://github.com/DexterInd/GrovePi/blob/master/Script/multi_grovepi_installer/grovepi4.py +// * https://github.com/DexterInd/GrovePi/tree/1.3.0/Script/multi_grovepi_installer/grovepi4.py const ( commandReadDigital = 1 commandWriteDigital = 2 @@ -30,7 +30,7 @@ const ( // https://www.dexterindustries.com/grovepi/ // // To use this driver with the GrovePi, it must be running the firmware >= 1.4.0 and the system version >=3. -// https://github.com/DexterInd/GrovePi/blob/master/README.md +// https://github.com/DexterInd/GrovePi/tree/1.3.0/README.md type GrovePiDriver struct { *Driver pins map[int]string diff --git a/drivers/i2c/mpl115a2_driver_test.go b/drivers/i2c/mpl115a2_driver_test.go index 0b2d94691..01d1c7ed4 100644 --- a/drivers/i2c/mpl115a2_driver_test.go +++ b/drivers/i2c/mpl115a2_driver_test.go @@ -51,7 +51,7 @@ func TestMPL115A2ReadData(t *testing.T) { // * shift the temperature value right for 6 bits (resolution is 10 bit) // * shift the pressure value right for 6 bits (resolution is 10 bit) // * calculate temperature in °C according to this implementation: - // https://github.com/adafruit/Adafruit_MPL115A2/blob/master/Adafruit_MPL115A2.cpp + // https://github.com/adafruit/Adafruit_MPL115A2/tree/2.0.2/Adafruit_MPL115A2.cpp // // arrange d, a := initTestMPL115A2DriverWithStubbedAdaptor() diff --git a/drivers/i2c/sht2x_driver.go b/drivers/i2c/sht2x_driver.go index f4c24f056..39b868153 100644 --- a/drivers/i2c/sht2x_driver.go +++ b/drivers/i2c/sht2x_driver.go @@ -43,16 +43,16 @@ const ( // Power on default is 0/0 SHT2xAccuracyHigh = byte(0x00) - // SHT2xTriggerTempMeasureHold is the command for measureing temperature in hold master mode + // SHT2xTriggerTempMeasureHold is the command for measuring temperature in hold controller mode SHT2xTriggerTempMeasureHold = 0xe3 - // SHT2xTriggerHumdMeasureHold is the command for measureing humidity in hold master mode + // SHT2xTriggerHumdMeasureHold is the command for measuring humidity in hold controller mode SHT2xTriggerHumdMeasureHold = 0xe5 - // SHT2xTriggerTempMeasureNohold is the command for measureing humidity in no hold master mode + // SHT2xTriggerTempMeasureNohold is the command for measuring humidity in no hold controller mode SHT2xTriggerTempMeasureNohold = 0xf3 - // SHT2xTriggerHumdMeasureNohold is the command for measureing humidity in no hold master mode + // SHT2xTriggerHumdMeasureNohold is the command for measuring humidity in no hold controller mode SHT2xTriggerHumdMeasureNohold = 0xf5 // SHT2xWriteUserReg is the command for writing user register diff --git a/drivers/serial/doc.go b/drivers/serial/doc.go index 11dd1b31e..bae3f9291 100644 --- a/drivers/serial/doc.go +++ b/drivers/serial/doc.go @@ -2,6 +2,6 @@ Package serial provides Gobot drivers for Serial Port communication based devices. For further information refer to readme: -https://github.com/hybridgroup/gobot/blob/master/drivers/serial/README.md +https://github.com/hybridgroup/gobot/blob/release/drivers/serial/README.md */ package serial // import "gobot.io/x/gobot/v2/drivers/serial" diff --git a/drivers/spi/doc.go b/drivers/spi/doc.go index a7a62641b..1cb149bf6 100644 --- a/drivers/spi/doc.go +++ b/drivers/spi/doc.go @@ -6,6 +6,6 @@ Installing: Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For further information refer to spi README: -https://github.com/hybridgroup/gobot/blob/master/drivers/spi/README.md +https://github.com/hybridgroup/gobot/blob/release/drivers/spi/README.md */ package spi // import "gobot.io/x/gobot/v2/drivers/spi" diff --git a/platforms/audio/doc.go b/platforms/audio/doc.go index b213f62f9..91e080613 100644 --- a/platforms/audio/doc.go +++ b/platforms/audio/doc.go @@ -2,6 +2,6 @@ Package audio provides the Gobot adaptor for audio. For more information refer to the README: -https://github.com/hybridgroup/gobot/blob/master/platforms/audio/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/audio/README.md */ package audio // import "gobot.io/x/gobot/v2/platforms/audio" diff --git a/platforms/beaglebone/doc.go b/platforms/beaglebone/doc.go index 48f9716dd..f4834243e 100644 --- a/platforms/beaglebone/doc.go +++ b/platforms/beaglebone/doc.go @@ -42,6 +42,6 @@ Example: } For more information refer to the beaglebone README: -https://github.com/hybridgroup/gobot/blob/master/platforms/beaglebone/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/beaglebone/README.md */ package beaglebone // import "gobot.io/x/gobot/v2/platforms/beaglebone" diff --git a/platforms/bleclient/doc.go b/platforms/bleclient/doc.go index b6ba3d1c0..29449f8e5 100644 --- a/platforms/bleclient/doc.go +++ b/platforms/bleclient/doc.go @@ -2,6 +2,6 @@ Package bleclient provides the Gobot client adaptor for Bluetooth LE. For more information refer to the README: -https://github.com/hybridgroup/gobot/blob/master/platforms/bleclient/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/bleclient/README.md */ package bleclient // import "gobot.io/x/gobot/v2/platforms/bleclient" diff --git a/platforms/chip/doc.go b/platforms/chip/doc.go index 49579424b..c49e43e34 100644 --- a/platforms/chip/doc.go +++ b/platforms/chip/doc.go @@ -2,6 +2,6 @@ Package chip contains the Gobot adaptor for the CHIP and CHIP Pro For further information refer to the chip README: -https://github.com/hybridgroup/gobot/blob/master/platforms/chip/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/chip/README.md */ package chip // import "gobot.io/x/gobot/v2/platforms/chip" diff --git a/platforms/dexter/dexter.go b/platforms/dexter/dexter.go index 18e2ba6c8..a2d1ccb4e 100644 --- a/platforms/dexter/dexter.go +++ b/platforms/dexter/dexter.go @@ -5,6 +5,6 @@ This package currently supports the following robots: - GoPiGo3 For further information refer to Dexter README: -https://gobot.io/x/gobot/v2/blob/master/platforms/dexter/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/dexter/README.md */ package dexter diff --git a/platforms/digispark/doc.go b/platforms/digispark/doc.go index dd335f32c..a62d3a2db 100644 --- a/platforms/digispark/doc.go +++ b/platforms/digispark/doc.go @@ -44,6 +44,6 @@ Example: } For further information refer to digispark README: -https://github.com/hybridgroup/gobot/blob/master/platforms/digispark/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/digispark/README.md */ package digispark // import "gobot.io/x/gobot/v2/platforms/digispark" diff --git a/platforms/dragonboard/doc.go b/platforms/dragonboard/doc.go index beee89625..2538cb1fc 100644 --- a/platforms/dragonboard/doc.go +++ b/platforms/dragonboard/doc.go @@ -2,6 +2,6 @@ Package dragonboard contains the Gobot adaptor for the DragonBoard 410c For further information refer to the chip README: -https://github.com/hybridgroup/gobot/blob/master/platforms/dragonboard/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/dragonboard/README.md */ package dragonboard // import "gobot.io/x/gobot/v2/platforms/dragonboard" diff --git a/platforms/firmata/doc.go b/platforms/firmata/doc.go index 66c5c5a3d..f93f9152a 100644 --- a/platforms/firmata/doc.go +++ b/platforms/firmata/doc.go @@ -41,6 +41,6 @@ Example: } For further information refer to firmata readme: -https://github.com/hybridgroup/gobot/blob/master/platforms/firmata/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/firmata/README.md */ package firmata // import "gobot.io/x/gobot/v2/platforms/firmata" diff --git a/platforms/intel-iot/curie/README.md b/platforms/intel-iot/curie/README.md index 7fd8616af..69f3403ca 100644 --- a/platforms/intel-iot/curie/README.md +++ b/platforms/intel-iot/curie/README.md @@ -69,8 +69,8 @@ func main() { ) if err := robot.Start(); err != nil { - panic(err) - } + panic(err) + } } ``` @@ -78,7 +78,9 @@ func main() { ### Installing Firmware -You need to flash your Intel Curie with firmware that uses ConfigurableFirmata along with the FirmataCurieIMU plugin. There are 2 versions of this firmware, once that allows connecting using the serial interface, the other using a Bluetooth LE connection. +You need to flash your Intel Curie with firmware that uses ConfigurableFirmata along with the FirmataCurieIMU plugin. +There are 2 versions of this firmware, once that allows connecting using the serial interface, the other using a +Bluetooth LE connection. To setup your Arduino environment: @@ -86,12 +88,8 @@ To setup your Arduino environment: - Install the "Intel Curie Boards" board files using the "Board Manager". You can find it in the Arduino IDE under the "Tools" menu. Choose "Boards > Boards Manager". - Search for the "Intel Curie Boards" package in the "Boards Manager" dialog, and then install the latest version. -- Download the ZIP file for the ConfigurableFirmata library. You can download the latest version of the ConfigurableFirmata - from here: - [https://github.com/firmata/ConfigurableFirmata/archive/master.zip](https://github.com/firmata/ConfigurableFirmata/archive/master.zip) - Once you have downloaded ConfigurableFirmata, install it by using the "Library Manager". You can find it in the Arduino - IDE under the "Sketch" menu. Choose "Include Library > Add .ZIP Library". Select the ZIP file for the ConfigurableFirmata - library that you just downloaded. +- Follow the [installation instructions](https://github.com/firmata/ConfigurableFirmata#installation) for the + ConfigurableFirmata library - Download the ZIP file for the FirmataCurieIMU library. You can download the latest version of FirmataCurieIMU from here: [https://github.com/intel-iot-devkit/firmata-curie-imu/archive/master.zip](https://github.com/intel-iot-devkit/firmata-curie-imu/archive/master.zip) - Once you have downloaded the FirmataCurieIMU library, install it by using the "Library Manager". You can find it in the diff --git a/platforms/intel-iot/curie/doc.go b/platforms/intel-iot/curie/doc.go index 5e59b56d9..13fedb7de 100644 --- a/platforms/intel-iot/curie/doc.go +++ b/platforms/intel-iot/curie/doc.go @@ -2,6 +2,6 @@ Package curie contains the Gobot driver for the Intel Curie IMU. For further information refer to intel-iot README: -https://github.com/hybridgroup/gobot/blob/master/platforms/intel-iot/curie/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/intel-iot/curie/README.md */ package curie // import "gobot.io/x/gobot/v2/platforms/intel-iot/curie" diff --git a/platforms/intel-iot/edison/doc.go b/platforms/intel-iot/edison/doc.go index 3e068753c..c3cd5852c 100644 --- a/platforms/intel-iot/edison/doc.go +++ b/platforms/intel-iot/edison/doc.go @@ -2,6 +2,6 @@ Package edison contains the Gobot adaptor for the Intel Edison. For further information refer to intel-iot README: -https://github.com/hybridgroup/gobot/blob/master/platforms/intel-iot/edison/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/intel-iot/edison/README.md */ package edison // import "gobot.io/x/gobot/v2/platforms/intel-iot/edison" diff --git a/platforms/intel-iot/intel-iot.go b/platforms/intel-iot/intel-iot.go index 9f5cedd44..e1837c1c1 100644 --- a/platforms/intel-iot/intel-iot.go +++ b/platforms/intel-iot/intel-iot.go @@ -6,6 +6,6 @@ This package currently supports the following Intel IoT hardware: - Intel Joule developer kit For further information refer to intel-iot README: -https://gobot.io/x/gobot/v2/blob/master/platforms/intel-iot/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/intel-iot/README.md */ package inteliot diff --git a/platforms/intel-iot/joule/doc.go b/platforms/intel-iot/joule/doc.go index c63d46a6c..1f8c1a2e2 100644 --- a/platforms/intel-iot/joule/doc.go +++ b/platforms/intel-iot/joule/doc.go @@ -2,6 +2,6 @@ Package joule contains the Gobot adaptor for the Intel Joule. For further information refer to intel-iot README: -https://github.com/hybridgroup/gobot/blob/master/platforms/intel-iot/joule/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/intel-iot/joule/README.md */ package joule // import "gobot.io/x/gobot/v2/platforms/intel-iot/joule" diff --git a/platforms/jetson/doc.go b/platforms/jetson/doc.go index 9763ef996..174678633 100644 --- a/platforms/jetson/doc.go +++ b/platforms/jetson/doc.go @@ -2,6 +2,6 @@ Package jetson contains the Gobot adaptor for the Jetson Nano. For further information refer to Jetson README: -https://github.com/hybridgroup/gobot/blob/master/platforms/jetson/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/jetson/README.md */ package jetson // import "gobot.io/x/gobot/v2/platforms/jetson" diff --git a/platforms/joystick/doc.go b/platforms/joystick/doc.go index 640429d6c..2d6284a8c 100644 --- a/platforms/joystick/doc.go +++ b/platforms/joystick/doc.go @@ -59,6 +59,6 @@ Example: } For further information refer to joystick README: -https://github.com/hybridgroup/gobot/blob/master/platforms/joystick/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/joystick/README.md */ package joystick // import "gobot.io/x/gobot/v2/platforms/joystick" diff --git a/platforms/keyboard/doc.go b/platforms/keyboard/doc.go index f5c6620e6..de63f755d 100644 --- a/platforms/keyboard/doc.go +++ b/platforms/keyboard/doc.go @@ -45,6 +45,6 @@ Example: } For further information refer to keyboard README: -https://github.com/hybridgroup/gobot/blob/master/platforms/keyboard/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/keyboard/README.md */ package keyboard // import "gobot.io/x/gobot/v2/platforms/keyboard" diff --git a/platforms/leap/doc.go b/platforms/leap/doc.go index fbb030810..83501d4d2 100644 --- a/platforms/leap/doc.go +++ b/platforms/leap/doc.go @@ -40,6 +40,6 @@ Example: } For more information refer to the leap README: -https://github.com/hybridgroup/gobot/blob/master/platforms/leap/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/leap/README.md */ package leap // import "gobot.io/x/gobot/v2/platforms/leap" diff --git a/platforms/mavlink/doc.go b/platforms/mavlink/doc.go index 630c180de..8fee54f6b 100644 --- a/platforms/mavlink/doc.go +++ b/platforms/mavlink/doc.go @@ -65,6 +65,6 @@ Example: } For further information refer to mavlink README: -https://github.com/hybridgroup/gobot/blob/master/platforms/mavlink/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/mavlink/README.md */ package mavlink // import "gobot.io/x/gobot/v2/platforms/mavlink" diff --git a/platforms/megapi/doc.go b/platforms/megapi/doc.go index 8e191020d..d863bdda0 100644 --- a/platforms/megapi/doc.go +++ b/platforms/megapi/doc.go @@ -2,6 +2,6 @@ Package megapi provides the Gobot adaptor for MegaPi. For more information refer to the README: -https://github.com/hybridgroup/gobot/blob/master/platforms/megapi/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/megapi/README.md */ package megapi // import "gobot.io/x/gobot/v2/platforms/megapi" diff --git a/platforms/mqtt/doc.go b/platforms/mqtt/doc.go index 06f3e194e..f70b4689c 100644 --- a/platforms/mqtt/doc.go +++ b/platforms/mqtt/doc.go @@ -6,6 +6,6 @@ Installing: Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For further information refer to mqtt README: -https://github.com/hybridgroup/gobot/blob/master/platforms/mqtt/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/mqtt/README.md */ package mqtt // import "gobot.io/x/gobot/v2/platforms/mqtt" diff --git a/platforms/nanopi/doc.go b/platforms/nanopi/doc.go index 9489524be..072c4871e 100644 --- a/platforms/nanopi/doc.go +++ b/platforms/nanopi/doc.go @@ -2,6 +2,6 @@ Package nanopi contains the Gobot adaptor for the FriendlyARM NanoPi Boards. For further information refer to nanopi README: -https://github.com/hybridgroup/gobot/blob/master/platforms/nanopi/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/nanopi/README.md */ package nanopi // import "gobot.io/x/gobot/v2/platforms/nanopi" diff --git a/platforms/nats/doc.go b/platforms/nats/doc.go index 5628b9695..ccbd6ba03 100644 --- a/platforms/nats/doc.go +++ b/platforms/nats/doc.go @@ -5,6 +5,6 @@ Installing: Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For further information refer to nats README: -https://github.com/hybridgroup/gobot/blob/master/platforms/nats/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/nats/README.md */ package nats // import "gobot.io/x/gobot/v2/platforms/nats" diff --git a/platforms/opencv/doc.go b/platforms/opencv/doc.go index da047368f..339734a13 100644 --- a/platforms/opencv/doc.go +++ b/platforms/opencv/doc.go @@ -40,6 +40,6 @@ Example: } For further information refer to opencv README: -https://github.com/hybridgroup/gobot/blob/master/platforms/opencv/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/opencv/README.md */ package opencv // import "gobot.io/x/gobot/v2/platforms/opencv" diff --git a/platforms/parrot/ardrone/doc.go b/platforms/parrot/ardrone/doc.go index bb1f8b896..75c91cba3 100644 --- a/platforms/parrot/ardrone/doc.go +++ b/platforms/parrot/ardrone/doc.go @@ -41,6 +41,6 @@ Example: } For more information refer to the ardrone README: -https://github.com/hybridgroup/gobot/tree/master/platforms/parrot/ardrone/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/ardrone/README.md */ package ardrone // import "gobot.io/x/gobot/v2/platforms/parrot/ardrone" diff --git a/platforms/parrot/bebop/doc.go b/platforms/parrot/bebop/doc.go index 6c3c77dc0..48fcd04d7 100644 --- a/platforms/parrot/bebop/doc.go +++ b/platforms/parrot/bebop/doc.go @@ -6,6 +6,6 @@ Installing: Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) For more information refer to the bebop README: -https://github.com/hybridgroup/gobot/tree/master/platforms/parrot/bebop/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/bebop/README.md */ package bebop // import "gobot.io/x/gobot/v2/platforms/parrot/bebop" diff --git a/platforms/particle/doc.go b/platforms/particle/doc.go index 8151b6335..01064744c 100644 --- a/platforms/particle/doc.go +++ b/platforms/particle/doc.go @@ -41,6 +41,6 @@ Example: } For further information refer to Particle readme: -https://github.com/hybridgroup/gobot/blob/master/platforms/particle/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/particle/README.md */ package particle // import "gobot.io/x/gobot/v2/platforms/particle" diff --git a/platforms/pebble/doc.go b/platforms/pebble/doc.go index 5e723cf76..308056536 100644 --- a/platforms/pebble/doc.go +++ b/platforms/pebble/doc.go @@ -55,6 +55,6 @@ your computer IP, robot name is 'pebble' and robot api port is 8080 } For more information refer to the pebble README: -https://github.com/hybridgroup/gobot/blob/master/platforms/pebble/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/pebble/README.md */ package pebble // import "gobot.io/x/gobot/v2/platforms/pebble" diff --git a/platforms/raspi/doc.go b/platforms/raspi/doc.go index 9c46a7fae..683796fce 100644 --- a/platforms/raspi/doc.go +++ b/platforms/raspi/doc.go @@ -2,6 +2,6 @@ Package raspi contains the Gobot adaptor for the Raspberry Pi. For further information refer to raspi README: -https://github.com/hybridgroup/gobot/blob/master/platforms/raspi/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/raspi/README.md */ package raspi // import "gobot.io/x/gobot/v2/platforms/raspi" diff --git a/platforms/rockpi/doc.go b/platforms/rockpi/doc.go index 10a589cd7..b2c26ce5e 100644 --- a/platforms/rockpi/doc.go +++ b/platforms/rockpi/doc.go @@ -2,6 +2,6 @@ Package rockpi contains the Gobot adaptor for Radxa's Rock Pi Single Board Computers. For further information refer to rockpi README: -https://github.com/hybridgroup/gobot/blob/master/platforms/rockpi/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/rockpi/README.md */ package rockpi // import "gobot.io/x/gobot/v2/platforms/rockpi" diff --git a/platforms/serialport/README.md b/platforms/serialport/README.md index a8cadcc60..605cb5706 100644 --- a/platforms/serialport/README.md +++ b/platforms/serialport/README.md @@ -8,5 +8,5 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r ## How to Use -See documentation for [Sphero](https://github.com/hybridgroup/gobot/blob/master/platforms/sphero/sphero/README.md) or -[Neurosky MindWave](https://github.com/hybridgroup/gobot/blob/master/platforms/neurosky/README.md). +See documentation for [Sphero](https://github.com/hybridgroup/gobot/blob/release/platforms/sphero/sphero/README.md) or +[Neurosky MindWave](https://github.com/hybridgroup/gobot/blob/release/platforms/neurosky/README.md). diff --git a/platforms/serialport/doc.go b/platforms/serialport/doc.go index 5baa09f4d..ed03a6260 100644 --- a/platforms/serialport/doc.go +++ b/platforms/serialport/doc.go @@ -2,6 +2,6 @@ Package serialport provides the Gobot adaptor for serial communication with drivers. For further information refer to readme: -https://github.com/hybridgroup/gobot/blob/master/platforms/serialport/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/serialport/README.md */ package serialport // import "gobot.io/x/gobot/v2/platforms/serialport" diff --git a/platforms/tinkerboard/doc.go b/platforms/tinkerboard/doc.go index 574fc490f..b2db191a0 100644 --- a/platforms/tinkerboard/doc.go +++ b/platforms/tinkerboard/doc.go @@ -2,6 +2,6 @@ Package tinkerboard contains the Gobot adaptor for the ASUS Tinker Board. For further information refer to tinkerboard README: -https://github.com/hybridgroup/gobot/blob/master/platforms/tinkerboard/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/tinkerboard/README.md */ package tinkerboard // import "gobot.io/x/gobot/v2/platforms/tinkerboard" diff --git a/platforms/upboard/up2/doc.go b/platforms/upboard/up2/doc.go index 23852a040..fb427bd5a 100644 --- a/platforms/upboard/up2/doc.go +++ b/platforms/upboard/up2/doc.go @@ -2,6 +2,6 @@ Package up2 contains the Gobot adaptor for the Upboard UP2. For further information refer to the UP2 README: -https://github.com/hybridgroup/gobot/blob/master/platforms/upboard/up2/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/upboard/up2/README.md */ package up2 // import "gobot.io/x/gobot/v2/platforms/upboard/up2" diff --git a/platforms/upboard/upboard.go b/platforms/upboard/upboard.go index 746d9858f..9a8c63e7f 100644 --- a/platforms/upboard/upboard.go +++ b/platforms/upboard/upboard.go @@ -5,6 +5,6 @@ This package currently supports the following hardware: - UP2 (Squared) For further information refer to the Upboard README: -https://gobot.io/x/gobot/v2/blob/master/platforms/upboard/README.md +https://github.com/hybridgroup/gobot/blob/release/platforms/upboard/README.md */ package upboard From c159228f48ec5a0d3891ca6dd50adf1815244d5b Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 13 Feb 2024 16:30:25 +0100 Subject: [PATCH 51/57] gobot: rename Master to Manager (#1070) --- CHANGELOG.md | 22 ++++++------ README.md | 44 +++++++++++------------ api/api.go | 36 +++++++++---------- api/api_test.go | 8 ++--- api/doc.go | 4 +-- doc.go | 12 +++---- examples/batty.go | 2 +- examples/bleclient_multiple_generic.go | 8 ++--- examples/bleclient_multiple_info.go | 8 ++--- examples/bleclient_ollie_multiple.go | 8 ++--- examples/digispark_api.go | 8 ++--- examples/edison_button_led_api.go | 8 ++--- examples/firmata_blink_api.go | 8 ++--- examples/firmata_travis.go | 10 +++--- examples/hello_api.go | 10 +++--- examples/hello_api_auth.go | 10 +++--- examples/hello_api_custom.go | 10 +++--- examples/hello_api_video.go | 8 ++--- examples/particle_api.go | 8 ++--- examples/pebble.go | 8 ++--- examples/pebble_accelerometer.go | 8 ++--- examples/serialport_sphero_api.go | 8 ++--- examples/serialport_sphero_calibration.go | 8 ++--- examples/serialport_sphero_conways.go | 6 ++-- examples/serialport_sphero_dpad.go | 8 ++--- examples/serialport_sphero_master.go | 10 +++--- examples/serialport_sphero_multiple.go | 8 ++--- examples/square.go | 8 ++--- examples/square_fire.go | 8 ++--- master.go => manager.go | 38 ++++++++++---------- master_test.go => manager_test.go | 42 +++++++++++----------- platforms/pebble/README.md | 12 +++---- platforms/pebble/doc.go | 8 ++--- 33 files changed, 206 insertions(+), 206 deletions(-) rename master.go => manager.go (67%) rename master_test.go => manager_test.go (82%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5576ac2d8..45da52407 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1183,7 +1183,7 @@ ### core -* Add Running() methods for Master and Robot and increase test coverage accordingly +* Add Running() methods for Manager and Robot and increase test coverage accordingly ### sysfs @@ -1647,9 +1647,9 @@ ### core * Refactoring to allow 'Metal' development using Gobot packages -* Able to run robots without being part of a Master. +* Able to run robots without being part of a Manager. * Now running all work in separate goroutines -* Rename internal name of Master type +* Rename internal name of Manager type * Refactor events to use channels all the way down. * Eliminate potential race conditions from Events and Every functions * Add Unsubscribe() to Eventer, now Once() works as expected @@ -1657,7 +1657,7 @@ * Ranges over event channels instead of using select * No longer return non-standard slices of errors, instead use hashicorp/go-multierror * Ensure that all drivers have default names -* Now both Robot and Master operate using AutoRun as expected +* Now both Robot and Manager operate using AutoRun as expected * Use canonical import domain of gobot.io for all code * Use time.Sleep unless waiting for a timeout in a select * Uses time.NewTimer() instead of time.After() to be more efficient @@ -2456,7 +2456,7 @@ * Replaced ginkgo/gomega with system testing package * Refactor gobot/robot/device commands * Added Event type -* Replaced Master type with Gobot type +* Replaced Manager type with Gobot type * Every` and `After` now accept `time.Duration` * Removed reflection helper methods @@ -2580,7 +2580,7 @@ * Finalize on SIGINT * Publish function for driver events * device test coverage -* master and robot test coverage +* manager and robot test coverage ### Clean @@ -2600,7 +2600,7 @@ ### Refactor -* robot and master +* robot and manager ### Remove @@ -2636,8 +2636,8 @@ * Travis banner to README * api commands * POST command -* master example -* robot master +* manager example +* robot manager * Sphero example * Digispark to list of supported platforms * helper functions @@ -2737,11 +2737,11 @@ ### Rename -* Gobot struct to Master +* Gobot struct to Manager ### Set -* GOMAXPROCS property in GobotMaster +* GOMAXPROCS property in GobotManager ### Skeleton diff --git a/README.md b/README.md index f4d720fc2..dd3e18b34 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,8 @@ func main() { work := func() { gobot.Every(1*time.Second, func() { if err := led.Toggle(); err != nil { - fmt.Println(err) - } + fmt.Println(err) + } }) } @@ -90,8 +90,8 @@ func main() { ) if err := robot.Start(); err != nil { - panic(err) - } + panic(err) + } } ``` @@ -148,26 +148,26 @@ import ( func main() { e := edison.NewAdaptor() if err := e.Connect(); err != nil { - fmt.Println(err) - } + fmt.Println(err) + } led := gpio.NewLedDriver(e, "13") if err := led.Start(); err != nil { - fmt.Println(err) - } + fmt.Println(err) + } for { if err := led.Toggle(); err != nil { - fmt.Println(err) - } + fmt.Println(err) + } time.Sleep(1000 * time.Millisecond) } } ``` -### "Master" Gobot +### "Manager" Gobot -You can also use the full capabilities of the framework aka "Master Gobot" to control swarms of robots or other features +You can also use the full capabilities of the framework aka "Manager Gobot" to control swarms of robots or other features such as the built-in API server. For example: ```go @@ -216,8 +216,8 @@ func NewSwarmBot(port string) *gobot.Robot { } func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() spheros := []string{ "/dev/rfcomm0", @@ -227,12 +227,12 @@ func main() { } for _, port := range spheros { - master.AddRobot(NewSwarmBot(port)) + manager.AddRobot(NewSwarmBot(port)) } - if err := master.Start(); err != nil { - panic(err) - } + if err := manager.Start(); err != nil { + panic(err) + } } ``` @@ -416,15 +416,15 @@ device status, and execute device commands. To activate the API, import the `gobot.io/x/gobot/v2/api` package and instantiate the `API` like this: ```go - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() ``` You can also specify the api host and port, and turn on authentication: ```go - master := gobot.NewMaster() - server := api.NewAPI(master) + manager := gobot.NewManager() + server := api.NewAPI(manager) server.Port = "4000" server.AddHandler(api.BasicAuth("gort", "klatuu")) server.Start() diff --git a/api/api.go b/api/api.go index b0de3dbb4..0c369fba4 100644 --- a/api/api.go +++ b/api/api.go @@ -17,7 +17,7 @@ import ( // API represents an API server type API struct { - master *gobot.Master + manager *gobot.Manager router *pat.PatternServeMux Host string Port string @@ -28,11 +28,11 @@ type API struct { } // NewAPI returns a new api instance -func NewAPI(m *gobot.Master) *API { +func NewAPI(m *gobot.Manager) *API { return &API{ - master: m, - router: pat.New(), - Port: "3000", + manager: m, + router: pat.New(), + Port: "3000", start: func(a *API) { log.Println("Initializing API on " + a.Host + ":" + a.Port + "...") http.Handle("/", a) @@ -196,20 +196,20 @@ func (a *API) robeaux(res http.ResponseWriter, req *http.Request) { // mcp returns MCP route handler. // Writes JSON with gobot representation func (a *API) mcp(res http.ResponseWriter, req *http.Request) { - a.writeJSON(map[string]interface{}{"MCP": gobot.NewJSONMaster(a.master)}, res) + a.writeJSON(map[string]interface{}{"MCP": gobot.NewJSONManager(a.manager)}, res) } // mcpCommands returns commands route handler. // Writes JSON with global commands representation func (a *API) mcpCommands(res http.ResponseWriter, req *http.Request) { - a.writeJSON(map[string]interface{}{"commands": gobot.NewJSONMaster(a.master).Commands}, res) + a.writeJSON(map[string]interface{}{"commands": gobot.NewJSONManager(a.manager).Commands}, res) } // robots returns route handler. // Writes JSON with robots representation func (a *API) robots(res http.ResponseWriter, req *http.Request) { jsonRobots := []*gobot.JSONRobot{} - a.master.Robots().Each(func(r *gobot.Robot) { + a.manager.Robots().Each(func(r *gobot.Robot) { jsonRobots = append(jsonRobots, gobot.NewJSONRobot(r)) }) a.writeJSON(map[string]interface{}{"robots": jsonRobots}, res) @@ -238,7 +238,7 @@ func (a *API) robotCommands(res http.ResponseWriter, req *http.Request) { // robotDevices returns devices route handler. // Writes JSON with robot devices representation func (a *API) robotDevices(res http.ResponseWriter, req *http.Request) { - if robot := a.master.Robot(req.URL.Query().Get(":robot")); robot != nil { + if robot := a.manager.Robot(req.URL.Query().Get(":robot")); robot != nil { jsonDevices := []*gobot.JSONDevice{} robot.Devices().Each(func(d gobot.Device) { jsonDevices = append(jsonDevices, gobot.NewJSONDevice(d)) @@ -268,11 +268,11 @@ func (a *API) robotDeviceEvent(res http.ResponseWriter, req *http.Request) { res.Header().Set("Cache-Control", "no-cache") res.Header().Set("Connection", "keep-alive") - device := a.master.Robot(req.URL.Query().Get(":robot")). + device := a.manager.Robot(req.URL.Query().Get(":robot")). Device(req.URL.Query().Get(":device")) //nolint:forcetypeassert // no error return value, so there is no better way - if event := a.master.Robot(req.URL.Query().Get(":robot")). + if event := a.manager.Robot(req.URL.Query().Get(":robot")). Device(req.URL.Query().Get(":device")).(gobot.Eventer). Event(req.URL.Query().Get(":event")); len(event) > 0 { //nolint:forcetypeassert // no error return value, so there is no better way @@ -314,7 +314,7 @@ func (a *API) robotDeviceCommands(res http.ResponseWriter, req *http.Request) { // writes JSON with robot connections representation func (a *API) robotConnections(res http.ResponseWriter, req *http.Request) { jsonConnections := []*gobot.JSONConnection{} - if robot := a.master.Robot(req.URL.Query().Get(":robot")); robot != nil { + if robot := a.manager.Robot(req.URL.Query().Get(":robot")); robot != nil { robot.Connections().Each(func(c gobot.Connection) { jsonConnections = append(jsonConnections, gobot.NewJSONConnection(c)) }) @@ -336,7 +336,7 @@ func (a *API) robotConnection(res http.ResponseWriter, req *http.Request) { // executeMcpCommand calls a global command associated to requested route func (a *API) executeMcpCommand(res http.ResponseWriter, req *http.Request) { - a.executeCommand(a.master.Command(req.URL.Query().Get(":command")), + a.executeCommand(a.manager.Command(req.URL.Query().Get(":command")), res, req, ) @@ -350,7 +350,7 @@ func (a *API) executeRobotDeviceCommand(res http.ResponseWriter, req *http.Reque } else { a.executeCommand( //nolint:forcetypeassert // no error return value, so there is no better way - a.master.Robot(req.URL.Query().Get(":robot")). + a.manager.Robot(req.URL.Query().Get(":robot")). Device(req.URL.Query().Get(":device")).(gobot.Commander). Command(req.URL.Query().Get(":command")), res, @@ -365,7 +365,7 @@ func (a *API) executeRobotCommand(res http.ResponseWriter, req *http.Request) { a.writeJSON(map[string]interface{}{"error": err.Error()}, res) } else { a.executeCommand( - a.master.Robot(req.URL.Query().Get(":robot")). + a.manager.Robot(req.URL.Query().Get(":robot")). Command(req.URL.Query().Get(":command")), res, req, @@ -410,14 +410,14 @@ func (a *API) Debug() { } func (a *API) jsonRobotFor(name string) (*gobot.JSONRobot, error) { - if robot := a.master.Robot(name); robot != nil { + if robot := a.manager.Robot(name); robot != nil { return gobot.NewJSONRobot(robot), nil } return nil, fmt.Errorf("No Robot found with the name %s", name) } func (a *API) jsonDeviceFor(robot string, name string) (*gobot.JSONDevice, error) { - if device := a.master.Robot(robot).Device(name); device != nil { + if device := a.manager.Robot(robot).Device(name); device != nil { return gobot.NewJSONDevice(device), nil } @@ -425,7 +425,7 @@ func (a *API) jsonDeviceFor(robot string, name string) (*gobot.JSONDevice, error } func (a *API) jsonConnectionFor(robot string, name string) (*gobot.JSONConnection, error) { - if connection := a.master.Robot(robot).Connection(name); connection != nil { + if connection := a.manager.Robot(robot).Connection(name); connection != nil { return gobot.NewJSONConnection(connection), nil } diff --git a/api/api_test.go b/api/api_test.go index 895f9416c..49ea95f62 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -19,7 +19,7 @@ import ( func initTestAPI() *API { log.SetOutput(NullReadWriteCloser{}) - g := gobot.NewMaster() + g := gobot.NewManager() a := NewAPI(g) a.start = func(m *API) {} a.Start() @@ -38,7 +38,7 @@ func initTestAPI() *API { func TestStartWithoutDefaults(t *testing.T) { log.SetOutput(NullReadWriteCloser{}) - g := gobot.NewMaster() + g := gobot.NewManager() a := NewAPI(g) a.start = func(m *API) {} @@ -396,13 +396,13 @@ func TestRobotDeviceEvent(t *testing.T) { respc <- resp }() - event := a.master.Robot("Robot1"). + event := a.manager.Robot("Robot1"). Device("Device1").(gobot.Eventer). Event("TestEvent") go func() { time.Sleep(time.Millisecond * 5) - a.master.Robot("Robot1"). + a.manager.Robot("Robot1"). Device("Device1").(gobot.Eventer).Publish(event, "event-data") }() diff --git a/api/doc.go b/api/doc.go index a8e04d3b1..08fc826a4 100644 --- a/api/doc.go +++ b/api/doc.go @@ -13,14 +13,14 @@ Example: ) func main() { - gbot := gobot.NewMaster() + gbot := gobot.NewManager() // Starts the API server on default port 3000 api.NewAPI(gbot).Start() // Accessible via http://localhost:3000/api/commands/say_hello gbot.AddCommand("say_hello", func(params map[string]interface{}) interface{} { - return "Master says hello!" + return "Manager says hello!" }) hello := gbot.AddRobot(gobot.NewRobot("Eve")) diff --git a/doc.go b/doc.go index b24ca6738..633a086e0 100644 --- a/doc.go +++ b/doc.go @@ -76,9 +76,9 @@ pure idiomatic Golang code. For example: } } -# Master Gobot +# Manager Gobot -Finally, you can use Master Gobot to add the complete Gobot API or control swarms of Robots: +Finally, you can use Manager Gobot to add the complete Gobot API or control swarms of Robots: package main @@ -125,8 +125,8 @@ Finally, you can use Master Gobot to add the complete Gobot API or control swarm } func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() spheros := []string{ "/dev/rfcomm0", @@ -136,10 +136,10 @@ Finally, you can use Master Gobot to add the complete Gobot API or control swarm } for _, port := range spheros { - master.AddRobot(NewSwarmBot(port)) + manager.AddRobot(NewSwarmBot(port)) } - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/batty.go b/examples/batty.go index b5237c9fe..398d544e3 100644 --- a/examples/batty.go +++ b/examples/batty.go @@ -15,7 +15,7 @@ import ( ) func main() { - gbot := gobot.NewMaster() + gbot := gobot.NewManager() api.NewAPI(gbot).Start() diff --git a/examples/bleclient_multiple_generic.go b/examples/bleclient_multiple_generic.go index c09b4e3ec..cbccf5649 100644 --- a/examples/bleclient_multiple_generic.go +++ b/examples/bleclient_multiple_generic.go @@ -53,15 +53,15 @@ func NewSwarmBot(port string) *gobot.Robot { } func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() for _, port := range os.Args[1:] { bot := NewSwarmBot(port) - master.AddRobot(bot) + manager.AddRobot(bot) } - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/bleclient_multiple_info.go b/examples/bleclient_multiple_info.go index f76f5b0ae..11afb2756 100644 --- a/examples/bleclient_multiple_info.go +++ b/examples/bleclient_multiple_info.go @@ -71,15 +71,15 @@ func NewSwarmBot(port string) *gobot.Robot { } func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() for _, port := range os.Args[1:] { bot := NewSwarmBot(port) - master.AddRobot(bot) + manager.AddRobot(bot) } - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/bleclient_ollie_multiple.go b/examples/bleclient_ollie_multiple.go index 90a06d714..5195e6f82 100644 --- a/examples/bleclient_ollie_multiple.go +++ b/examples/bleclient_ollie_multiple.go @@ -47,15 +47,15 @@ func NewSwarmBot(port string) *gobot.Robot { } func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() for _, port := range os.Args[1:] { bot := NewSwarmBot(port) - master.AddRobot(bot) + manager.AddRobot(bot) } - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/digispark_api.go b/examples/digispark_api.go index b409ba8f5..1930ff734 100644 --- a/examples/digispark_api.go +++ b/examples/digispark_api.go @@ -14,8 +14,8 @@ import ( ) func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() digisparkAdaptor := digispark.NewAdaptor() led := gpio.NewLedDriver(digisparkAdaptor, "0") @@ -25,9 +25,9 @@ func main() { []gobot.Device{led}, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/edison_button_led_api.go b/examples/edison_button_led_api.go index 70dad36df..167c7974f 100644 --- a/examples/edison_button_led_api.go +++ b/examples/edison_button_led_api.go @@ -16,8 +16,8 @@ import ( ) func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() e := edison.NewAdaptor() @@ -43,9 +43,9 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/firmata_blink_api.go b/examples/firmata_blink_api.go index 9d8c027c1..46a51cbfe 100644 --- a/examples/firmata_blink_api.go +++ b/examples/firmata_blink_api.go @@ -17,8 +17,8 @@ import ( ) func main() { - master := gobot.NewMaster() - a := api.NewAPI(master) + manager := gobot.NewManager() + a := api.NewAPI(manager) a.Start() firmataAdaptor := firmata.NewAdaptor("/dev/ttyACM0") @@ -38,9 +38,9 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/firmata_travis.go b/examples/firmata_travis.go index c8f16ff83..1cd3dc4bc 100644 --- a/examples/firmata_travis.go +++ b/examples/firmata_travis.go @@ -88,16 +88,16 @@ func checkTravis(robot *gobot.Robot) { } func main() { - master := gobot.NewMaster() + manager := gobot.NewManager() firmataAdaptor := firmata.NewAdaptor(os.Args[1]) red := gpio.NewLedDriver(firmataAdaptor, "7", gpio.WithName("red")) green := gpio.NewLedDriver(firmataAdaptor, "6", gpio.WithName("green")) blue := gpio.NewLedDriver(firmataAdaptor, "5", gpio.WithName("blue")) work := func() { - checkTravis(master.Robot("travis")) + checkTravis(manager.Robot("travis")) gobot.Every(10*time.Second, func() { - checkTravis(master.Robot("travis")) + checkTravis(manager.Robot("travis")) }) } @@ -107,8 +107,8 @@ func main() { work, ) - master.AddRobot(robot) - if err := master.Start(); err != nil { + manager.AddRobot(robot) + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/hello_api.go b/examples/hello_api.go index 9079343b8..0cb626783 100644 --- a/examples/hello_api.go +++ b/examples/hello_api.go @@ -16,27 +16,27 @@ import ( ) func main() { - master := gobot.NewMaster() + manager := gobot.NewManager() - a := api.NewAPI(master) + a := api.NewAPI(manager) a.AddHandler(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %q \n", html.EscapeString(r.URL.Path)) }) a.Debug() a.Start() - master.AddCommand("custom_gobot_command", + manager.AddCommand("custom_gobot_command", func(params map[string]interface{}) interface{} { return "This command is attached to the mcp!" }) - hello := master.AddRobot(gobot.NewRobot("hello")) + hello := manager.AddRobot(gobot.NewRobot("hello")) hello.AddCommand("hi_there", func(params map[string]interface{}) interface{} { return fmt.Sprintf("This command is attached to the robot %v", hello.Name) }) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/hello_api_auth.go b/examples/hello_api_auth.go index a4fa3249e..6afb7ff61 100644 --- a/examples/hello_api_auth.go +++ b/examples/hello_api_auth.go @@ -16,9 +16,9 @@ import ( ) func main() { - master := gobot.NewMaster() + manager := gobot.NewManager() - a := api.NewAPI(master) + a := api.NewAPI(manager) a.AddHandler(api.BasicAuth("gort", "klatuu")) a.Debug() @@ -27,18 +27,18 @@ func main() { }) a.Start() - master.AddCommand("custom_gobot_command", + manager.AddCommand("custom_gobot_command", func(params map[string]interface{}) interface{} { return "This command is attached to the mcp!" }) - hello := master.AddRobot(gobot.NewRobot("hello")) + hello := manager.AddRobot(gobot.NewRobot("hello")) hello.AddCommand("hi_there", func(params map[string]interface{}) interface{} { return fmt.Sprintf("This command is attached to the robot %v", hello.Name) }) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/hello_api_custom.go b/examples/hello_api_custom.go index 895165ecb..a1eff0b9a 100644 --- a/examples/hello_api_custom.go +++ b/examples/hello_api_custom.go @@ -15,9 +15,9 @@ import ( ) func main() { - master := gobot.NewMaster() + manager := gobot.NewManager() - a := api.NewAPI(master) + a := api.NewAPI(manager) // creates routes/handlers for the custom API a.Get("/", func(res http.ResponseWriter, req *http.Request) { @@ -26,7 +26,7 @@ func main() { } }) a.Get("/api/hello", func(res http.ResponseWriter, req *http.Request) { - msg := fmt.Sprintf("This command is attached to the robot %v", master.Robot("hello").Name) + msg := fmt.Sprintf("This command is attached to the robot %v", manager.Robot("hello").Name) if _, err := res.Write([]byte(msg)); err != nil { fmt.Println(err) } @@ -35,9 +35,9 @@ func main() { // starts the API without the default C2PIO API and Robeaux web interface. a.StartWithoutDefaults() - master.AddRobot(gobot.NewRobot("hello")) + manager.AddRobot(gobot.NewRobot("hello")) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/hello_api_video.go b/examples/hello_api_video.go index dbcf73e1d..469e661cf 100644 --- a/examples/hello_api_video.go +++ b/examples/hello_api_video.go @@ -28,9 +28,9 @@ func main() { // parse args deviceID := os.Args[1] - master := gobot.NewMaster() + manager := gobot.NewManager() - a := api.NewAPI(master) + a := api.NewAPI(manager) // add the standard C3PIO API routes manually. a.AddC3PIORoutes() @@ -40,7 +40,7 @@ func main() { // means the REST API will be available, but not the web interface. a.StartWithoutDefaults() - hello := master.AddRobot(gobot.NewRobot("hello")) + hello := manager.AddRobot(gobot.NewRobot("hello")) hello.AddCommand("hi_there", func(params map[string]interface{}) interface{} { return fmt.Sprintf("This command is attached to the robot %v", hello.Name) @@ -61,7 +61,7 @@ func main() { // start capturing go mjpegCapture() - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/particle_api.go b/examples/particle_api.go index ee267d073..0dbc30b7b 100644 --- a/examples/particle_api.go +++ b/examples/particle_api.go @@ -25,8 +25,8 @@ import ( ) func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() core := particle.NewAdaptor(os.Args[1], os.Args[2]) led := gpio.NewLedDriver(core, "D7") @@ -45,9 +45,9 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/pebble.go b/examples/pebble.go index 3bbe1bedd..80a481464 100644 --- a/examples/pebble.go +++ b/examples/pebble.go @@ -15,8 +15,8 @@ import ( ) func main() { - master := gobot.NewMaster() - api := api.NewAPI(master) + manager := gobot.NewManager() + api := api.NewAPI(manager) api.Port = "8080" api.Start() @@ -40,9 +40,9 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/pebble_accelerometer.go b/examples/pebble_accelerometer.go index 632989ed3..4887a40e9 100644 --- a/examples/pebble_accelerometer.go +++ b/examples/pebble_accelerometer.go @@ -15,8 +15,8 @@ import ( ) func main() { - master := gobot.NewMaster() - a := api.NewAPI(master) + manager := gobot.NewManager() + a := api.NewAPI(manager) a.Port = "8080" a.Start() @@ -35,9 +35,9 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/serialport_sphero_api.go b/examples/serialport_sphero_api.go index a6f2f3dfa..c12cd9f43 100644 --- a/examples/serialport_sphero_api.go +++ b/examples/serialport_sphero_api.go @@ -14,8 +14,8 @@ import ( ) func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() spheros := map[string]string{ "Sphero-BPO": "/dev/rfcomm0", @@ -39,10 +39,10 @@ func main() { return nil }) - master.AddRobot(robot) + manager.AddRobot(robot) } - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/serialport_sphero_calibration.go b/examples/serialport_sphero_calibration.go index ee3f46bd7..a4442fc2f 100644 --- a/examples/serialport_sphero_calibration.go +++ b/examples/serialport_sphero_calibration.go @@ -15,8 +15,8 @@ import ( ) func main() { - master := gobot.NewMaster() - a := api.NewAPI(master) + manager := gobot.NewManager() + a := api.NewAPI(manager) a.Start() ballConn := serialport.NewAdaptor("/dev/rfcomm0") @@ -62,9 +62,9 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/serialport_sphero_conways.go b/examples/serialport_sphero_conways.go index 47af59964..73e974791 100644 --- a/examples/serialport_sphero_conways.go +++ b/examples/serialport_sphero_conways.go @@ -25,7 +25,7 @@ type conway struct { } func main() { - master := gobot.NewMaster() + manager := gobot.NewManager() spheros := []string{ "/dev/rfcomm0", @@ -67,10 +67,10 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) } - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/serialport_sphero_dpad.go b/examples/serialport_sphero_dpad.go index a6206dec7..111b01150 100644 --- a/examples/serialport_sphero_dpad.go +++ b/examples/serialport_sphero_dpad.go @@ -16,8 +16,8 @@ import ( ) func main() { - master := gobot.NewMaster() - a := api.NewAPI(master) + manager := gobot.NewManager() + a := api.NewAPI(manager) a.Start() conn := serialport.NewAdaptor("/dev/rfcomm0") @@ -47,9 +47,9 @@ func main() { return "ok" }) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/serialport_sphero_master.go b/examples/serialport_sphero_master.go index a4c0e42e8..793858b3d 100644 --- a/examples/serialport_sphero_master.go +++ b/examples/serialport_sphero_master.go @@ -15,7 +15,7 @@ import ( ) func main() { - master := gobot.NewMaster() + manager := gobot.NewManager() spheros := map[string]string{ "Sphero-BPO": "/dev/rfcomm0", @@ -35,13 +35,13 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) } robot := gobot.NewRobot("", func() { gobot.Every(1*time.Second, func() { - sphero := master.Robot("Sphero-BPO").Device("sphero").(*sphero.SpheroDriver) + sphero := manager.Robot("Sphero-BPO").Device("sphero").(*sphero.SpheroDriver) sphero.SetRGB(uint8(gobot.Rand(255)), uint8(gobot.Rand(255)), uint8(gobot.Rand(255)), @@ -50,9 +50,9 @@ func main() { }, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/serialport_sphero_multiple.go b/examples/serialport_sphero_multiple.go index 65fef75dd..12058f566 100644 --- a/examples/serialport_sphero_multiple.go +++ b/examples/serialport_sphero_multiple.go @@ -50,8 +50,8 @@ func NewSwarmBot(port string) *gobot.Robot { } func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() spheros := []string{ "/dev/rfcomm0", @@ -61,10 +61,10 @@ func main() { } for _, port := range spheros { - master.AddRobot(NewSwarmBot(port)) + manager.AddRobot(NewSwarmBot(port)) } - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/square.go b/examples/square.go index 7a6c3fc30..5c99fb3bd 100644 --- a/examples/square.go +++ b/examples/square.go @@ -17,8 +17,8 @@ import ( ) func main() { - master := gobot.NewMaster() - a := api.NewAPI(master) + manager := gobot.NewManager() + a := api.NewAPI(manager) a.Start() board := edison.NewAdaptor() @@ -103,9 +103,9 @@ func main() { return enabled }) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/examples/square_fire.go b/examples/square_fire.go index 76980069d..6fa2eb5fe 100644 --- a/examples/square_fire.go +++ b/examples/square_fire.go @@ -17,8 +17,8 @@ import ( ) func main() { - master := gobot.NewMaster() - a := api.NewAPI(master) + manager := gobot.NewManager() + a := api.NewAPI(manager) a.Start() board := edison.NewAdaptor() @@ -103,9 +103,9 @@ func main() { return enabled }) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } diff --git a/master.go b/manager.go similarity index 67% rename from master.go rename to manager.go index 6119d6d12..eb0322f7f 100644 --- a/master.go +++ b/manager.go @@ -6,15 +6,15 @@ import ( "sync/atomic" ) -// JSONMaster is a JSON representation of a Gobot Master. -type JSONMaster struct { +// JSONManager is a JSON representation of a Gobot Manager. +type JSONManager struct { Robots []*JSONRobot `json:"robots"` Commands []string `json:"commands"` } -// NewJSONMaster returns a JSONMaster given a Gobot Master. -func NewJSONMaster(gobot *Master) *JSONMaster { - jsonGobot := &JSONMaster{ +// NewJSONManager returns a JSONManager given a Gobot Manager. +func NewJSONManager(gobot *Manager) *JSONManager { + jsonGobot := &JSONManager{ Robots: []*JSONRobot{}, Commands: []string{}, } @@ -29,9 +29,9 @@ func NewJSONMaster(gobot *Master) *JSONMaster { return jsonGobot } -// Master is the main type of your Gobot application and contains a collection of -// Robots, API commands that apply to the Master, and Events that apply to the Master. -type Master struct { +// Manager is the main type of your Gobot application and contains a collection of +// Robots, API commands that apply to the Manager, and Events that apply to the Manager. +type Manager struct { robots *Robots trap func(chan os.Signal) AutoRun bool @@ -40,9 +40,9 @@ type Master struct { Eventer } -// NewMaster returns a new Gobot Master -func NewMaster() *Master { - m := &Master{ +// NewManager returns a new Gobot Manager +func NewManager() *Manager { + m := &Manager{ robots: &Robots{}, trap: func(c chan os.Signal) { signal.Notify(c, os.Interrupt) @@ -58,7 +58,7 @@ func NewMaster() *Master { // Start calls the Start method on each robot in its collection of robots. On // error, call Stop to ensure that all robots are returned to a sane, stopped // state. -func (g *Master) Start() error { +func (g *Manager) Start() error { if err := g.robots.Start(!g.AutoRun); err != nil { return err } @@ -80,31 +80,31 @@ func (g *Master) Start() error { } // Stop calls the Stop method on each robot in its collection of robots. -func (g *Master) Stop() error { +func (g *Manager) Stop() error { err := g.robots.Stop() g.running.Store(false) return err } -// Running returns if the Master is currently started or not -func (g *Master) Running() bool { +// Running returns if the Manager is currently started or not +func (g *Manager) Running() bool { return g.running.Load().(bool) //nolint:forcetypeassert // no error return value, so there is no better way } -// Robots returns all robots associated with this Gobot Master. -func (g *Master) Robots() *Robots { +// Robots returns all robots associated with this Gobot Manager. +func (g *Manager) Robots() *Robots { return g.robots } // AddRobot adds a new robot to the internal collection of robots. Returns the // added robot -func (g *Master) AddRobot(r *Robot) *Robot { +func (g *Manager) AddRobot(r *Robot) *Robot { *g.robots = append(*g.robots, r) return r } // Robot returns a robot given name. Returns nil if the Robot does not exist. -func (g *Master) Robot(name string) *Robot { +func (g *Manager) Robot(name string) *Robot { for _, robot := range *g.Robots() { if robot.Name == name { return robot diff --git a/master_test.go b/manager_test.go similarity index 82% rename from master_test.go rename to manager_test.go index 6ac1ddca6..f9525fe36 100644 --- a/master_test.go +++ b/manager_test.go @@ -13,9 +13,9 @@ import ( "github.com/stretchr/testify/require" ) -func initTestMaster() *Master { +func initTestManager() *Manager { log.SetOutput(&NullReadWriteCloser{}) - g := NewMaster() + g := NewManager() g.trap = func(c chan os.Signal) { c <- os.Interrupt } @@ -25,9 +25,9 @@ func initTestMaster() *Master { return g } -func initTestMaster1Robot() *Master { +func initTestManager1Robot() *Manager { log.SetOutput(&NullReadWriteCloser{}) - g := NewMaster() + g := NewManager() g.trap = func(c chan os.Signal) { c <- os.Interrupt } @@ -45,8 +45,8 @@ func TestNullReadWriteCloser(t *testing.T) { require.NoError(t, n.Close()) } -func TestMasterRobot(t *testing.T) { - g := initTestMaster() +func TestManagerRobot(t *testing.T) { + g := initTestManager() assert.Equal(t, "Robot1", g.Robot("Robot1").Name) assert.Equal(t, (*Robot)(nil), g.Robot("Robot4")) assert.Equal(t, (Device)(nil), g.Robot("Robot4").Device("Device1")) @@ -58,25 +58,25 @@ func TestMasterRobot(t *testing.T) { assert.Equal(t, 3, g.Robot("Robot1").Connections().Len()) } -func TestMasterToJSON(t *testing.T) { - g := initTestMaster() +func TestManagerToJSON(t *testing.T) { + g := initTestManager() g.AddCommand("test_function", func(params map[string]interface{}) interface{} { return nil }) - json := NewJSONMaster(g) + json := NewJSONManager(g) assert.Len(t, json.Robots, g.Robots().Len()) assert.Len(t, json.Commands, len(g.Commands())) } -func TestMasterStart(t *testing.T) { - g := initTestMaster() +func TestManagerStart(t *testing.T) { + g := initTestManager() require.NoError(t, g.Start()) require.NoError(t, g.Stop()) assert.False(t, g.Running()) } -func TestMasterStartAutoRun(t *testing.T) { - g := NewMaster() +func TestManagerStartAutoRun(t *testing.T) { + g := NewManager() g.AddRobot(newTestRobot("Robot99")) go func() { _ = g.Start() }() time.Sleep(10 * time.Millisecond) @@ -87,8 +87,8 @@ func TestMasterStartAutoRun(t *testing.T) { assert.False(t, g.Running()) } -func TestMasterStartDriverErrors(t *testing.T) { - g := initTestMaster1Robot() +func TestManagerStartDriverErrors(t *testing.T) { + g := initTestManager1Robot() e := errors.New("driver start error 1") testDriverStart = func() error { return e @@ -105,8 +105,8 @@ func TestMasterStartDriverErrors(t *testing.T) { testDriverStart = func() error { return nil } } -func TestMasterHaltFromRobotDriverErrors(t *testing.T) { - g := initTestMaster1Robot() +func TestManagerHaltFromRobotDriverErrors(t *testing.T) { + g := initTestManager1Robot() var ec int testDriverHalt = func() error { ec++ @@ -123,8 +123,8 @@ func TestMasterHaltFromRobotDriverErrors(t *testing.T) { assert.Equal(t, want, g.Start()) } -func TestMasterStartRobotAdaptorErrors(t *testing.T) { - g := initTestMaster1Robot() +func TestManagerStartRobotAdaptorErrors(t *testing.T) { + g := initTestManager1Robot() var ec int testAdaptorConnect = func() error { ec++ @@ -144,8 +144,8 @@ func TestMasterStartRobotAdaptorErrors(t *testing.T) { testAdaptorConnect = func() error { return nil } } -func TestMasterFinalizeErrors(t *testing.T) { - g := initTestMaster1Robot() +func TestManagerFinalizeErrors(t *testing.T) { + g := initTestManager1Robot() var ec int testAdaptorFinalize = func() error { ec++ diff --git a/platforms/pebble/README.md b/platforms/pebble/README.md index c12e35005..10f431171 100644 --- a/platforms/pebble/README.md +++ b/platforms/pebble/README.md @@ -29,8 +29,8 @@ import ( ) func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() pebbleAdaptor := pebble.NewAdaptor() watch := pebble.NewDriver(pebbleAdaptor) @@ -52,11 +52,11 @@ func main() { work, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { - panic(err) - } + if err := manager.Start(); err != nil { + panic(err) + } } ``` diff --git a/platforms/pebble/doc.go b/platforms/pebble/doc.go index 308056536..1c95fd21f 100644 --- a/platforms/pebble/doc.go +++ b/platforms/pebble/doc.go @@ -24,8 +24,8 @@ your computer IP, robot name is 'pebble' and robot api port is 8080 ) func main() { - master := gobot.NewMaster() - api.NewAPI(master).Start() + manager := gobot.NewManager() + api.NewAPI(manager).Start() pebbleAdaptor := pebble.NewAdaptor() watch := pebble.NewDriver(pebbleAdaptor) @@ -47,9 +47,9 @@ your computer IP, robot name is 'pebble' and robot api port is 8080 work, ) - master.AddRobot(robot) + manager.AddRobot(robot) - if err := master.Start(); err != nil { + if err := manager.Start(); err != nil { panic(err) } } From bfba1ab9e0eb0970d4905ea2e7d1a69f7863285d Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 13 Feb 2024 18:16:18 +0100 Subject: [PATCH 52/57] i2c/spi: remove offensive terminology (#1071) --- drivers/i2c/i2c_connection_test.go | 2 +- examples/tinkerboard_mfcrc522gpio.go | 10 ++-- examples/tinkerboard_mfcrc522spi.go | 2 +- platforms/adaptors/digitalpinsadaptor.go | 4 +- .../adaptors/digitalpinsadaptoroptions.go | 6 +-- platforms/beaglebone/beaglebone_adaptor.go | 2 +- platforms/beaglebone/pocketbeagle_adaptor.go | 2 +- platforms/chip/chip_adaptor.go | 2 +- platforms/digispark/littleWire.h | 4 +- platforms/dragonboard/dragonboard_adaptor.go | 2 +- platforms/intel-iot/curie/imu_driver.go | 6 +-- platforms/intel-iot/joule/joule_adaptor.go | 2 +- platforms/jetson/jetson_adaptor.go | 2 +- platforms/mavlink/common/common.go | 4 +- platforms/nanopi/nanopi_adaptor.go | 2 +- platforms/nanopi/nanopineo_pin_map.go | 4 +- platforms/raspi/raspi_adaptor.go | 2 +- platforms/rockpi/rockpi_adaptor.go | 2 +- platforms/tinkerboard/adaptor.go | 2 +- platforms/upboard/up2/adaptor.go | 2 +- system/GPIO.md | 4 +- system/I2C.md | 2 +- system/i2c_device.go | 8 +-- system/i2c_device_test.go | 2 +- system/spi_gpio.go | 50 +++++++++---------- system/syscall.go | 2 +- system/syscall_mock.go | 2 +- system/system_options.go | 14 +++--- 28 files changed, 74 insertions(+), 74 deletions(-) diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go index 248d90f48..4d9f4110f 100644 --- a/drivers/i2c/i2c_connection_test.go +++ b/drivers/i2c/i2c_connection_test.go @@ -37,7 +37,7 @@ func getSyscallFuncImpl( system.I2C_FUNC_SMBUS_WRITE_WORD_DATA } // set address - if (trap == system.Syscall_SYS_IOCTL) && (a2 == system.I2C_SLAVE) { + if (trap == system.Syscall_SYS_IOCTL) && (a2 == system.I2C_TARGET) { if errorMask&0x02 == 0x02 { return 0, 0, 1 } diff --git a/examples/tinkerboard_mfcrc522gpio.go b/examples/tinkerboard_mfcrc522gpio.go index 484743bd2..7843b8fdf 100644 --- a/examples/tinkerboard_mfcrc522gpio.go +++ b/examples/tinkerboard_mfcrc522gpio.go @@ -19,17 +19,17 @@ import ( // Wiring // PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) // GPIO-SPI Tinkerboard (same as SPI2): 23 (CLK), 19 (TXD), 21 (RXD), 24 (CSN0) -// MFRC522 plate: VCC, GND, SCK (CLK), MOSI (->TXD), MISO (->RXD), NSS/SDA (CSN0/CSN1?) +// MFRC522 plate: VCC, GND, SCK (CLK), SDO (->TXD), SDI (->RXD), NCS/SDA (CSN0/CSN1?) const ( sclk = "23" - nss = "24" - mosi = "19" - miso = "21" + ncs = "24" + sdo = "19" + sdi = "21" speedHz = 5000 // more than 15kHz is not possible with GPIO's, so we choose 5kHz ) func main() { - a := tinkerboard.NewAdaptor(adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso)) + a := tinkerboard.NewAdaptor(adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi)) d := spi.NewMFRC522Driver(a, spi.WithSpeed(speedHz)) wasCardDetected := false diff --git a/examples/tinkerboard_mfcrc522spi.go b/examples/tinkerboard_mfcrc522spi.go index 161567e9c..33d549621 100644 --- a/examples/tinkerboard_mfcrc522spi.go +++ b/examples/tinkerboard_mfcrc522spi.go @@ -19,7 +19,7 @@ import ( // PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND) // SPI0 Tinkerboard (not working with armbian): 11 (CLK), 13 (TXD), 15 (RXD), 29 (CSN0), 31 (CSN1, n.c.) // SPI2 Tinkerboard: 23 (CLK), 19 (TXD), 21 (RXD), 24 (CSN0), 26 (CSN1, n.c.) -// MFRC522 plate: VCC, GND, SCK (CLK), MOSI (->TXD), MISO (->RXD), NSS/SDA (CSN0/CSN1?) +// MFRC522 plate: VCC, GND, SCK (CLK), SDO (->TXD), SDI (->RXD), NCS/SDA (CSN0/CSN1?) func main() { a := tinkerboard.NewAdaptor() d := spi.NewMFRC522Driver(a, spi.WithBusNumber(2)) diff --git a/platforms/adaptors/digitalpinsadaptor.go b/platforms/adaptors/digitalpinsadaptor.go index d60aa9be6..943814b51 100644 --- a/platforms/adaptors/digitalpinsadaptor.go +++ b/platforms/adaptors/digitalpinsadaptor.go @@ -63,9 +63,9 @@ func WithGpiodAccess() func(DigitalPinsOptioner) { } // WithSpiGpioAccess can be used to switch the default SPI implementation to GPIO usage. -func WithSpiGpioAccess(sclkPin, nssPin, mosiPin, misoPin string) func(DigitalPinsOptioner) { +func WithSpiGpioAccess(sclkPin, ncsPin, sdoPin, sdiPin string) func(DigitalPinsOptioner) { return func(o DigitalPinsOptioner) { - o.setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin) + o.setDigitalPinsForSystemSpi(sclkPin, ncsPin, sdoPin, sdiPin) } } diff --git a/platforms/adaptors/digitalpinsadaptoroptions.go b/platforms/adaptors/digitalpinsadaptoroptions.go index 6aefbf700..b39339022 100644 --- a/platforms/adaptors/digitalpinsadaptoroptions.go +++ b/platforms/adaptors/digitalpinsadaptoroptions.go @@ -13,7 +13,7 @@ import ( type DigitalPinsOptioner interface { setDigitalPinInitializer(initializer digitalPinInitializer) setDigitalPinsForSystemGpiod() - setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string) + setDigitalPinsForSystemSpi(sclkPin, ncsPin, sdoPin, sdiPin string) prepareDigitalPinsActiveLow(pin string, otherPins ...string) prepareDigitalPinsPullDown(pin string, otherPins ...string) prepareDigitalPinsPullUp(pin string, otherPins ...string) @@ -37,8 +37,8 @@ func (a *DigitalPinsAdaptor) setDigitalPinsForSystemGpiod() { system.WithDigitalPinGpiodAccess()(a.sys) } -func (a *DigitalPinsAdaptor) setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string) { - system.WithSpiGpioAccess(a, sclkPin, nssPin, mosiPin, misoPin)(a.sys) +func (a *DigitalPinsAdaptor) setDigitalPinsForSystemSpi(sclkPin, ncsPin, sdoPin, sdiPin string) { + system.WithSpiGpioAccess(a, sclkPin, ncsPin, sdoPin, sdiPin)(a.sys) } func (a *DigitalPinsAdaptor) prepareDigitalPinsActiveLow(id string, otherIDs ...string) { diff --git a/platforms/beaglebone/beaglebone_adaptor.go b/platforms/beaglebone/beaglebone_adaptor.go index 3355497e4..c95fb170e 100644 --- a/platforms/beaglebone/beaglebone_adaptor.go +++ b/platforms/beaglebone/beaglebone_adaptor.go @@ -60,7 +60,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // // Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] func NewAdaptor(opts ...interface{}) *Adaptor { diff --git a/platforms/beaglebone/pocketbeagle_adaptor.go b/platforms/beaglebone/pocketbeagle_adaptor.go index 5ef366970..907b37e40 100644 --- a/platforms/beaglebone/pocketbeagle_adaptor.go +++ b/platforms/beaglebone/pocketbeagle_adaptor.go @@ -16,7 +16,7 @@ type PocketBeagleAdaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // // Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] func NewPocketBeagleAdaptor(opts ...interface{}) *PocketBeagleAdaptor { diff --git a/platforms/chip/chip_adaptor.go b/platforms/chip/chip_adaptor.go index 7f9d999ce..cdd3092ee 100644 --- a/platforms/chip/chip_adaptor.go +++ b/platforms/chip/chip_adaptor.go @@ -41,7 +41,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // // Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] func NewAdaptor(opts ...interface{}) *Adaptor { diff --git a/platforms/digispark/littleWire.h b/platforms/digispark/littleWire.h index ada3f0dbc..a348f7036 100644 --- a/platforms/digispark/littleWire.h +++ b/platforms/digispark/littleWire.h @@ -339,7 +339,7 @@ void spi_init(littleWire* lwHandle); void spi_sendMessage(littleWire* lwHandle, unsigned char * sendBuffer, unsigned char * inputBuffer, unsigned char length ,unsigned char mode); /** - * Send one byte SPI message over MOSI pin. Slightly slower than the actual one. + * Send one byte SPI message over SDO pin. Slightly slower than the actual one. * \n There isn't any chip select control involved. Useful for debug console app * * @param lwHandle littleWire device pointer @@ -376,7 +376,7 @@ void i2c_init(littleWire* lwHandle); * Start the i2c communication * * @param lwHandle littleWire device pointer - * @param address 7 bit slave address. + * @param address 7 bit target address. * @param direction ( \b READ or \b WRITE ) * @return 1 if received ACK */ diff --git a/platforms/dragonboard/dragonboard_adaptor.go b/platforms/dragonboard/dragonboard_adaptor.go index 5941b995f..ea1e2d35f 100644 --- a/platforms/dragonboard/dragonboard_adaptor.go +++ b/platforms/dragonboard/dragonboard_adaptor.go @@ -49,7 +49,7 @@ var fixedPins = map[string]int{ // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { sys := system.NewAccesser() c := &Adaptor{ diff --git a/platforms/intel-iot/curie/imu_driver.go b/platforms/intel-iot/curie/imu_driver.go index 15998c84d..185e6bc0f 100644 --- a/platforms/intel-iot/curie/imu_driver.go +++ b/platforms/intel-iot/curie/imu_driver.go @@ -86,13 +86,13 @@ func (imu *IMUDriver) Start() error { // Halt stops the IMUDriver func (imu *IMUDriver) Halt() error { return nil } -// Name returns the IMUDriver's name +// Name returns the IMUDrivers name func (imu *IMUDriver) Name() string { return imu.name } -// SetName sets the IMUDriver'ss name +// SetName sets the IMUDrivers name func (imu *IMUDriver) SetName(n string) { imu.name = n } -// Connection returns the IMUDriver's Connection +// Connection returns the IMUDrivers Connection func (imu *IMUDriver) Connection() gobot.Connection { return imu.connection } // ReadAccelerometer calls the Curie's built-in accelerometer. The result will diff --git a/platforms/intel-iot/joule/joule_adaptor.go b/platforms/intel-iot/joule/joule_adaptor.go index ba612e12a..b20c01eec 100644 --- a/platforms/intel-iot/joule/joule_adaptor.go +++ b/platforms/intel-iot/joule/joule_adaptor.go @@ -33,7 +33,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // // Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] func NewAdaptor(opts ...interface{}) *Adaptor { diff --git a/platforms/jetson/jetson_adaptor.go b/platforms/jetson/jetson_adaptor.go index 1d3160535..748babb15 100644 --- a/platforms/jetson/jetson_adaptor.go +++ b/platforms/jetson/jetson_adaptor.go @@ -41,7 +41,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // // Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] func NewAdaptor(opts ...interface{}) *Adaptor { diff --git a/platforms/mavlink/common/common.go b/platforms/mavlink/common/common.go index 2b3dbca7a..449b1e403 100644 --- a/platforms/mavlink/common/common.go +++ b/platforms/mavlink/common/common.go @@ -451,7 +451,7 @@ const ( MAV_CMD_DO_PARACHUTE = 208 // Mission command to trigger a parachute | action (0=disable, 1=enable, 2=release, for some systems see PARACHUTE_ACTION enum, not in general message set.) | Empty | Empty | Empty | Empty | Empty | Empty | MAV_CMD_DO_INVERTED_FLIGHT = 210 // Change to/from inverted flight | inverted (0=normal, 1=inverted) | Empty | Empty | Empty | Empty | Empty | Empty | MAV_CMD_DO_MOUNT_CONTROL_QUAT = 220 // Mission command to control a camera or antenna mount, using a quaternion as reference. | q1 - quaternion param #1, w (1 in null-rotation) | q2 - quaternion param #2, x (0 in null-rotation) | q3 - quaternion param #3, y (0 in null-rotation) | q4 - quaternion param #4, z (0 in null-rotation) | Empty | Empty | Empty | - MAV_CMD_DO_GUIDED_MASTER = 221 // set id of master controller | System ID | Component ID | Empty | Empty | Empty | Empty | Empty | + MAV_CMD_DO_GUIDED_CONTROLLER = 221 // set id of the controller | System ID | Component ID | Empty | Empty | Empty | Empty | Empty | MAV_CMD_DO_GUIDED_LIMITS = 222 // set limits for external control | timeout - maximum time (in seconds) that external controller will be allowed to control vehicle. 0 means no timeout | absolute altitude min (in meters, WGS84) - if vehicle moves below this alt, the command will be aborted and the mission will continue. 0 means no lower altitude limit | absolute altitude max (in meters)- if vehicle moves above this alt, the command will be aborted and the mission will continue. 0 means no upper altitude limit | horizontal move limit (in meters, WGS84) - if vehicle moves more than this distance from it's location at the moment the command was executed, the command will be aborted and the mission will continue. 0 means no horizontal altitude limit | Empty | Empty | Empty | MAV_CMD_DO_LAST = 240 // NOP - This command is only used to mark the upper limit of the DO commands in the enumeration | Empty | Empty | Empty | Empty | Empty | Empty | Empty | MAV_CMD_PREFLIGHT_CALIBRATION = 241 // Trigger calibration. This command will be only accepted if in pre-flight mode. | Gyro calibration: 0: no, 1: yes | Magnetometer calibration: 0: no, 1: yes | Ground pressure: 0: no, 1: yes | Radio calibration: 0: no, 1: yes | Accelerometer calibration: 0: no, 1: yes | Compass/Motor interference calibration: 0: no, 1: yes | Empty | @@ -879,7 +879,7 @@ func (m *SysStatus) Decode(buf []byte) { // // MAVLINK_MSG_ID_SYSTEM_TIME_CRC 137 type SystemTime struct { - TIME_UNIX_USEC uint64 // Timestamp of the master clock in microseconds since UNIX epoch. + TIME_UNIX_USEC uint64 // Timestamp of the primary reference clock in microseconds since UNIX epoch. TIME_BOOT_MS uint32 // Timestamp of the component clock since boot time in milliseconds. } diff --git a/platforms/nanopi/nanopi_adaptor.go b/platforms/nanopi/nanopi_adaptor.go index d0da14c1d..42d7cbd3c 100644 --- a/platforms/nanopi/nanopi_adaptor.go +++ b/platforms/nanopi/nanopi_adaptor.go @@ -63,7 +63,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // adaptors.WithGpiosActiveLow(pin's): invert the pin behavior // adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor // adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior diff --git a/platforms/nanopi/nanopineo_pin_map.go b/platforms/nanopi/nanopineo_pin_map.go index e055c1c29..349923666 100644 --- a/platforms/nanopi/nanopineo_pin_map.go +++ b/platforms/nanopi/nanopineo_pin_map.go @@ -8,8 +8,8 @@ var neoGpioPins = map[string]gpioPinDefinition{ "13": {sysfs: 2, cdev: cdevPin{chip: 0, line: 2}}, // UART2_RTS/GPIOA2 "15": {sysfs: 3, cdev: cdevPin{chip: 0, line: 3}}, // UART2_CTS/GPIOA3 "12": {sysfs: 6, cdev: cdevPin{chip: 0, line: 6}}, // GPIOA6 - "19": {sysfs: 64, cdev: cdevPin{chip: 0, line: 64}}, // SPI0_MOSI/GPIOC0 - "21": {sysfs: 65, cdev: cdevPin{chip: 0, line: 65}}, // SPI0_MISO/GPIOC1 + "19": {sysfs: 64, cdev: cdevPin{chip: 0, line: 64}}, // SPI0_SDO/GPIOC0 + "21": {sysfs: 65, cdev: cdevPin{chip: 0, line: 65}}, // SPI0_SDI/GPIOC1 "23": {sysfs: 66, cdev: cdevPin{chip: 0, line: 66}}, // SPI0_CLK/GPIOC2 "24": {sysfs: 67, cdev: cdevPin{chip: 0, line: 67}}, // SPI0_CS/GPIOC3 "8": {sysfs: 198, cdev: cdevPin{chip: 0, line: 198}}, // UART1_TX/GPIOG6 diff --git a/platforms/raspi/raspi_adaptor.go b/platforms/raspi/raspi_adaptor.go index e8b25bd7f..b8ffa95da 100644 --- a/platforms/raspi/raspi_adaptor.go +++ b/platforms/raspi/raspi_adaptor.go @@ -48,7 +48,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // adaptors.WithGpiosActiveLow(pin's): invert the pin behavior // adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor // adaptors.WithGpiosOpenDrain/Source(pin's): sets the output behavior diff --git a/platforms/rockpi/rockpi_adaptor.go b/platforms/rockpi/rockpi_adaptor.go index de76717ee..2778fe091 100644 --- a/platforms/rockpi/rockpi_adaptor.go +++ b/platforms/rockpi/rockpi_adaptor.go @@ -42,7 +42,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of the default sysfs (NOT work on RockPi4C+!) -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // adaptors.WithGpiosActiveLow(pin's): invert the pin behavior func NewAdaptor(opts ...func(adaptors.DigitalPinsOptioner)) *Adaptor { sys := system.NewAccesser() diff --git a/platforms/tinkerboard/adaptor.go b/platforms/tinkerboard/adaptor.go index 8dc9a4b5b..49f8eca72 100644 --- a/platforms/tinkerboard/adaptor.go +++ b/platforms/tinkerboard/adaptor.go @@ -61,7 +61,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs (still used by default) -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // adaptors.WithGpiosActiveLow(pin's): invert the pin behavior // adaptors.WithGpiosPullUp/Down(pin's): sets the internal pull resistor // diff --git a/platforms/upboard/up2/adaptor.go b/platforms/upboard/up2/adaptor.go index b58d1258d..4641303c2 100644 --- a/platforms/upboard/up2/adaptor.go +++ b/platforms/upboard/up2/adaptor.go @@ -55,7 +55,7 @@ type Adaptor struct { // Optional parameters: // // adaptors.WithGpiodAccess(): use character device gpiod driver instead of sysfs -// adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso): use GPIO's instead of /dev/spidev#.# +// adaptors.WithSpiGpioAccess(sclk, ncs, sdo, sdi): use GPIO's instead of /dev/spidev#.# // // Optional parameters for PWM, see [adaptors.NewPWMPinsAdaptor] func NewAdaptor(opts ...interface{}) *Adaptor { diff --git a/system/GPIO.md b/system/GPIO.md index e2a4fae1c..66045b258 100644 --- a/system/GPIO.md +++ b/system/GPIO.md @@ -66,8 +66,8 @@ gpiochip0 - 54 lines: ... line 7: "SPI_CE1_N" unused input active-high line 8: "SPI_CE0_N" unused input active-high - line 9: "SPI_MISO" unused input active-high - line 10: "SPI_MOSI" unused input active-high + line 9: "SPI_SDI" unused input active-high + line 10: "SPI_SDO" unused input active-high line 11: "SPI_SCLK" unused input active-high ... line 14: "TXD0" unused input active-high diff --git a/system/I2C.md b/system/I2C.md index 7d656055e..769e1f785 100644 --- a/system/I2C.md +++ b/system/I2C.md @@ -23,7 +23,7 @@ In general there are different ioctl features for I2C > Some calls are branched by kernels [i2c-dev.c:i2cdev_ioctl()](https://elixir.bootlin.com/linux/latest/source/drivers/i2c/i2c-dev.c#L392) > to the next listed calls. -Set the device address `ioctl(file, I2C_SLAVE, long addr)`. The call set the address directly to the character device. +Set the device address `ioctl(file, I2C_TARGET, long addr)`. The call set the address directly to the character device. Query the supported functions `ioctl(file, I2C_FUNCS, unsigned long *funcs)`. The call is converted to in-kernel function [i2c.h:i2c_get_functionality()](https://elixir.bootlin.com/linux/latest/source/include/linux/i2c.h#L902) diff --git a/system/i2c_device.go b/system/i2c_device.go index 8c8e9f077..2a3d83b14 100644 --- a/system/i2c_device.go +++ b/system/i2c_device.go @@ -16,9 +16,9 @@ const ( const ( // From /usr/include/linux/i2c-dev.h: // ioctl signals - I2C_SLAVE = 0x0703 - I2C_FUNCS = 0x0705 - I2C_SMBUS = 0x0720 + I2C_TARGET = 0x0703 + I2C_FUNCS = 0x0705 + I2C_SMBUS = 0x0720 // Read/write markers I2C_SMBUS_READ = 1 I2C_SMBUS_WRITE = 0 @@ -371,7 +371,7 @@ func (d *i2cDevice) setAddress(address int) error { return nil } - if err := d.syscallIoctl(I2C_SLAVE, nil, address, "Setting address"); err != nil { + if err := d.syscallIoctl(I2C_TARGET, nil, address, "Setting address"); err != nil { return err } d.lastAddress = address diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index b7b473885..95725899d 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -34,7 +34,7 @@ func getSyscallFuncImpl( I2C_FUNC_SMBUS_WRITE_WORD_DATA } // set address - if (trap == Syscall_SYS_IOCTL) && (a2 == I2C_SLAVE) { + if (trap == Syscall_SYS_IOCTL) && (a2 == I2C_TARGET) { if errorMask&0x02 == 0x02 { return 0, 0, 1 } diff --git a/system/spi_gpio.go b/system/spi_gpio.go index 5a21ff7d2..48c96212d 100644 --- a/system/spi_gpio.go +++ b/system/spi_gpio.go @@ -12,9 +12,9 @@ import ( type spiGpioConfig struct { pinProvider gobot.DigitalPinnerProvider sclkPinID string - nssPinID string - mosiPinID string - misoPinID string + ncsPinID string + sdoPinID string + sdiPinID string } // spiGpio is the implementation of the SPI interface using GPIO's. @@ -23,9 +23,9 @@ type spiGpio struct { // time between clock edges (i.e. half the cycle time) tclk time.Duration sclkPin gobot.DigitalPinner - nssPin gobot.DigitalPinner - mosiPin gobot.DigitalPinner - misoPin gobot.DigitalPinner + ncsPin gobot.DigitalPinner + sdoPin gobot.DigitalPinner + sdiPin gobot.DigitalPinner } // newSpiGpio creates and returns a new SPI connection based on given GPIO's. @@ -60,7 +60,7 @@ func (s *spiGpio) TxRx(tx []byte, rx []byte) error { } } - if err := s.nssPin.Write(0); err != nil { + if err := s.ncsPin.Write(0); err != nil { return err } @@ -74,7 +74,7 @@ func (s *spiGpio) TxRx(tx []byte, rx []byte) error { } } - return s.nssPin.Write(1) + return s.ncsPin.Write(1) } // Close the SPI connection. Implements gobot.SpiSystemDevicer. @@ -85,18 +85,18 @@ func (s *spiGpio) Close() error { err = multierror.Append(err, e) } } - if s.mosiPin != nil { - if e := s.mosiPin.Unexport(); e != nil { + if s.sdoPin != nil { + if e := s.sdoPin.Unexport(); e != nil { err = multierror.Append(err, e) } } - if s.misoPin != nil { - if e := s.misoPin.Unexport(); e != nil { + if s.sdiPin != nil { + if e := s.sdiPin.Unexport(); e != nil { err = multierror.Append(err, e) } } - if s.nssPin != nil { - if e := s.nssPin.Unexport(); e != nil { + if s.ncsPin != nil { + if e := s.ncsPin.Unexport(); e != nil { err = multierror.Append(err, e) } } @@ -104,7 +104,7 @@ func (s *spiGpio) Close() error { } func (cfg *spiGpioConfig) String() string { - return fmt.Sprintf("sclk: %s, nss: %s, mosi: %s, miso: %s", cfg.sclkPinID, cfg.nssPinID, cfg.mosiPinID, cfg.misoPinID) + return fmt.Sprintf("sclk: %s, ncs: %s, sdo: %s, sdi: %s", cfg.sclkPinID, cfg.ncsPinID, cfg.sdoPinID, cfg.sdiPinID) } // transferByte simultaneously transmit and receive a byte @@ -116,7 +116,7 @@ func (s *spiGpio) transferByte(txByte uint8) (uint8, error) { bitMask := uint8(0x80) // start at MSBit for i := 0; i < 8; i++ { - if err := s.mosiPin.Write(int(txByte & bitMask)); err != nil { + if err := s.sdoPin.Write(int(txByte & bitMask)); err != nil { return 0, err } @@ -125,7 +125,7 @@ func (s *spiGpio) transferByte(txByte uint8) (uint8, error) { return 0, err } - v, err := s.misoPin.Read() + v, err := s.sdiPin.Read() if err != nil { return 0, err } @@ -146,12 +146,12 @@ func (s *spiGpio) transferByte(txByte uint8) (uint8, error) { func (s *spiGpio) initializeGpios() error { var err error - // nss is an output, negated (currently not implemented at pin level) - s.nssPin, err = s.cfg.pinProvider.DigitalPin(s.cfg.nssPinID) + // ncs is an output, negated (currently not implemented at pin level) + s.ncsPin, err = s.cfg.pinProvider.DigitalPin(s.cfg.ncsPinID) if err != nil { return err } - if err := s.nssPin.ApplyOptions(WithPinDirectionOutput(1)); err != nil { + if err := s.ncsPin.ApplyOptions(WithPinDirectionOutput(1)); err != nil { return err } // sclk is an output, CPOL = 0 @@ -162,15 +162,15 @@ func (s *spiGpio) initializeGpios() error { if err := s.sclkPin.ApplyOptions(WithPinDirectionOutput(0)); err != nil { return err } - // miso is an input - s.misoPin, err = s.cfg.pinProvider.DigitalPin(s.cfg.misoPinID) + // sdi is an input + s.sdiPin, err = s.cfg.pinProvider.DigitalPin(s.cfg.sdiPinID) if err != nil { return err } - // mosi is an output - s.mosiPin, err = s.cfg.pinProvider.DigitalPin(s.cfg.mosiPinID) + // sdo is an output + s.sdoPin, err = s.cfg.pinProvider.DigitalPin(s.cfg.sdoPinID) if err != nil { return err } - return s.mosiPin.ApplyOptions(WithPinDirectionOutput(0)) + return s.sdoPin.ApplyOptions(WithPinDirectionOutput(0)) } diff --git a/system/syscall.go b/system/syscall.go index 41f29441a..03b05b246 100644 --- a/system/syscall.go +++ b/system/syscall.go @@ -39,7 +39,7 @@ func (sys *nativeSyscall) syscall( address uint16, ) (r1, r2 uintptr, err SyscallErrno) { var errNo unix.Errno - if signal == I2C_SLAVE { + if signal == I2C_TARGET { // this is the setup for the address, it just needs to be converted to an uintptr, // the given payload is not used in this case, see the comment on the function r1, r2, errNo = unix.Syscall(trap, f.Fd(), signal, uintptr(address)) diff --git a/system/syscall_mock.go b/system/syscall_mock.go index 1f77f2d11..020ade25f 100644 --- a/system/syscall_mock.go +++ b/system/syscall_mock.go @@ -30,7 +30,7 @@ func (sys *mockSyscall) syscall( sys.lastFile = f // a character device file (e.g. file to path "/dev/i2c-1") sys.lastSignal = signal // points to used function type (e.g. I2C_SMBUS, I2C_RDWR) - if signal == I2C_SLAVE { + if signal == I2C_TARGET { // this is the setup for the address, it needs to be converted to an uintptr, // the given payload is not used in this case, see the comment on the function used for production sys.devAddress = uintptr(address) diff --git a/system/system_options.go b/system/system_options.go index 049d888c7..bcabd4244 100644 --- a/system/system_options.go +++ b/system/system_options.go @@ -10,7 +10,7 @@ import ( // caller/user when creating the system access, e.g. by "NewAccesser()". type Optioner interface { setDigitalPinToGpiodAccess() - setSpiToGpioAccess(p gobot.DigitalPinnerProvider, sclkPin, nssPin, mosiPin, misoPin string) + setSpiToGpioAccess(p gobot.DigitalPinnerProvider, sclkPin, ncsPin, sdoPin, sdiPin string) } // WithDigitalPinGpiodAccess can be used to change the default sysfs implementation for digital pins to the character @@ -22,9 +22,9 @@ func WithDigitalPinGpiodAccess() func(Optioner) { } // WithSpiGpioAccess can be used to switch the default SPI implementation to GPIO usage. -func WithSpiGpioAccess(p gobot.DigitalPinnerProvider, sclkPin, nssPin, mosiPin, misoPin string) func(Optioner) { +func WithSpiGpioAccess(p gobot.DigitalPinnerProvider, sclkPin, ncsPin, sdoPin, sdiPin string) func(Optioner) { return func(s Optioner) { - s.setSpiToGpioAccess(p, sclkPin, nssPin, mosiPin, misoPin) + s.setSpiToGpioAccess(p, sclkPin, ncsPin, sdoPin, sdiPin) } } @@ -42,13 +42,13 @@ func (a *Accesser) setDigitalPinToGpiodAccess() { } } -func (a *Accesser) setSpiToGpioAccess(p gobot.DigitalPinnerProvider, sclkPin, nssPin, mosiPin, misoPin string) { +func (a *Accesser) setSpiToGpioAccess(p gobot.DigitalPinnerProvider, sclkPin, ncsPin, sdoPin, sdiPin string) { cfg := spiGpioConfig{ pinProvider: p, sclkPinID: sclkPin, - nssPinID: nssPin, - mosiPinID: mosiPin, - misoPinID: misoPin, + ncsPinID: ncsPin, + sdoPinID: sdoPin, + sdiPinID: sdiPin, } gsa := &gpioSpiAccess{cfg: cfg} if gsa.isSupported() { From fd85df03e31a055854ffc3fd10404d72b73b5b51 Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Thu, 31 Oct 2024 18:39:48 +0100 Subject: [PATCH 53/57] build(go, deps): update modules (#1092) --- go.mod | 26 +++++++------- go.sum | 53 ++++++++++++++--------------- platforms/nats/nats_adaptor_test.go | 2 +- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/go.mod b/go.mod index d00bf9181..3bd97c5e0 100644 --- a/go.mod +++ b/go.mod @@ -6,20 +6,20 @@ require ( github.com/0xcafed00d/joystick v1.0.1 github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 - github.com/eclipse/paho.mqtt.golang v1.4.3 + github.com/eclipse/paho.mqtt.golang v1.5.0 github.com/gofrs/uuid v4.4.0+incompatible github.com/hashicorp/go-multierror v1.1.1 github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e - github.com/nats-io/nats.go v1.32.0 + github.com/nats-io/nats.go v1.37.0 github.com/nsf/termbox-go v1.1.1 github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f - github.com/stretchr/testify v1.8.4 - github.com/warthog618/gpiod v0.8.2 - go.bug.st/serial v1.6.1 - gocv.io/x/gocv v0.35.0 - golang.org/x/net v0.21.0 - golang.org/x/sys v0.17.0 + github.com/stretchr/testify v1.9.0 + github.com/warthog618/gpiod v0.8.3 + go.bug.st/serial v1.6.2 + gocv.io/x/gocv v0.39.0 + golang.org/x/net v0.30.0 + golang.org/x/sys v0.26.0 periph.io/x/conn/v3 v3.7.0 periph.io/x/host/v3 v3.8.2 tinygo.org/x/bluetooth v0.8.0 @@ -31,18 +31,18 @@ require ( github.com/fatih/structs v1.1.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.6 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/muka/go-bluetooth v0.0.0-20240115085408-dfdf79b8f61d // indirect + github.com/muka/go-bluetooth v0.0.0-20240701044517-04c4f09c514e // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/saltosystems/winrt-go v0.0.0-20240110120258-ad49e9790c38 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/tinygo-org/cbgo v0.0.4 // indirect - golang.org/x/crypto v0.19.0 // indirect - golang.org/x/sync v0.6.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/sync v0.8.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d6278d132..c1773eb6b 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 h1:C7t6eeMaEQVy6e8CarIhscYQlNmw5e3G36y7l7Y21Ao= github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw= -github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik= -github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE= +github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o= +github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= @@ -21,8 +21,8 @@ github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -32,8 +32,8 @@ github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 h1:7of6LJZ4 github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78/go.mod h1:YllNbhGM1UEcySxCv1BWK5lre7QLmJJ+O0ADUOo2nbc= github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e h1:xCcwD5FOXul+j1dn8xD16nbrhJkkum/Cn+jTd/u1LhY= github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM805MRKrioHYuU7iKLUyFPVKqVV6um5DAvCkUtXs= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -41,10 +41,10 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/muka/go-bluetooth v0.0.0-20240115085408-dfdf79b8f61d h1:7ZjEBZo3QkT5hu4koEPrNJ5SKQ2NdHjpB+uJpxUcWDc= -github.com/muka/go-bluetooth v0.0.0-20240115085408-dfdf79b8f61d/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= -github.com/nats-io/nats.go v1.32.0 h1:Bx9BZS+aXYlxW08k8Gd3yR2s73pV5XSoAQUyp1Kwvp0= -github.com/nats-io/nats.go v1.32.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/muka/go-bluetooth v0.0.0-20240701044517-04c4f09c514e h1:1Sc4DqlgszKejMkjydCSq8zOKmF+hr8odAl5JoBZ+ec= +github.com/muka/go-bluetooth v0.0.0-20240701044517-04c4f09c514e/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= +github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE= +github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -53,7 +53,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY= github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -71,34 +70,34 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/suapapa/go_eddystone v1.3.1/go.mod h1:bXC11TfJOS+3g3q/Uzd7FKd5g62STQEfeEIhcKe4Qy8= github.com/tinygo-org/cbgo v0.0.4 h1:3D76CRYbH03Rudi8sEgs/YO0x3JIMdyq8jlQtk/44fU= github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk= github.com/warthog618/go-gpiosim v0.1.0 h1:2rTMTcKUVZxpUuvRKsagnKAbKpd3Bwffp87xywEDVGI= -github.com/warthog618/gpiod v0.8.2 h1:2HgQ9pNowPp7W77sXhX5ut5Tqq1WoS3t7bXYDxtYvxc= -github.com/warthog618/gpiod v0.8.2/go.mod h1:O7BNpHjCn/4YS5yFVmoFZAlY1LuYuQ8vhPf0iy/qdi4= +github.com/warthog618/gpiod v0.8.3 h1:hGFm/zf5PUyXU2LBG4fiZyRnbSSiPEajuOtQzQ3vkLo= +github.com/warthog618/gpiod v0.8.3/go.mod h1:YHsKSpTHebSDGnKNQKfQp9t/0JxQCyXyYtCF3F+78dc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.bug.st/serial v1.6.1 h1:VSSWmUxlj1T/YlRo2J104Zv3wJFrjHIl/T3NeruWAHY= -go.bug.st/serial v1.6.1/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= -gocv.io/x/gocv v0.35.0 h1:Qaxb5KdVyy8Spl4S4K0SMZ6CVmKtbfoSGQAxRD3FZlw= -gocv.io/x/gocv v0.35.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU= +go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8= +go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= +gocv.io/x/gocv v0.39.0 h1:vWHupDE22LebZW6id2mVeT767j1YS8WqGt+ZiV7XJXE= +gocv.io/x/gocv v0.39.0/go.mod h1:zYdWMj29WAEznM3Y8NsU3A0TRq/wR/cy75jeUypThqU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -106,8 +105,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= diff --git a/platforms/nats/nats_adaptor_test.go b/platforms/nats/nats_adaptor_test.go index a2c4bb0c5..76c4f302b 100644 --- a/platforms/nats/nats_adaptor_test.go +++ b/platforms/nats/nats_adaptor_test.go @@ -17,7 +17,7 @@ var _ gobot.Adaptor = (*Adaptor)(nil) func connStub(options ...nats.Option) func() (*nats.Conn, error) { return func() (*nats.Conn, error) { - opts := nats.DefaultOptions + opts := nats.GetDefaultOptions() for _, opt := range options { if err := opt(&opts); err != nil { return nil, err From a8f47eaae86461d5c98a4558935ae633ba1c00cc Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Fri, 1 Nov 2024 12:54:20 +0100 Subject: [PATCH 54/57] build(go, deps): switch to Go 1.22 and update modules (#1093) --- .circleci/config.yml | 8 ++-- .github/pull_request_template.md | 8 ++++ .github/workflows/golangci-lint.yml | 22 ++++------ .golangci.yml | 39 ++++++++--------- Makefile | 4 +- api/basic_auth.go | 1 + drivers/aio/temperature_sensor_driver.go | 2 +- drivers/ble/microbit/io_pin_driver.go | 12 ++++-- drivers/ble/parrot/minidrone_driver.go | 6 +++ drivers/ble/sphero/sphero_ollie_driver.go | 7 ++-- drivers/common/mfrc522/mfrc522_pcd.go | 4 +- drivers/common/mfrc522/mfrc522_pcd_test.go | 2 +- drivers/common/mfrc522/mfrc522_picc.go | 2 +- drivers/common/spherocommon/spherocommon.go | 2 +- drivers/gpio/hcsr04_driver_test.go | 3 +- drivers/gpio/stepper_driver.go | 1 + drivers/i2c/adafruit1109_driver.go | 2 +- drivers/i2c/adafruit2327_driver.go | 2 +- drivers/i2c/adafruit2348_driver.go | 4 +- drivers/i2c/ads1x15_driver.go | 10 ++--- drivers/i2c/adxl345_driver.go | 6 +-- drivers/i2c/bmp180_driver.go | 8 ++-- drivers/i2c/drv2605l_driver.go | 1 + drivers/i2c/helpers_test.go | 4 +- drivers/i2c/hmc5883l_driver.go | 13 ++++-- drivers/i2c/i2c_connection.go | 6 +-- drivers/i2c/i2c_driver.go | 4 +- drivers/i2c/ina3221_driver.go | 4 +- drivers/i2c/jhd1313m1_driver.go | 2 +- drivers/i2c/mcp23017_driver.go | 10 ++--- drivers/i2c/mcp23017_driver_test.go | 2 +- drivers/i2c/pca9501_driver.go | 6 +-- drivers/i2c/pca9685_driver.go | 2 +- drivers/i2c/pcf8583_driver.go | 21 ++++++---- drivers/i2c/pcf8591_driver.go | 4 +- drivers/i2c/ssd1306_driver.go | 2 +- drivers/i2c/tsl2561_driver.go | 4 +- drivers/serial/sphero/sphero_driver.go | 4 +- drivers/spi/ssd1306_driver.go | 5 ++- examples/beaglebone_servo.go | 1 + examples/bleclient_bb8.go | 1 + examples/bleclient_ollie.go | 1 + examples/bleclient_ollie_boost.go | 4 +- examples/bleclient_ollie_multiple.go | 1 + examples/bleclient_ollie_roll.go | 1 + examples/bleclient_sprkplus.go | 1 + examples/digispark_servo.go | 1 + examples/edison_rgb_led.go | 42 ------------------- examples/firmata_gpio_max7219.go | 8 ++-- examples/firmata_pca9685.go | 1 + examples/firmata_rgb_led.go | 1 + examples/firmata_servo.go | 1 + examples/gopigo3_servo.go | 1 + examples/jetson-nano_servo.go | 1 + examples/joule_rgb_led.go | 42 ------------------- examples/raspi_adafruit2327_servo.go | 1 + examples/raspi_stepper_move.go | 1 + examples/serialport_sphero.go | 1 + examples/serialport_sphero_conways.go | 1 + examples/serialport_sphero_master.go | 1 + examples/serialport_sphero_multiple.go | 1 + go.mod | 8 ++-- go.sum | 11 ++--- platforms/adaptors/pwmpinsadaptor.go | 10 +++-- platforms/adaptors/pwmpinsadaptor_test.go | 3 +- platforms/dexter/gopigo3/driver.go | 6 +-- platforms/digispark/README.md | 2 + platforms/digispark/digispark_adaptor.go | 6 +++ platforms/digispark/digispark_adaptor_test.go | 3 ++ platforms/digispark/digispark_i2c.go | 7 +++- platforms/digispark/digispark_i2c_test.go | 3 ++ platforms/digispark/doc.go | 3 ++ platforms/digispark/littleWire.go | 3 ++ platforms/dji/tello/driver.go | 9 +++- platforms/firmata/client/client.go | 13 +++--- platforms/firmata/firmata_adaptor.go | 6 +-- platforms/firmata/firmata_i2c.go | 4 +- platforms/firmata/firmata_i2c_test.go | 2 +- platforms/intel-iot/curie/imu_driver.go | 30 ++++++------- platforms/joystick/bin/scanner.go | 1 + platforms/joystick/joystick_driver.go | 3 ++ platforms/leap/leap_motion_adaptor_test.go | 2 +- platforms/mavlink/common/mavlink.go | 4 +- platforms/mavlink/mavlink_adaptor_test.go | 2 +- platforms/mavlink/mavlink_driver_test.go | 2 +- platforms/opencv/README.md | 2 + platforms/opencv/camera_driver.go | 7 +++- platforms/opencv/camera_driver_test.go | 3 ++ platforms/opencv/helpers_test.go | 3 ++ platforms/opencv/utils.go | 3 ++ platforms/opencv/utils_test.go | 3 ++ platforms/opencv/window_driver.go | 7 +++- platforms/opencv/window_driver_test.go | 3 ++ platforms/parrot/bebop/client/client.go | 9 ++++ .../bebop/client/networkframegenerator.go | 7 +--- platforms/particle/adaptor_test.go | 2 + system/digitalpin_gpiod.go | 6 ++- system/digitalpin_poll_test.go | 4 +- system/fs_mock_test.go | 4 +- system/i2c_device.go | 1 + system/i2c_device_test.go | 1 + system/pwmpin_sysfs.go | 4 +- utils.go | 30 ++++++------- 103 files changed, 323 insertions(+), 282 deletions(-) delete mode 100644 examples/edison_rgb_led.go delete mode 100644 examples/joule_rgb_led.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 168a145fb..c2e92deb0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ version: 2 jobs: "test_core_and_drivers_with_coverage": docker: - - image: cimg/go:1.20 + - image: cimg/go:1.22 steps: - checkout - run: @@ -31,7 +31,7 @@ jobs: "test_platforms": docker: - - image: cimg/go:1.20 + - image: cimg/go:1.22 steps: - checkout - run: @@ -45,7 +45,7 @@ jobs: "check_examples": docker: - - image: cimg/go:1.20 + - image: cimg/go:1.22 steps: - checkout - run: @@ -61,7 +61,7 @@ jobs: "fmt_check_examples": docker: - - image: golangci/golangci-lint:v1.56.1 + - image: golangci/golangci-lint:v1.61.0 steps: - checkout - run: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 8588899ad..a3141dcbd 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -22,6 +22,14 @@ If this is a new driver or adaptor: - [ ] I have added an example to see how to setup and use it - [ ] I have checked or build at least my new example (e.g. by run `make examples_check`) +If this is a Go version update: + +- [ ] go.mod to new version updated +- [ ] modules updated (go get -u -t ./...) +- [ ] CI files updated +- [ ] linter setting and linter version (if a newer one exist) updated +- [ ] linter issues fixed or suppressed by config + If this is a PR for release: - [ ] The PR's target branch is 'hybridgroup:release' diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index e1489e644..c3eff8162 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -15,24 +15,24 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: '1.22' cache: false - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.56.1 + version: v1.61.0 # Optional: working directory, useful for monorepos # working-directory: v2 # Optional: golangci-lint command line arguments. - # mostly there is no problem locally, but on server: "could not import C (cgo preprocessing failed) (typecheck)" - # and the digispark adaptor can not be build since switch to linter version 1.54.2 - args: --skip-files="platforms/digispark/littleWire.go,platforms/digispark/digispark_adaptor.go" + # Note: exclude arguments, e.g. --exclude-files="my_file", will not affect the "typecheck" linter, + # at least since v1.61.0 - use build tags instead. + #args: --exclude-files="platforms/digispark/digispark_adaptor.go" # Optional: show only new issues if it's a pull request. The default value is `false`. # only-new-issues: true @@ -40,9 +40,3 @@ jobs: # Optional: if set to true then the all caching functionality will be complete disabled, # takes precedence over all other caching options. # skip-cache: true - - # Optional: if set to true then the action don't cache or restore ~/go/pkg. - # skip-pkg-cache: true - - # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. - # skip-build-cache: true diff --git a/.golangci.yml b/.golangci.yml index f826bb4c0..17456d31a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -22,41 +22,36 @@ run: # By default, it isn't set. modules-download-mode: readonly +issues: # Enables skipping of directories: # - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ # Default: true - skip-dirs-use-default: false + exclude-dirs-use-default: false - # note: examples will be currently omitted by the build tag - skip-dirs: - - platforms/opencv + # note: folders/files can not be excluded from "typecheck" anymore since v1.61.0 linters: # currently active linters: # - # INFO [lintersdb] Active 64 linters: [asasalint asciicheck bidichk bodyclose containedctx contextcheck decorder depguard dogsled dupword durationcheck - # errcheck errchkjson errorlint exportloopref forcetypeassert gci gocheckcompilerdirectives gochecknoinits gochecksumtype gocritic gofmt gofumpt goimports - # gomoddirectives gomodguard goprintffuncname gosec gosimple govet grouper inamedparam ineffassign lll makezero mirror misspell musttag nakedret nilerr nilnil - # noctx nolintlint nonamedreturns nosprintfhostport perfsprint prealloc predeclared protogetter reassign revive sloglint staticcheck tagalign tenv - # testableexamples testifylint thelper tparallel unconvert unparam unused usestdlibvars wastedassign] + # INFO [lintersdb] Active 67 linters: [asasalint asciicheck bidichk bodyclose canonicalheader containedctx + # contextcheck decorder depguard dogsled dupword durationcheck errcheck errchkjson errorlint fatcontext + # forcetypeassert gci gocheckcompilerdirectives gochecknoinits gochecksumtype gocritic gofmt gofumpt goimports + # gomoddirectives gomodguard goprintffuncname gosec gosimple govet grouper inamedparam ineffassign lll makezero + # mirror misspell mnd musttag nakedret nilerr nilnil noctx nolintlint nonamedreturns nosprintfhostport perfsprint + # prealloc predeclared protogetter reassign revive sloglint spancheck staticcheck tagalign tenv testableexamples + # testifylint thelper tparallel unconvert unparam unused usestdlibvars wastedassign] enable-all: true # https://golangci-lint.run/usage/linters/#enabled-by-default # note: typecheck can not be disabled, it is used to check code compilation disable: - # deprecated - - deadcode # deprecated - - exhaustivestruct # deprecated - - golint # deprecated - - ifshort # deprecated - - interfacer # deprecated - - maligned # deprecated - - nosnakecase # deprecated - - scopelint # deprecated - - structcheck # deprecated - - varcheck # deprecated + # deprecated: + - exportloopref # Since Go1.22 (loopvar) this linter is no longer relevant. Replaced by copyloopvar + - gomnd # The linter has been renamed. Replaced by mnd. + # not used for this go version: none # not used for any reason + - err113 # not used (we allow error creation at return statement) - execinquery # not needed (no sql) - exhaustive # not used (we allow incomplete usage of enum switch, e.g. with default case) - forbidigo # not used (we allow print statements) @@ -64,7 +59,6 @@ linters: - gochecknoglobals # not used (we allow definition of unexposed variables at top level) - godot # not used (seems to be counting peas) - godox # not used (we have many TODOs, so not useful) - - goerr113 # not used (we allow error creation at return statement) - gosmopolitan # not needed (report i18n/l10n anti-patterns) - importas # not needed (there is no alias rule at the moment) - ireturn # not used (we allow return interfaces) @@ -86,9 +80,10 @@ linters: - goconst # useful (reduce bugs) - gocyclo # useful with some tweeks (better understandable code) - goheader # useful, if we introduce a common header (e.g. for copyright) - - gomnd # useful with some exclusions for existing code (e.g. mavlink.go) - interfacebloat # useful with some exclusions at usage of external packages + - intrange # introduced with go 1.22, will simplify the range syntax - maintidx # useful with some tweeks (better understandable code), maybe use instead "gocyclo", "gocognit" , "cyclop" + - mnd # useful with some exclusions for existing code (e.g. mavlink.go) - nestif # useful (reduce bugs, simplify code, better understandable code) - nlreturn # more common style, but could become annoying - stylecheck # useful with some tweaking (e.g. underscores in names should be allowed - we use it for constants retrieved from C/C++) diff --git a/Makefile b/Makefile index 46f532518..faf3056f5 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ including_except := $(shell go list ./... | grep -v platforms/opencv) # Run tests on nearly all directories without test cache, with race detection test_race: - go test -failfast -count=1 -race $(including_except) + go test -failfast -count=1 -race $(including_except) -tags libusb # Run tests on nearly all directories without test cache test: @@ -73,7 +73,7 @@ ifeq ($(CHECK),ON) go vet ./$@ else ifeq ($(CHECK),FMT) gofumpt -l -w ./$@ - golangci-lint run ./$@ --fix --build-tags example --disable forcetypeassert --disable noctx + golangci-lint run ./$@ --fix --build-tags example,libusb --disable forcetypeassert --disable noctx else go build -o /tmp/gobot_examples/$@ ./$@ endif diff --git a/api/basic_auth.go b/api/basic_auth.go index 260d2c357..0548dda39 100644 --- a/api/basic_auth.go +++ b/api/basic_auth.go @@ -22,6 +22,7 @@ func BasicAuth(username, password string) http.HandlerFunc { } func secureCompare(given string, actual string) bool { + //nolint:gosec // TODO: fix later if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 { return subtle.ConstantTimeCompare([]byte(given), []byte(actual)) == 1 } diff --git a/drivers/aio/temperature_sensor_driver.go b/drivers/aio/temperature_sensor_driver.go index f415caa1d..fb2c78e83 100644 --- a/drivers/aio/temperature_sensor_driver.go +++ b/drivers/aio/temperature_sensor_driver.go @@ -86,7 +86,7 @@ func TemperatureSensorNtcScaler( if input < 0 { input = 0 } - rTherm := temperaturSensorGetResistance(uint(input), vRef, rOhm, reverse) + rTherm := temperaturSensorGetResistance(uint(input), vRef, rOhm, reverse) //nolint:gosec // checked before temp := ntc.getTemp(rTherm) return temp }) diff --git a/drivers/ble/microbit/io_pin_driver.go b/drivers/ble/microbit/io_pin_driver.go index d45b2d6c2..bcf76bd76 100644 --- a/drivers/ble/microbit/io_pin_driver.go +++ b/drivers/ble/microbit/io_pin_driver.go @@ -72,7 +72,7 @@ func (d *IOPinDriver) ReadPinADConfig() (int, error) { } var result byte for i := 0; i < 4; i++ { - result |= c[i] << uint(i) + result |= c[i] << uint(i) //nolint:gosec // ok here } d.adMask = int(result) @@ -83,6 +83,7 @@ func (d *IOPinDriver) ReadPinADConfig() (int, error) { func (d *IOPinDriver) WritePinADConfig(config int) error { d.adMask = config data := &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(data, binary.LittleEndian, uint32(config)); err != nil { return err } @@ -99,7 +100,7 @@ func (d *IOPinDriver) ReadPinIOConfig() (int, error) { var result byte for i := 0; i < 4; i++ { - result |= c[i] << uint(i) + result |= c[i] << uint(i) //nolint:gosec // ok here } d.ioMask = int(result) @@ -110,6 +111,7 @@ func (d *IOPinDriver) ReadPinIOConfig() (int, error) { func (d *IOPinDriver) WritePinIOConfig(config int) error { d.ioMask = config data := &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(data, binary.LittleEndian, uint32(config)); err != nil { return err } @@ -179,6 +181,7 @@ func (d *IOPinDriver) AnalogRead(pin string) (int, error) { } func (d *IOPinDriver) ensureDigital(pin int) error { + //nolint:gosec // TODO: fix later if bit.IsSet(d.adMask, uint8(pin)) { return d.WritePinADConfig(bit.Clear(d.adMask, uint8(pin))) } @@ -187,6 +190,7 @@ func (d *IOPinDriver) ensureDigital(pin int) error { } func (d *IOPinDriver) ensureAnalog(pin int) error { + //nolint:gosec // TODO: fix later if !bit.IsSet(d.adMask, uint8(pin)) { return d.WritePinADConfig(bit.Set(d.adMask, uint8(pin))) } @@ -195,6 +199,7 @@ func (d *IOPinDriver) ensureAnalog(pin int) error { } func (d *IOPinDriver) ensureInput(pin int) error { + //nolint:gosec // TODO: fix later if !bit.IsSet(d.ioMask, uint8(pin)) { return d.WritePinIOConfig(bit.Set(d.ioMask, uint8(pin))) } @@ -203,8 +208,9 @@ func (d *IOPinDriver) ensureInput(pin int) error { } func (d *IOPinDriver) ensureOutput(pin int) error { + //nolint:gosec // TODO: fix later if bit.IsSet(d.ioMask, uint8(pin)) { - return d.WritePinIOConfig(bit.Clear(d.ioMask, uint8(pin))) + return d.WritePinIOConfig(bit.Clear(d.ioMask, uint8(pin))) //nolint:gosec // TODO: fix later } return nil diff --git a/drivers/ble/parrot/minidrone_driver.go b/drivers/ble/parrot/minidrone_driver.go index e42f1f370..4dee03ef5 100644 --- a/drivers/ble/parrot/minidrone_driver.go +++ b/drivers/ble/parrot/minidrone_driver.go @@ -394,6 +394,7 @@ func (d *MinidroneDriver) generatePcmd() *bytes.Buffer { if err := binary.Write(cmd, binary.LittleEndian, int8(2)); err != nil { panic(err) } + //nolint:gosec // TODO: fix later if err := binary.Write(cmd, binary.LittleEndian, int8(d.stepsfa0a)); err != nil { panic(err) } @@ -409,18 +410,23 @@ func (d *MinidroneDriver) generatePcmd() *bytes.Buffer { if err := binary.Write(cmd, binary.LittleEndian, int8(0)); err != nil { panic(err) } + //nolint:gosec // TODO: fix later if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Flag)); err != nil { panic(err) } + //nolint:gosec // TODO: fix later if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Roll)); err != nil { panic(err) } + //nolint:gosec // TODO: fix later if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Pitch)); err != nil { panic(err) } + //nolint:gosec // TODO: fix later if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Yaw)); err != nil { panic(err) } + //nolint:gosec // TODO: fix later if err := binary.Write(cmd, binary.LittleEndian, int8(pcmd.Gaz)); err != nil { panic(err) } diff --git a/drivers/ble/sphero/sphero_ollie_driver.go b/drivers/ble/sphero/sphero_ollie_driver.go index cd521e597..a2dfcb54d 100644 --- a/drivers/ble/sphero/sphero_ollie_driver.go +++ b/drivers/ble/sphero/sphero_ollie_driver.go @@ -143,6 +143,7 @@ func (d *OllieDriver) SetRGB(r uint8, g uint8, b uint8) { // Roll tells the Ollie to roll func (d *OllieDriver) Roll(speed uint8, heading uint16) { + //nolint:gosec // TODO: fix later d.sendCraftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x02, 0x30) } @@ -353,13 +354,13 @@ func (d *OllieDriver) handleLocatorDetected(data []uint8) { var x, y int16 if ux > 32255 { - x = int16(ux - 65535) + x = int16(ux - 65535) //nolint:gosec // ok here } else { x = int16(ux) } if uy > 32255 { - y = int16(uy - 65535) + y = int16(uy - 65535) //nolint:gosec // ok here } else { y = int16(uy) } @@ -424,7 +425,7 @@ func (d *OllieDriver) sendCraftPacket(body []uint8, did byte, cid byte) { func (d *OllieDriver) craftPacket(body []uint8, did byte, cid byte) *packet { dlen := len(body) + 1 - hdr := []uint8{0xFF, 0xFF, did, cid, d.seq, uint8(dlen)} + hdr := []uint8{0xFF, 0xFF, did, cid, d.seq, uint8(dlen)} //nolint:gosec // TODO: fix later buf := append(hdr, body...) packet := &packet{ diff --git a/drivers/common/mfrc522/mfrc522_pcd.go b/drivers/common/mfrc522/mfrc522_pcd.go index a6cad3495..a24e53cb0 100644 --- a/drivers/common/mfrc522/mfrc522_pcd.go +++ b/drivers/common/mfrc522/mfrc522_pcd.go @@ -172,6 +172,7 @@ func (d *MFRC522Common) communicateWithPICC(command uint8, sendData []byte, back } // TODO: this is not used at the moment (propagation of IRQ pin) + //nolint:gosec // TODO: fix later if err := d.writeByteData(regComIEn, uint8(irqEn|comIEnRegIRqInv)); err != nil { return err } @@ -337,10 +338,11 @@ func (d *MFRC522Common) readFifo(backData []byte) (uint8, error) { if err != nil { return 0, err } + //nolint:gosec // TODO: fix later if n > uint8(len(backData)) { return 0, fmt.Errorf("more data in FIFO (%d) than expected (%d)", n, len(backData)) } - + //nolint:gosec // TODO: fix later if n < uint8(len(backData)) { return 0, fmt.Errorf("less data in FIFO (%d) than expected (%d)", n, len(backData)) } diff --git a/drivers/common/mfrc522/mfrc522_pcd_test.go b/drivers/common/mfrc522/mfrc522_pcd_test.go index 19c14bf16..3edc0fff4 100644 --- a/drivers/common/mfrc522/mfrc522_pcd_test.go +++ b/drivers/common/mfrc522/mfrc522_pcd_test.go @@ -20,7 +20,7 @@ func (c *busConnMock) ReadByteData(reg uint8) (uint8, error) { switch reg { case regFIFOLevel: - return uint8(len(c.simFifo)), nil + return uint8(len(c.simFifo)), nil //nolint:gosec // ok for test case regFIFOData: c.fifoIdx++ return c.simFifo[c.fifoIdx-1], nil diff --git a/drivers/common/mfrc522/mfrc522_picc.go b/drivers/common/mfrc522/mfrc522_picc.go index 1776daa25..dd228021a 100644 --- a/drivers/common/mfrc522/mfrc522_picc.go +++ b/drivers/common/mfrc522/mfrc522_picc.go @@ -336,7 +336,7 @@ func (d *MFRC522Common) piccActivate() ([]byte, error) { bcc = bcc ^ v } if bcc != backData[4] { - return nil, fmt.Errorf(fmt.Sprintf("BCC mismatch, expected %02x actual %02x", bcc, backData[4])) + return nil, fmt.Errorf("BCC mismatch, expected %02x actual %02x", bcc, backData[4]) } if backData[0] == piccCascadeTag { diff --git a/drivers/common/spherocommon/spherocommon.go b/drivers/common/spherocommon/spherocommon.go index 978ac7dcd..843166825 100644 --- a/drivers/common/spherocommon/spherocommon.go +++ b/drivers/common/spherocommon/spherocommon.go @@ -29,5 +29,5 @@ func CalculateChecksum(buf []byte) byte { for i := range buf { calculatedChecksum += uint16(buf[i]) } - return uint8(^(calculatedChecksum % 256)) + return uint8(^(calculatedChecksum % 256)) //nolint:gosec // TODO: fix later } diff --git a/drivers/gpio/hcsr04_driver_test.go b/drivers/gpio/hcsr04_driver_test.go index 4c32cae5e..554bae5c2 100644 --- a/drivers/gpio/hcsr04_driver_test.go +++ b/drivers/gpio/hcsr04_driver_test.go @@ -1,6 +1,7 @@ package gpio import ( + "errors" "fmt" "strings" "sync" @@ -132,7 +133,7 @@ func TestHCSR04MeasureDistance(t *testing.T) { oldVal = val var err error if tc.simulateWriteErr != "" { - err = fmt.Errorf(tc.simulateWriteErr) + err = errors.New(tc.simulateWriteErr) } return err } diff --git a/drivers/gpio/stepper_driver.go b/drivers/gpio/stepper_driver.go index b33b845fd..5f6d4cd47 100644 --- a/drivers/gpio/stepper_driver.go +++ b/drivers/gpio/stepper_driver.go @@ -308,6 +308,7 @@ func (d *StepperDriver) stepAsynch(stepsToMove float64) error { // t [min] = steps [st] / (steps_per_revolution [st/u] * speed [u/min]) or // t [min] = steps [st] * delay_per_step [min/st], use safety factor 2 and a small offset of 100 ms // prepare this timeout outside of stop function to prevent data race with stepsLeft + //nolint:gosec // TODO: fix later stopTimeout := time.Duration(2*stepsLeft)*d.getDelayPerStep() + 100*time.Millisecond endlessMovement := false diff --git a/drivers/i2c/adafruit1109_driver.go b/drivers/i2c/adafruit1109_driver.go index 92781fea4..2c3433404 100644 --- a/drivers/i2c/adafruit1109_driver.go +++ b/drivers/i2c/adafruit1109_driver.go @@ -281,7 +281,7 @@ func adafruit1109ParseID(id string) adafruit1109PortPin { items := strings.Split(id, "_") io := uint8(0) if io64, err := strconv.ParseUint(items[1], 10, 32); err == nil { - io = uint8(io64) + io = uint8(io64) //nolint:gosec // TODO: fix later } return adafruit1109PortPin{port: items[0], pin: io} } diff --git a/drivers/i2c/adafruit2327_driver.go b/drivers/i2c/adafruit2327_driver.go index c26ff5d87..6b42b8c78 100644 --- a/drivers/i2c/adafruit2327_driver.go +++ b/drivers/i2c/adafruit2327_driver.go @@ -41,5 +41,5 @@ func (a *Adafruit2327Driver) SetServoMotorFreq(freq float64) error { // SetServoMotorPulse is a convenience function to specify the 'tick' value, // between 0-4095, when the signal will turn on, and when it will turn off. func (a *Adafruit2327Driver) SetServoMotorPulse(channel byte, on, off int32) error { - return a.SetPWM(int(channel), uint16(on), uint16(off)) + return a.SetPWM(int(channel), uint16(on), uint16(off)) //nolint:gosec // TODO: fix later } diff --git a/drivers/i2c/adafruit2348_driver.go b/drivers/i2c/adafruit2348_driver.go index 2fdf86a47..f18c2ee3f 100644 --- a/drivers/i2c/adafruit2348_driver.go +++ b/drivers/i2c/adafruit2348_driver.go @@ -125,7 +125,7 @@ func NewAdafruit2348Driver(c Connector, options ...func(Config)) *Adafruit2348Dr // SetDCMotorSpeed will set the appropriate pins to run the specified DC motor for the given speed. func (a *Adafruit2348Driver) SetDCMotorSpeed(dcMotor int, speed int32) error { - return a.SetPWM(int(a.dcMotors[dcMotor].pwmPin), 0, uint16(speed*16)) + return a.SetPWM(int(a.dcMotors[dcMotor].pwmPin), 0, uint16(speed*16)) //nolint:gosec // TODO: fix later } // RunDCMotor will set the appropriate pins to run the specified DC motor for the given direction. @@ -281,9 +281,11 @@ func (a *Adafruit2348Driver) oneStep(motor int, dir Adafruit2348Direction, style a.stepperMotors[motor].currentStep %= adafruit2348StepperMicrosteps * 4 // only really used for microstepping, otherwise always on! + //nolint:gosec // TODO: fix later if err := a.SetPWM(int(a.stepperMotors[motor].pwmPinA), 0, uint16(pwmA*16)); err != nil { return 0, err } + //nolint:gosec // TODO: fix later if err := a.SetPWM(int(a.stepperMotors[motor].pwmPinB), 0, uint16(pwmB*16)); err != nil { return 0, err } diff --git a/drivers/i2c/ads1x15_driver.go b/drivers/i2c/ads1x15_driver.go index 1e3fbb30a..6f8690e3d 100644 --- a/drivers/i2c/ads1x15_driver.go +++ b/drivers/i2c/ads1x15_driver.go @@ -394,10 +394,10 @@ func (d *ADS1x15Driver) rawRead(channel int, channelOffset int, gain int, dataRa // Specify mux value. mux := channel + channelOffset - config |= uint16((mux & 0x07) << ads1x15ConfigMuxOffset) + config |= uint16((mux & 0x07) << ads1x15ConfigMuxOffset) //nolint:gosec // TODO: fix later // Set the programmable gain amplifier bits. - config |= uint16(gain) << ads1x15ConfigPgaOffset + config |= uint16(gain) << ads1x15ConfigPgaOffset //nolint:gosec // TODO: fix later // Set the mode (continuous or single shot). config |= ads1x15ConfigModeSingle @@ -525,12 +525,12 @@ func ads1x15GetDataRateBits(dataRates map[int]uint16, dataRate int) (uint16, err // ads1x15BestGainForVoltage returns the gain the most adapted to read up to the specified difference of potential. func ads1x15BestGainForVoltage(voltage float64) (int, error) { - var max float64 + var maximum float64 difference := math.MaxFloat64 currentBestGain := -1 for key, fsr := range ads1x15FullScaleRange { - max = math.Max(max, fsr) + maximum = math.Max(maximum, fsr) newDiff := fsr - voltage if newDiff >= 0 && newDiff < difference { difference = newDiff @@ -539,7 +539,7 @@ func ads1x15BestGainForVoltage(voltage float64) (int, error) { } if currentBestGain < 0 { - return 0, fmt.Errorf("The maximum voltage which can be read is %f", max) + return 0, fmt.Errorf("The maximum voltage which can be read is %f", maximum) } return currentBestGain, nil diff --git a/drivers/i2c/adxl345_driver.go b/drivers/i2c/adxl345_driver.go index 42d577d36..04c205f13 100644 --- a/drivers/i2c/adxl345_driver.go +++ b/drivers/i2c/adxl345_driver.go @@ -239,9 +239,9 @@ func (d *ADXL345Driver) readRawData() (int16, int16, int16, error) { return 0, 0, 0, err } - rx := int16(binary.LittleEndian.Uint16(buf[0:2])) - ry := int16(binary.LittleEndian.Uint16(buf[2:4])) - rz := int16(binary.LittleEndian.Uint16(buf[4:6])) + rx := int16(binary.LittleEndian.Uint16(buf[0:2])) //nolint:gosec // TODO: fix later + ry := int16(binary.LittleEndian.Uint16(buf[2:4])) //nolint:gosec // TODO: fix later + rz := int16(binary.LittleEndian.Uint16(buf[4:6])) //nolint:gosec // TODO: fix later return rx, ry, rz, nil } diff --git a/drivers/i2c/bmp180_driver.go b/drivers/i2c/bmp180_driver.go index 176945605..62abcfe9d 100644 --- a/drivers/i2c/bmp180_driver.go +++ b/drivers/i2c/bmp180_driver.go @@ -219,13 +219,13 @@ func (d *BMP180Driver) calculatePressure( x1 = (int32(d.calCoeffs.ac3) * b6) >> 13 x2 = (int32(d.calCoeffs.b1) * ((b6 * b6) >> 12)) >> 16 x3 = ((x1 + x2) + 2) >> 2 - b4 := (uint32(d.calCoeffs.ac4) * uint32(x3+32768)) >> 15 - b7 := (uint32(rawPressure-b3) * (50000 >> uint(oversampling))) + b4 := (uint32(d.calCoeffs.ac4) * uint32(x3+32768)) >> 15 //nolint:gosec // TODO: fix later + b7 := (uint32(rawPressure-b3) * (50000 >> uint(oversampling))) //nolint:gosec // TODO: fix later var p int32 if b7 < 0x80000000 { - p = int32((b7 << 1) / b4) + p = int32((b7 << 1) / b4) //nolint:gosec // TODO: fix later } else { - p = int32((b7 / b4) << 1) + p = int32((b7 / b4) << 1) //nolint:gosec // TODO: fix later } x1 = (p >> 8) * (p >> 8) x1 = (x1 * 3038) >> 16 diff --git a/drivers/i2c/drv2605l_driver.go b/drivers/i2c/drv2605l_driver.go index a29995bc6..b845cb032 100644 --- a/drivers/i2c/drv2605l_driver.go +++ b/drivers/i2c/drv2605l_driver.go @@ -163,6 +163,7 @@ func (d *DRV2605LDriver) SetSequence(waveforms []uint8) error { waveforms = waveforms[0:8] } for i, w := range waveforms { + //nolint:gosec // TODO: fix later if err := d.connection.WriteByteData(uint8(drv2605RegWaveSeq1+i), w); err != nil { return err } diff --git a/drivers/i2c/helpers_test.go b/drivers/i2c/helpers_test.go index 0a043d744..87bc55e1b 100644 --- a/drivers/i2c/helpers_test.go +++ b/drivers/i2c/helpers_test.go @@ -127,8 +127,8 @@ func (t *i2cTestAdaptor) WriteByteData(reg uint8, val uint8) error { func (t *i2cTestAdaptor) WriteWordData(reg uint8, val uint16) error { t.mtx.Lock() defer t.mtx.Unlock() - low := uint8(val & 0xff) - high := uint8((val >> 8) & 0xff) + low := uint8(val & 0xff) //nolint:gosec // ok here + high := uint8((val >> 8) & 0xff) //nolint:gosec // ok here bytes := []byte{reg, low, high} return t.writeBytes(bytes) diff --git a/drivers/i2c/hmc5883l_driver.go b/drivers/i2c/hmc5883l_driver.go index c43f212ca..83bc5db29 100644 --- a/drivers/i2c/hmc5883l_driver.go +++ b/drivers/i2c/hmc5883l_driver.go @@ -147,7 +147,7 @@ func WithHMC5883LSamplesAveraged(val int) func(Config) { if err := hmc5883lValidateSamplesAveraged(val); err != nil { panic(err) } - d.samplesAvg = uint8(val) + d.samplesAvg = uint8(val) //nolint:gosec // TODO: fix later } else if hmc5883lDebug { log.Printf("Trying to set samples averaged for non-HMC5883LDriver %v", c) } @@ -163,7 +163,7 @@ func WithHMC5883LDataOutputRate(val int) func(Config) { if err := hmc5883lValidateOutputRate(val); err != nil { panic(err) } - d.outputRate = uint32(val) + d.outputRate = uint32(val) //nolint:gosec // TODO: fix later } else if hmc5883lDebug { log.Printf("Trying to set data output rate for non-HMC5883LDriver %v", c) } @@ -179,7 +179,7 @@ func WithHMC5883LApplyBias(val int) func(Config) { if err := hmc5883lValidateApplyBias(val); err != nil { panic(err) } - d.applyBias = int8(val) + d.applyBias = int8(val) //nolint:gosec // TODO: fix later } else if hmc5883lDebug { log.Printf("Trying to set measurement flow for non-HMC5883LDriver %v", c) } @@ -256,18 +256,21 @@ func (h *HMC5883LDriver) initialize() error { regA := hmc5883lMeasurementFlowBits[h.applyBias] regA |= hmc5883lOutputRateBits[h.outputRate] << 2 regA |= hmc5883lSamplesAvgBits[h.samplesAvg] << 5 + //nolint:gosec // TODO: fix later if err := h.connection.WriteByteData(hmc5883lRegA, uint8(regA)); err != nil { return err } regB := hmc5883lGainBits[h.gain] << 5 + //nolint:gosec // TODO: fix later if err := h.connection.WriteByteData(hmc5883lRegB, uint8(regB)); err != nil { return err } - + //nolint:gosec // TODO: fix later return h.connection.WriteByteData(hmc5883lRegMode, uint8(h.measurementMode)) } func hmc5883lValidateSamplesAveraged(samplesAvg int) error { + //nolint:gosec // TODO: fix later if _, ok := hmc5883lSamplesAvgBits[uint8(samplesAvg)]; ok { return nil } @@ -282,6 +285,7 @@ func hmc5883lValidateSamplesAveraged(samplesAvg int) error { } func hmc5883lValidateOutputRate(outputRate int) error { + //nolint:gosec // TODO: fix later if _, ok := hmc5883lOutputRateBits[uint32(outputRate)]; ok { return nil } @@ -296,6 +300,7 @@ func hmc5883lValidateOutputRate(outputRate int) error { } func hmc5883lValidateApplyBias(applyBias int) error { + //nolint:gosec // TODO: fix later if _, ok := hmc5883lMeasurementFlowBits[int8(applyBias)]; ok { return nil } diff --git a/drivers/i2c/i2c_connection.go b/drivers/i2c/i2c_connection.go index e1c08a36d..0916bc4ca 100644 --- a/drivers/i2c/i2c_connection.go +++ b/drivers/i2c/i2c_connection.go @@ -29,8 +29,8 @@ var ( type bitState uint8 const ( - clear bitState = 0x00 - set bitState = 0x01 + clearBit bitState = 0x00 + setBit bitState = 0x01 ) // Connection is a connection to an I2C device with a specified address @@ -115,7 +115,7 @@ func twosComplement16Bit(uValue uint16) int16 { if result&0x8000 != 0 { result -= 1 << 16 } - return int16(result) + return int16(result) //nolint:gosec // ok here } func swapBytes(value uint16) uint16 { diff --git a/drivers/i2c/i2c_driver.go b/drivers/i2c/i2c_driver.go index 296b1c0c7..23409c0c1 100644 --- a/drivers/i2c/i2c_driver.go +++ b/drivers/i2c/i2c_driver.go @@ -131,13 +131,13 @@ func (d *Driver) Write(pin string, val int) error { if val > 0xFFFF { buf := make([]byte, 4) - binary.LittleEndian.PutUint32(buf, uint32(val)) + binary.LittleEndian.PutUint32(buf, uint32(val)) //nolint:gosec // ok here return d.connection.WriteBlockData(register, buf) } if val > 0xFF { return d.connection.WriteWordData(register, uint16(val)) } - return d.connection.WriteByteData(register, uint8(val)) + return d.connection.WriteByteData(register, uint8(val)) //nolint:gosec // ok here } // Read implements a simple read mechanism from the given register of an i2c device. diff --git a/drivers/i2c/ina3221_driver.go b/drivers/i2c/ina3221_driver.go index 6ff5ab7a2..743314d91 100644 --- a/drivers/i2c/ina3221_driver.go +++ b/drivers/i2c/ina3221_driver.go @@ -124,7 +124,7 @@ func (i *INA3221Driver) getBusVoltageRaw(channel INA3221Channel) (int16, error) value -= 0x10000 } - return int16(value), nil + return int16(value), nil //nolint:gosec // TODO: fix later } // getShuntVoltageRaw gets the raw shunt voltage (16-bit signed integer, so +-32767) @@ -139,7 +139,7 @@ func (i *INA3221Driver) getShuntVoltageRaw(channel INA3221Channel) (int16, error value -= 0x10000 } - return int16(value), nil + return int16(value), nil //nolint:gosec // TODO: fix later } // reads word from supplied register address diff --git a/drivers/i2c/jhd1313m1_driver.go b/drivers/i2c/jhd1313m1_driver.go index 9d17818ec..0a524420a 100644 --- a/drivers/i2c/jhd1313m1_driver.go +++ b/drivers/i2c/jhd1313m1_driver.go @@ -303,7 +303,7 @@ func (d *JHD1313M1Driver) SetCustomChar(pos int, charMap [8]byte) error { if pos > 7 { return fmt.Errorf("can't set a custom character at a position greater than 7") } - location := uint8(pos) + location := uint8(pos) //nolint:gosec // checked before if err := d.command([]byte{LCD_SETCGRAMADDR | (location << 3)}); err != nil { return err } diff --git a/drivers/i2c/mcp23017_driver.go b/drivers/i2c/mcp23017_driver.go index def7fe527..80def1220 100644 --- a/drivers/i2c/mcp23017_driver.go +++ b/drivers/i2c/mcp23017_driver.go @@ -273,7 +273,7 @@ func (m *MCP23017Driver) WriteGPIO(pin uint8, portStr string, val uint8) error { if !m.mcpBehav.autoIODirOff { // Set IODIR register bit for given pin to an output by clearing bit. // can't call SetPinMode() because mutex will cause deadlock - if err := m.write(selectedPort.IODIR, pin, clear); err != nil { + if err := m.write(selectedPort.IODIR, pin, clearBit); err != nil { return err } } @@ -290,7 +290,7 @@ func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (uint8, error) { if !m.mcpBehav.autoIODirOff { // Set IODIR register bit for given pin to an input by set bit. // can't call SetPinMode() because mutex will cause deadlock - if err := m.write(selectedPort.IODIR, pin, set); err != nil { + if err := m.write(selectedPort.IODIR, pin, setBit); err != nil { return 0, err } } @@ -323,10 +323,10 @@ func (m *MCP23017Driver) write(reg uint8, pin uint8, state bitState) error { } var val uint8 - if state == clear { - val = uint8(bit.Clear(int(valOrg), pin)) + if state == clearBit { + val = uint8(bit.Clear(int(valOrg), pin)) //nolint:gosec // TODO: fix later } else { - val = uint8(bit.Set(int(valOrg), pin)) + val = uint8(bit.Set(int(valOrg), pin)) //nolint:gosec // TODO: fix later } if val != valOrg || m.mcpBehav.forceRefresh { diff --git a/drivers/i2c/mcp23017_driver_test.go b/drivers/i2c/mcp23017_driver_test.go index 0228d982b..e5a5ec9c7 100644 --- a/drivers/i2c/mcp23017_driver_test.go +++ b/drivers/i2c/mcp23017_driver_test.go @@ -1,4 +1,4 @@ -//nolint:forcetypeassert // ok here +//nolint:forcetypeassert,gosec // ok here package i2c import ( diff --git a/drivers/i2c/pca9501_driver.go b/drivers/i2c/pca9501_driver.go index a71934ca7..b68730b2e 100644 --- a/drivers/i2c/pca9501_driver.go +++ b/drivers/i2c/pca9501_driver.go @@ -84,7 +84,7 @@ func (p *PCA9501Driver) WriteGPIO(pin uint8, val uint8) error { // set pin as output by clearing bit iodirVal := bit.Clear(int(iodir), pin) // write CTRL register - err = p.connection.WriteByte(uint8(iodirVal)) + err = p.connection.WriteByte(uint8(iodirVal)) //nolint:gosec // TODO: fix later if err != nil { return err } @@ -101,7 +101,7 @@ func (p *PCA9501Driver) WriteGPIO(pin uint8, val uint8) error { nVal = bit.Set(int(cVal), pin) } // write new value to port - err = p.connection.WriteByte(uint8(nVal)) + err = p.connection.WriteByte(uint8(nVal)) //nolint:gosec // TODO: fix later if err != nil { return err } @@ -121,7 +121,7 @@ func (p *PCA9501Driver) ReadGPIO(pin uint8) (uint8, error) { // set pin as input by setting bit iodirVal := bit.Set(int(iodir), pin) // write CTRL register - err = p.connection.WriteByte(uint8(iodirVal)) + err = p.connection.WriteByte(uint8(iodirVal)) //nolint:gosec // TODO: fix later if err != nil { return 0, err } diff --git a/drivers/i2c/pca9685_driver.go b/drivers/i2c/pca9685_driver.go index 24b6a7fdd..bd9e040b4 100644 --- a/drivers/i2c/pca9685_driver.go +++ b/drivers/i2c/pca9685_driver.go @@ -77,7 +77,7 @@ func NewPCA9685Driver(c Connector, options ...func(Config)) *PCA9685Driver { channel, _ := strconv.Atoi(params["channel"].(string)) on, _ := strconv.Atoi(params["on"].(string)) off, _ := strconv.Atoi(params["off"].(string)) - return p.SetPWM(channel, uint16(on), uint16(off)) + return p.SetPWM(channel, uint16(on), uint16(off)) //nolint:gosec // TODO: fix later }) p.AddCommand("SetPWMFreq", func(params map[string]interface{}) interface{} { freq, _ := strconv.ParseFloat(params["freq"].(string), 32) diff --git a/drivers/i2c/pcf8583_driver.go b/drivers/i2c/pcf8583_driver.go index 70883b72a..34d605f5e 100644 --- a/drivers/i2c/pcf8583_driver.go +++ b/drivers/i2c/pcf8583_driver.go @@ -152,14 +152,14 @@ func (d *PCF8583Driver) WriteTime(val time.Time) error { []byte{ ctrlRegVal | uint8(pcf8583CtrlStopCounting), // sub seconds in 1/10th seconds - pcf8583encodeBcd(uint8(val.Nanosecond() / 1000000 / 10)), - pcf8583encodeBcd(uint8(val.Second())), - pcf8583encodeBcd(uint8(val.Minute())), - pcf8583encodeBcd(uint8(val.Hour())), + pcf8583encodeBcd(uint8(val.Nanosecond() / 1000000 / 10)), //nolint:gosec // TODO: fix later + pcf8583encodeBcd(uint8(val.Second())), //nolint:gosec // TODO: fix later + pcf8583encodeBcd(uint8(val.Minute())), //nolint:gosec // TODO: fix later + pcf8583encodeBcd(uint8(val.Hour())), //nolint:gosec // TODO: fix later // year, date (we keep the year counter zero and set the offset) - pcf8583encodeBcd(uint8(day)), + pcf8583encodeBcd(uint8(day)), //nolint:gosec // TODO: fix later // month, weekday (not BCD): Sunday = 0, Monday = 1 ... - uint8(val.Weekday())<<5 | pcf8583encodeBcd(uint8(month)), + uint8(val.Weekday())<<5 | pcf8583encodeBcd(uint8(month)), //nolint:gosec // TODO: fix later }) if err != nil { return err @@ -221,9 +221,12 @@ func (d *PCF8583Driver) WriteCounter(val int32) error { } err = d.connection.WriteBlockData(uint8(pcf8583Reg_CTRL), []byte{ - ctrlRegVal | uint8(pcf8583CtrlStopCounting), // stop - pcf8583encodeBcd(uint8(val % 100)), // 2 lowest digits - pcf8583encodeBcd(uint8((val / 100) % 100)), // 2 middle digits + ctrlRegVal | uint8(pcf8583CtrlStopCounting), // stop + //nolint:gosec // TODO: fix later + pcf8583encodeBcd(uint8(val % 100)), // 2 lowest digits + //nolint:gosec // TODO: fix later + pcf8583encodeBcd(uint8((val / 100) % 100)), // 2 middle digits + //nolint:gosec // TODO: fix later pcf8583encodeBcd(uint8((val / 10000) % 100)), // 2 highest digits }) if err != nil { diff --git a/drivers/i2c/pcf8591_driver.go b/drivers/i2c/pcf8591_driver.go index 8946cc03b..f5d2b9469 100644 --- a/drivers/i2c/pcf8591_driver.go +++ b/drivers/i2c/pcf8591_driver.go @@ -143,8 +143,8 @@ func WithPCF8591With400kbitStabilization(additionalReadWrite, additionalRead int if additionalRead < 0 { additionalRead = 2 // works in most cases } - p.additionalReadWrite = uint8(additionalReadWrite) - p.additionalRead = uint8(additionalRead) + p.additionalReadWrite = uint8(additionalReadWrite) //nolint:gosec // checked before + p.additionalRead = uint8(additionalRead) //nolint:gosec // checked before if pcf8591Debug { log.Printf("400 kbit stabilization for PCF8591Driver set rw: %d, r: %d", p.additionalReadWrite, p.additionalRead) } diff --git a/drivers/i2c/ssd1306_driver.go b/drivers/i2c/ssd1306_driver.go index f7a674d05..4153a0b3c 100644 --- a/drivers/i2c/ssd1306_driver.go +++ b/drivers/i2c/ssd1306_driver.go @@ -163,7 +163,7 @@ func (d *DisplayBuffer) Clear() { // SetPixel sets the x, y pixel with c color. func (d *DisplayBuffer) SetPixel(x, y, c int) { idx := x + (y/d.pageSize)*d.width - bit := uint(y) % uint(d.pageSize) + bit := uint(y) % uint(d.pageSize) //nolint:gosec // TODO: fix later if c == 0 { d.buffer[idx] &= ^(1 << bit) } else { diff --git a/drivers/i2c/tsl2561_driver.go b/drivers/i2c/tsl2561_driver.go index 44e94ac58..a3c5a9b0a 100644 --- a/drivers/i2c/tsl2561_driver.go +++ b/drivers/i2c/tsl2561_driver.go @@ -215,7 +215,7 @@ func (d *TSL2561Driver) SetIntegrationTime(time TSL2561IntegrationTime) error { return err } - timeGainVal := uint8(time) | uint8(d.gain) + timeGainVal := uint8(time) | uint8(d.gain) //nolint:gosec // TODO: fix later if err := d.connection.WriteByteData(tsl2561CommandBit|tsl2561RegisterTiming, timeGainVal); err != nil { return err } @@ -230,7 +230,7 @@ func (d *TSL2561Driver) SetGain(gain TSL2561Gain) error { return err } - timeGainVal := uint8(d.integrationTime) | uint8(gain) + timeGainVal := uint8(d.integrationTime) | uint8(gain) //nolint:gosec // TODO: fix later if err := d.connection.WriteByteData(tsl2561CommandBit|tsl2561RegisterTiming, timeGainVal); err != nil { return err } diff --git a/drivers/serial/sphero/sphero_driver.go b/drivers/serial/sphero/sphero_driver.go index c9a80cbaa..907d171bd 100644 --- a/drivers/serial/sphero/sphero_driver.go +++ b/drivers/serial/sphero/sphero_driver.go @@ -183,6 +183,7 @@ func (d *SpheroDriver) SetRotationRate(level uint8) { // SetHeading sets the heading of the Sphero func (d *SpheroDriver) SetHeading(heading uint16) { + //nolint:gosec // TODO: fix later d.sendCraftPacket([]uint8{uint8(heading >> 8), uint8(heading & 0xFF)}, 0x01) } @@ -197,6 +198,7 @@ func (d *SpheroDriver) SetStabilization(on bool) { // Roll sends a roll command to the Sphero gives a speed and heading func (d *SpheroDriver) Roll(speed uint8, heading uint16) { + //nolint:gosec // TODO: fix later d.sendCraftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x30) } @@ -393,7 +395,7 @@ func (d *SpheroDriver) sendCraftPacket(body []uint8, cid byte) { func (d *SpheroDriver) craftPacket(body []uint8, cid byte) *packet { dlen := len(body) + 1 did := uint8(0x02) - hdr := []uint8{0xFF, 0xFF, did, cid, d.seq, uint8(dlen)} + hdr := []uint8{0xFF, 0xFF, did, cid, d.seq, uint8(dlen)} //nolint:gosec // TODO: fix later buf := append(hdr, body...) packet := &packet{ diff --git a/drivers/spi/ssd1306_driver.go b/drivers/spi/ssd1306_driver.go index 819a6a2a7..e13db111b 100644 --- a/drivers/spi/ssd1306_driver.go +++ b/drivers/spi/ssd1306_driver.go @@ -84,7 +84,7 @@ func (d *DisplayBuffer) Clear() { // SetPixel sets the x, y pixel with c color func (d *DisplayBuffer) SetPixel(x, y, c int) { idx := x + (y/d.pageSize)*d.width - bit := uint(y) % uint(d.pageSize) + bit := uint(y) % uint(d.pageSize) //nolint:gosec // TODO: fix later if c == 0 { d.buffer[idx] &= ^(1 << bit) } else { @@ -305,6 +305,7 @@ func (s *SSD1306Driver) Display() error { if err := s.command(0); err != nil { return err } + //nolint:gosec // TODO: fix later if err := s.command(uint8(s.DisplayWidth) - 1); err != nil { return err } @@ -314,6 +315,7 @@ func (s *SSD1306Driver) Display() error { if err := s.command(0); err != nil { return err } + //nolint:gosec // TODO: fix later if err := s.command(uint8(s.pageSize) - 1); err != nil { return err } @@ -371,6 +373,7 @@ func (s *SSD1306Driver) initialize() error { if err := s.command(ssd1306SetMultiplexRatio); err != nil { return err } + //nolint:gosec // TODO: fix later if err := s.command(uint8(s.DisplayHeight) - 1); err != nil { return err } diff --git a/examples/beaglebone_servo.go b/examples/beaglebone_servo.go index 26fd68a5a..325c01400 100644 --- a/examples/beaglebone_servo.go +++ b/examples/beaglebone_servo.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/bleclient_bb8.go b/examples/bleclient_bb8.go index f22a4db1e..18500cc99 100644 --- a/examples/bleclient_bb8.go +++ b/examples/bleclient_bb8.go @@ -13,6 +13,7 @@ NOTE: sudo is required to use BLE in Linux */ +//nolint:gosec // ok here package main import ( diff --git a/examples/bleclient_ollie.go b/examples/bleclient_ollie.go index 82f91762c..208354df0 100644 --- a/examples/bleclient_ollie.go +++ b/examples/bleclient_ollie.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/bleclient_ollie_boost.go b/examples/bleclient_ollie_boost.go index b4a10bf8c..72e1b4963 100644 --- a/examples/bleclient_ollie_boost.go +++ b/examples/bleclient_ollie_boost.go @@ -20,11 +20,11 @@ func main() { ollieBot := sphero.NewOllieDriver(bleAdaptor) work := func() { - head := 90 + head := uint16(90) ollieBot.SetRGB(255, 0, 0) ollieBot.Boost(true) gobot.Every(1*time.Second, func() { - ollieBot.Roll(0, uint16(head)) + ollieBot.Roll(0, head) time.Sleep(1 * time.Second) head += 90 head = head % 360 diff --git a/examples/bleclient_ollie_multiple.go b/examples/bleclient_ollie_multiple.go index 5195e6f82..0ced0c475 100644 --- a/examples/bleclient_ollie_multiple.go +++ b/examples/bleclient_ollie_multiple.go @@ -12,6 +12,7 @@ NOTE: sudo is required to use BLE in Linux */ +//nolint:gosec // ok here package main import ( diff --git a/examples/bleclient_ollie_roll.go b/examples/bleclient_ollie_roll.go index 7bcba8401..bb7b51259 100644 --- a/examples/bleclient_ollie_roll.go +++ b/examples/bleclient_ollie_roll.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/bleclient_sprkplus.go b/examples/bleclient_sprkplus.go index 36c5d1914..d814c667c 100644 --- a/examples/bleclient_sprkplus.go +++ b/examples/bleclient_sprkplus.go @@ -13,6 +13,7 @@ NOTE: sudo is required to use BLE in Linux */ +//nolint:gosec // ok here package main import ( diff --git a/examples/digispark_servo.go b/examples/digispark_servo.go index 4a6fd4d95..5d0e3630b 100644 --- a/examples/digispark_servo.go +++ b/examples/digispark_servo.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/edison_rgb_led.go b/examples/edison_rgb_led.go deleted file mode 100644 index 966887dc1..000000000 --- a/examples/edison_rgb_led.go +++ /dev/null @@ -1,42 +0,0 @@ -//go:build example -// +build example - -// -// Do not build by default. - -package main - -import ( - "fmt" - "time" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/intel-iot/edison" -) - -func main() { - e := edison.NewAdaptor() - led := gpio.NewRgbLedDriver(e, "3", "5", "6") - - work := func() { - gobot.Every(1*time.Second, func() { - r := uint8(gobot.Rand(255)) - g := uint8(gobot.Rand(255)) - b := uint8(gobot.Rand(255)) - if err := led.SetRGB(r, g, b); err != nil { - fmt.Println(err) - } - }) - } - - robot := gobot.NewRobot("rgbBot", - []gobot.Connection{e}, - []gobot.Device{led}, - work, - ) - - if err := robot.Start(); err != nil { - panic(err) - } -} diff --git a/examples/firmata_gpio_max7219.go b/examples/firmata_gpio_max7219.go index 87f3b7682..d0069f971 100644 --- a/examples/firmata_gpio_max7219.go +++ b/examples/firmata_gpio_max7219.go @@ -29,7 +29,7 @@ import ( func main() { firmataAdaptor := firmata.NewAdaptor(os.Args[1]) - max := gpio.NewMAX7219Driver(firmataAdaptor, "11", "10", "9", 4) + maxim := gpio.NewMAX7219Driver(firmataAdaptor, "11", "10", "9", 4) var digit byte = 1 // digit address goes from 0x01 (MAX7219Digit0) to 0x08 (MAX7219Digit8) var bits byte = 1 @@ -38,10 +38,10 @@ func main() { work := func() { gobot.Every(100*time.Millisecond, func() { - if err := max.ClearAll(); err != nil { + if err := maxim.ClearAll(); err != nil { fmt.Println(err) } - if err := max.One(module, digit, bits); err != nil { + if err := maxim.One(module, digit, bits); err != nil { fmt.Println(err) } bits = bits << 1 @@ -65,7 +65,7 @@ func main() { robot := gobot.NewRobot("Max7219Bot", []gobot.Connection{firmataAdaptor}, - []gobot.Device{max}, + []gobot.Device{maxim}, work, ) diff --git a/examples/firmata_pca9685.go b/examples/firmata_pca9685.go index 05e56c766..58a9f6302 100644 --- a/examples/firmata_pca9685.go +++ b/examples/firmata_pca9685.go @@ -11,6 +11,7 @@ go run examples/firmata_pca9685.go /dev/ttyACM0 */ +//nolint:gosec // ok here package main import ( diff --git a/examples/firmata_rgb_led.go b/examples/firmata_rgb_led.go index 8a246b66d..0f403f1d4 100644 --- a/examples/firmata_rgb_led.go +++ b/examples/firmata_rgb_led.go @@ -11,6 +11,7 @@ go run examples/firmata_rgb_led.go /dev/ttyACM0 */ +//nolint:gosec // ok here package main import ( diff --git a/examples/firmata_servo.go b/examples/firmata_servo.go index ed1cbb07d..0663614b3 100644 --- a/examples/firmata_servo.go +++ b/examples/firmata_servo.go @@ -11,6 +11,7 @@ go run examples/firmata_servo.go /dev/ttyACM0 */ +//nolint:gosec // ok here package main import ( diff --git a/examples/gopigo3_servo.go b/examples/gopigo3_servo.go index 04e50bfdf..c1aa98ffc 100644 --- a/examples/gopigo3_servo.go +++ b/examples/gopigo3_servo.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/jetson-nano_servo.go b/examples/jetson-nano_servo.go index 5eaafe92b..ee62319d9 100644 --- a/examples/jetson-nano_servo.go +++ b/examples/jetson-nano_servo.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main // diff --git a/examples/joule_rgb_led.go b/examples/joule_rgb_led.go deleted file mode 100644 index 6f008969a..000000000 --- a/examples/joule_rgb_led.go +++ /dev/null @@ -1,42 +0,0 @@ -//go:build example -// +build example - -// -// Do not build by default. - -package main - -import ( - "fmt" - "time" - - "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/drivers/gpio" - "gobot.io/x/gobot/v2/platforms/intel-iot/joule" -) - -func main() { - e := joule.NewAdaptor() - led := gpio.NewRgbLedDriver(e, "25", "27", "29") - - work := func() { - gobot.Every(1*time.Second, func() { - r := uint8(gobot.Rand(255)) - g := uint8(gobot.Rand(255)) - b := uint8(gobot.Rand(255)) - if err := led.SetRGB(r, g, b); err != nil { - fmt.Println(err) - } - }) - } - - robot := gobot.NewRobot("rgbBot", - []gobot.Connection{e}, - []gobot.Device{led}, - work, - ) - - if err := robot.Start(); err != nil { - panic(err) - } -} diff --git a/examples/raspi_adafruit2327_servo.go b/examples/raspi_adafruit2327_servo.go index d87d78103..846137c73 100644 --- a/examples/raspi_adafruit2327_servo.go +++ b/examples/raspi_adafruit2327_servo.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/raspi_stepper_move.go b/examples/raspi_stepper_move.go index d214d5438..f20b2eee8 100644 --- a/examples/raspi_stepper_move.go +++ b/examples/raspi_stepper_move.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/serialport_sphero.go b/examples/serialport_sphero.go index af709cc13..1947542f6 100644 --- a/examples/serialport_sphero.go +++ b/examples/serialport_sphero.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/serialport_sphero_conways.go b/examples/serialport_sphero_conways.go index 73e974791..11de8517f 100644 --- a/examples/serialport_sphero_conways.go +++ b/examples/serialport_sphero_conways.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/serialport_sphero_master.go b/examples/serialport_sphero_master.go index 793858b3d..2679ab17d 100644 --- a/examples/serialport_sphero_master.go +++ b/examples/serialport_sphero_master.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/examples/serialport_sphero_multiple.go b/examples/serialport_sphero_multiple.go index 12058f566..6d8c70374 100644 --- a/examples/serialport_sphero_multiple.go +++ b/examples/serialport_sphero_multiple.go @@ -4,6 +4,7 @@ // // Do not build by default. +//nolint:gosec // ok here package main import ( diff --git a/go.mod b/go.mod index 3bd97c5e0..e5283e041 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module gobot.io/x/gobot/v2 -go 1.20 +go 1.22.0 + +toolchain go1.22.7 require ( github.com/0xcafed00d/joystick v1.0.1 @@ -15,12 +17,12 @@ require ( github.com/nsf/termbox-go v1.1.1 github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f github.com/stretchr/testify v1.9.0 - github.com/warthog618/gpiod v0.8.3 + github.com/warthog618/go-gpiocdev v0.9.1 go.bug.st/serial v1.6.2 gocv.io/x/gocv v0.39.0 golang.org/x/net v0.30.0 golang.org/x/sys v0.26.0 - periph.io/x/conn/v3 v3.7.0 + periph.io/x/conn/v3 v3.7.1 periph.io/x/host/v3 v3.8.2 tinygo.org/x/bluetooth v0.8.0 ) diff --git a/go.sum b/go.sum index c1773eb6b..d8bc81ebb 100644 --- a/go.sum +++ b/go.sum @@ -75,9 +75,10 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 github.com/suapapa/go_eddystone v1.3.1/go.mod h1:bXC11TfJOS+3g3q/Uzd7FKd5g62STQEfeEIhcKe4Qy8= github.com/tinygo-org/cbgo v0.0.4 h1:3D76CRYbH03Rudi8sEgs/YO0x3JIMdyq8jlQtk/44fU= github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk= -github.com/warthog618/go-gpiosim v0.1.0 h1:2rTMTcKUVZxpUuvRKsagnKAbKpd3Bwffp87xywEDVGI= -github.com/warthog618/gpiod v0.8.3 h1:hGFm/zf5PUyXU2LBG4fiZyRnbSSiPEajuOtQzQ3vkLo= -github.com/warthog618/gpiod v0.8.3/go.mod h1:YHsKSpTHebSDGnKNQKfQp9t/0JxQCyXyYtCF3F+78dc= +github.com/warthog618/go-gpiocdev v0.9.1 h1:pwHPaqjJfhCipIQl78V+O3l9OKHivdRDdmgXYbmhuCI= +github.com/warthog618/go-gpiocdev v0.9.1/go.mod h1:dN3e3t/S2aSNC+hgigGE/dBW8jE1ONk9bDSEYfoPyl8= +github.com/warthog618/go-gpiosim v0.1.1 h1:MRAEv+T+itmw+3GeIGpQJBfanUVyg0l3JCTwHtwdre4= +github.com/warthog618/go-gpiosim v0.1.1/go.mod h1:YXsnB+I9jdCMY4YAlMSRrlts25ltjmuIsrnoUrBLdqU= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8= go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= @@ -119,8 +120,8 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -periph.io/x/conn/v3 v3.7.0 h1:f1EXLn4pkf7AEWwkol2gilCNZ0ElY+bxS4WE2PQXfrA= -periph.io/x/conn/v3 v3.7.0/go.mod h1:ypY7UVxgDbP9PJGwFSVelRRagxyXYfttVh7hJZUHEhg= +periph.io/x/conn/v3 v3.7.1 h1:tMjNv3WO8jEz/ePuXl7y++2zYi8LsQ5otbmqGKy3Myg= +periph.io/x/conn/v3 v3.7.1/go.mod h1:c+HCVjkzbf09XzcqZu/t+U8Ss/2QuJj0jgRF6Nye838= periph.io/x/host/v3 v3.8.2 h1:ayKUDzgUCN0g8+/xM9GTkWaOBhSLVcVHGTfjAOi8OsQ= periph.io/x/host/v3 v3.8.2/go.mod h1:yFL76AesNHR68PboofSWYaQTKmvPXsQH2Apvp/ls/K4= tinygo.org/x/bluetooth v0.8.0 h1:WmuRebsODcUUIlGhesyuNRIAEIUCErhKlrZ9K9aimdI= diff --git a/platforms/adaptors/pwmpinsadaptor.go b/platforms/adaptors/pwmpinsadaptor.go index 16388bba2..25978a40c 100644 --- a/platforms/adaptors/pwmpinsadaptor.go +++ b/platforms/adaptors/pwmpinsadaptor.go @@ -135,14 +135,14 @@ func WithPWMDefaultPeriodForPin(pin string, periodNanoSec uint32) pwmPinsDefault // WithPWMServoDutyCycleRangeForPin set new values for range of duty cycle for servo calls, which replaces the default // 0.5-2.5 ms range. The given duration values will be internally converted to nanoseconds. -func WithPWMServoDutyCycleRangeForPin(pin string, min, max time.Duration) pwmPinsServoDutyScaleForPinOption { - return pwmPinsServoDutyScaleForPinOption{id: pin, min: min, max: max} +func WithPWMServoDutyCycleRangeForPin(pin string, minimum, maximum time.Duration) pwmPinsServoDutyScaleForPinOption { + return pwmPinsServoDutyScaleForPinOption{id: pin, min: minimum, max: maximum} } // WithPWMServoAngleRangeForPin set new values for range of angle for servo calls, which replaces // the default 0.0-180.0° range. -func WithPWMServoAngleRangeForPin(pin string, min, max float64) pwmPinsServoAngleScaleForPinOption { - return pwmPinsServoAngleScaleForPinOption{id: pin, minDegree: min, maxDegree: max} +func WithPWMServoAngleRangeForPin(pin string, minimum, maximum float64) pwmPinsServoAngleScaleForPinOption { + return pwmPinsServoAngleScaleForPinOption{id: pin, minDegree: minimum, maxDegree: maximum} } // Connect prepare new connection to PWM pins. @@ -384,6 +384,8 @@ func setPeriod(pin gobot.PWMPinner, period uint32, adjustDuty bool) error { if err != nil { return fmt.Errorf("%s with '%v'", errorBase, err) } + + //nolint:gosec // TODO: fix later duty := uint32(uint64(oldDuty) * uint64(period) / uint64(oldPeriod)) // the order depends on value (duty must not be bigger than period in any situation) diff --git a/platforms/adaptors/pwmpinsadaptor_test.go b/platforms/adaptors/pwmpinsadaptor_test.go index 3dfc595fe..400674d97 100644 --- a/platforms/adaptors/pwmpinsadaptor_test.go +++ b/platforms/adaptors/pwmpinsadaptor_test.go @@ -2,6 +2,7 @@ package adaptors import ( + "errors" "fmt" "runtime" "strconv" @@ -416,7 +417,7 @@ func Test_PWMPin(t *testing.T) { "/sys/devices/platform/ff680020.pwm/pwm/pwmchip3/pwm44/polarity: no such file", }, "translate_error": { - translate: func(string) (string, int, error) { return "", -1, fmt.Errorf(translateErr) }, + translate: func(string) (string, int, error) { return "", -1, errors.New(translateErr) }, wantErr: translateErr, }, } diff --git a/platforms/dexter/gopigo3/driver.go b/platforms/dexter/gopigo3/driver.go index 0edbdb1d2..d05ca6bee 100644 --- a/platforms/dexter/gopigo3/driver.go +++ b/platforms/dexter/gopigo3/driver.go @@ -355,7 +355,7 @@ func (d *Driver) ServoWrite(port string, angle byte) error { angle = 180 } pulseWidth := ((1500 - (pulseWidthRange / 2)) + ((pulseWidthRange / 180) * int(angle))) - return d.SetServo(srvo, uint16(pulseWidth)) + return d.SetServo(srvo, uint16(pulseWidth)) //nolint:gosec // TODO: fix later } // SetMotorPower sets a motor's power from -128 to 127. @@ -438,7 +438,7 @@ func (d *Driver) GetMotorStatus(motor Motor) (flags uint8, power uint16, encoder e := binary.LittleEndian.Uint32(enc) encoder = int(e) if e&0x80000000 == 0x80000000 { - encoder = int(uint64(e) - 0x100000000) + encoder = int(uint64(e) - 0x100000000) //nolint:gosec // TODO: fix later } // get dps dpsRaw := make([]byte, 4) @@ -557,7 +557,7 @@ func (d *Driver) PwmWrite(pin string, val byte) error { return err } val64 := math.Float64frombits(uint64(val)) - dutyCycle := uint16(math.Float64bits((100.0 / 255.0) * val64)) + dutyCycle := uint16(math.Float64bits((100.0 / 255.0) * val64)) //nolint:gosec // TODO: fix later return d.SetPWMDuty(grovePin, dutyCycle) } diff --git a/platforms/digispark/README.md b/platforms/digispark/README.md index 80a953aff..b53687033 100644 --- a/platforms/digispark/README.md +++ b/platforms/digispark/README.md @@ -66,6 +66,8 @@ func main() { } ``` +Build your application with build tag "libusb". + ## How to Connect If your Digispark already has the Little Wire protocol firmware installed, you can connect right away with Gobot. diff --git a/platforms/digispark/digispark_adaptor.go b/platforms/digispark/digispark_adaptor.go index fd69498d5..44e139221 100644 --- a/platforms/digispark/digispark_adaptor.go +++ b/platforms/digispark/digispark_adaptor.go @@ -1,3 +1,6 @@ +//go:build libusb +// +build libusb + package digispark import ( @@ -58,10 +61,12 @@ func (d *Adaptor) DigitalWrite(pin string, level byte) error { return err } + //nolint:gosec // TODO: fix later if err := d.littleWire.pinMode(uint8(p), 0); err != nil { return err } + //nolint:gosec // TODO: fix later return d.littleWire.digitalWrite(uint8(p), level) } @@ -98,6 +103,7 @@ func (d *Adaptor) GetI2cConnection(address int, bus int) (i2c.Connection, error) if bus != 0 { return nil, fmt.Errorf("Invalid bus number %d, only 0 is supported", bus) } + //nolint:gosec // TODO: fix later c := NewDigisparkI2cConnection(d, uint8(address)) if err := c.Init(); err != nil { return nil, err diff --git a/platforms/digispark/digispark_adaptor_test.go b/platforms/digispark/digispark_adaptor_test.go index 677018fa6..cbf74fbde 100644 --- a/platforms/digispark/digispark_adaptor_test.go +++ b/platforms/digispark/digispark_adaptor_test.go @@ -1,3 +1,6 @@ +//go:build libusb +// +build libusb + //nolint:forcetypeassert // ok here package digispark diff --git a/platforms/digispark/digispark_i2c.go b/platforms/digispark/digispark_i2c.go index b63f50f1e..7a178aa3f 100644 --- a/platforms/digispark/digispark_i2c.go +++ b/platforms/digispark/digispark_i2c.go @@ -1,3 +1,6 @@ +//go:build libusb +// +build libusb + package digispark import ( @@ -155,8 +158,8 @@ func (c *digisparkI2cConnection) WriteWordData(reg uint8, val uint16) error { c.mtx.Lock() defer c.mtx.Unlock() - low := uint8(val & 0xff) - high := uint8((val >> 8) & 0xff) + low := uint8(val & 0xff) //nolint:gosec // ok here + high := uint8((val >> 8) & 0xff) //nolint:gosec // ok here buf := []byte{reg, low, high} return c.writeAndCheckCount(buf, true) } diff --git a/platforms/digispark/digispark_i2c_test.go b/platforms/digispark/digispark_i2c_test.go index b14b7fb38..5c603f501 100644 --- a/platforms/digispark/digispark_i2c_test.go +++ b/platforms/digispark/digispark_i2c_test.go @@ -1,3 +1,6 @@ +//go:build libusb +// +build libusb + //nolint:forcetypeassert // ok here package digispark diff --git a/platforms/digispark/doc.go b/platforms/digispark/doc.go index a62d3a2db..3105d4105 100644 --- a/platforms/digispark/doc.go +++ b/platforms/digispark/doc.go @@ -1,3 +1,6 @@ +//go:build libusb +// +build libusb + /* Package digispark provides the Gobot adaptor for the Digispark ATTiny-based USB development board. diff --git a/platforms/digispark/littleWire.go b/platforms/digispark/littleWire.go index 39f129c1e..e8a97879c 100644 --- a/platforms/digispark/littleWire.go +++ b/platforms/digispark/littleWire.go @@ -1,3 +1,6 @@ +//go:build libusb +// +build libusb + package digispark //#cgo pkg-config: libusb diff --git a/platforms/dji/tello/driver.go b/platforms/dji/tello/driver.go index 0510c0316..ffe23fe91 100644 --- a/platforms/dji/tello/driver.go +++ b/platforms/dji/tello/driver.go @@ -890,7 +890,7 @@ func (d *Driver) SendStickCommand() error { axis4 := int16(660.0*d.lx + 1024.0) // speed control - axis5 := int16(d.throttle) + axis5 := int16(d.throttle) //nolint:gosec // TODO: fix later packedAxis := int64(axis1)&0x7FF | int64(axis2&0x7FF)<<11 | 0x7FF&int64(axis3)<<22 | 0x7FF&int64(axis4)<<33 | int64(axis5)<<44 @@ -954,18 +954,23 @@ func (d *Driver) SendDateTime() error { if err := binary.Write(buf, binary.LittleEndian, byte(0x00)); err != nil { return err } + //nolint:gosec // TODO: fix later if err := binary.Write(buf, binary.LittleEndian, int16(now.Hour())); err != nil { return err } + //nolint:gosec // TODO: fix later if err := binary.Write(buf, binary.LittleEndian, int16(now.Minute())); err != nil { return err } + //nolint:gosec // TODO: fix later if err := binary.Write(buf, binary.LittleEndian, int16(now.Second())); err != nil { return err } + //nolint:gosec // TODO: fix later if err := binary.Write(buf, binary.LittleEndian, int16(now.UnixNano()/int64(time.Millisecond)&0xff)); err != nil { return err } + //nolint:gosec // TODO: fix later if err := binary.Write(buf, binary.LittleEndian, int16(now.UnixNano()/int64(time.Millisecond)>>8)); err != nil { return err } @@ -1100,7 +1105,7 @@ func (d *Driver) createPacket(cmd int16, pktType byte, pktLen int16) (*bytes.Buf func (d *Driver) connectionString() string { x, _ := strconv.Atoi(d.videoPort) b := [2]byte{} - binary.LittleEndian.PutUint16(b[:], uint16(x)) + binary.LittleEndian.PutUint16(b[:], uint16(x)) //nolint:gosec // TODO: fix later res := fmt.Sprintf("conn_req:%s", b) return res } diff --git a/platforms/firmata/client/client.go b/platforms/firmata/client/client.go index 0f0f6f246..6c000102d 100644 --- a/platforms/firmata/client/client.go +++ b/platforms/firmata/client/client.go @@ -278,14 +278,14 @@ func (b *Client) DigitalWrite(pin int, value int) error { } // ServoConfig sets the min and max pulse width for servo PWM range -func (b *Client) ServoConfig(pin int, max int, min int) error { +func (b *Client) ServoConfig(pin int, maximum int, minimum int) error { ret := []byte{ ServoConfig, byte(pin), - byte(min & 0x7F), - byte((min >> 7) & 0x7F), - byte(max & 0x7F), - byte((max >> 7) & 0x7F), + byte(minimum & 0x7F), + byte((minimum >> 7) & 0x7F), + byte(maximum & 0x7F), + byte((maximum >> 7) & 0x7F), } return b.WriteSysex(ret) } @@ -410,6 +410,7 @@ func (b *Client) process() error { if len(b.analogPins) > pin { if len(b.pins) > b.analogPins[pin] { + //nolint:gosec // TODO: fix later b.pins[b.analogPins[pin]].Value = int(value) b.Publish(b.Event(fmt.Sprintf("AnalogRead%v", pin)), b.pins[b.analogPins[pin]].Value) } @@ -500,9 +501,11 @@ func (b *Client) process() error { b.pins[pin].State = int(currentBuffer[4]) if len(currentBuffer) > 6 { + //nolint:gosec // TODO: fix later b.pins[pin].State = int(uint(b.pins[pin].State) | uint(currentBuffer[5])<<7) } if len(currentBuffer) > 7 { + //nolint:gosec // TODO: fix later b.pins[pin].State = int(uint(b.pins[pin].State) | uint(currentBuffer[6])<<14) } diff --git a/platforms/firmata/firmata_adaptor.go b/platforms/firmata/firmata_adaptor.go index 888f6a13b..0c704bb2c 100644 --- a/platforms/firmata/firmata_adaptor.go +++ b/platforms/firmata/firmata_adaptor.go @@ -28,7 +28,7 @@ type firmataBoard interface { I2cRead(address int, numBytes int) error I2cWrite(address int, data []byte) error I2cConfig(delay int) error - ServoConfig(pin int, max int, min int) error + ServoConfig(pin int, maximum int, minimum int) error WriteSysex(data []byte) error gobot.Eventer } @@ -126,13 +126,13 @@ func (f *Adaptor) Name() string { return f.name } func (f *Adaptor) SetName(n string) { f.name = n } // ServoConfig sets the pulse width in microseconds for a pin attached to a servo -func (f *Adaptor) ServoConfig(pin string, min, max int) error { +func (f *Adaptor) ServoConfig(pin string, minimum, maximum int) error { p, err := strconv.Atoi(pin) if err != nil { return err } - return f.Board.ServoConfig(p, max, min) + return f.Board.ServoConfig(p, maximum, minimum) } // ServoWrite writes the 0-180 degree angle to the specified pin. diff --git a/platforms/firmata/firmata_i2c.go b/platforms/firmata/firmata_i2c.go index e4c5d8714..407091026 100644 --- a/platforms/firmata/firmata_i2c.go +++ b/platforms/firmata/firmata_i2c.go @@ -140,8 +140,8 @@ func (c *firmataI2cConnection) WriteWordData(reg uint8, val uint16) error { c.mtx.Lock() defer c.mtx.Unlock() - low := uint8(val & 0xff) - high := uint8((val >> 8) & 0xff) + low := uint8(val & 0xff) //nolint:gosec // ok here + high := uint8((val >> 8) & 0xff) //nolint:gosec // ok here buf := []byte{reg, low, high} return c.writeAndCheckCount(buf) } diff --git a/platforms/firmata/firmata_i2c_test.go b/platforms/firmata/firmata_i2c_test.go index 8b06ca6f6..0b5247e73 100644 --- a/platforms/firmata/firmata_i2c_test.go +++ b/platforms/firmata/firmata_i2c_test.go @@ -1,7 +1,7 @@ //go:build !windows // +build !windows -//nolint:forcetypeassert // ok here +//nolint:forcetypeassert,gosec // ok here package firmata import ( diff --git a/platforms/intel-iot/curie/imu_driver.go b/platforms/intel-iot/curie/imu_driver.go index 185e6bc0f..340c37d6c 100644 --- a/platforms/intel-iot/curie/imu_driver.go +++ b/platforms/intel-iot/curie/imu_driver.go @@ -203,9 +203,9 @@ func parseAccelerometerData(data []byte) (*AccelerometerData, error) { if len(data) < 9 { return nil, errors.New("Invalid data") } - x := int16(uint16(data[3]) | uint16(data[4])<<7) - y := int16(uint16(data[5]) | uint16(data[6])<<7) - z := int16(uint16(data[7]) | uint16(data[8])<<7) + x := int16(uint16(data[3]) | uint16(data[4])<<7) //nolint:gosec // ok here + y := int16(uint16(data[5]) | uint16(data[6])<<7) //nolint:gosec // ok here + z := int16(uint16(data[7]) | uint16(data[8])<<7) //nolint:gosec // ok here res := &AccelerometerData{X: x, Y: y, Z: z} return res, nil @@ -215,9 +215,9 @@ func parseGyroscopeData(data []byte) (*GyroscopeData, error) { if len(data) < 9 { return nil, errors.New("Invalid data") } - x := int16(uint16(data[3]) | uint16(data[4])<<7) - y := int16(uint16(data[5]) | uint16(data[6])<<7) - z := int16(uint16(data[7]) | uint16(data[8])<<7) + x := int16(uint16(data[3]) | uint16(data[4])<<7) //nolint:gosec // ok here + y := int16(uint16(data[5]) | uint16(data[6])<<7) //nolint:gosec // ok here + z := int16(uint16(data[7]) | uint16(data[8])<<7) //nolint:gosec // ok here res := &GyroscopeData{X: x, Y: y, Z: z} return res, nil @@ -227,8 +227,8 @@ func parseTemperatureData(data []byte) (float32, error) { if len(data) < 8 { return 0, errors.New("Invalid data") } - t1 := int16(uint16(data[3]) | uint16(data[4])<<7) - t2 := int16(uint16(data[5]) | uint16(data[6])<<7) + t1 := int16(uint16(data[3]) | uint16(data[4])<<7) //nolint:gosec // ok here + t2 := int16(uint16(data[5]) | uint16(data[6])<<7) //nolint:gosec // ok here res := (float32(t1+(t2*8)) / 512.0) + 23.0 return res, nil @@ -248,7 +248,7 @@ func parseStepData(data []byte) (int16, error) { return 0, errors.New("Invalid data") } - res := int16(uint16(data[3]) | uint16(data[4])<<7) + res := int16(uint16(data[3]) | uint16(data[4])<<7) //nolint:gosec // ok here return res, nil } @@ -265,13 +265,13 @@ func parseMotionData(data []byte) (*MotionData, error) { if len(data) < 16 { return nil, errors.New("Invalid data") } - ax := int16(uint16(data[3]) | uint16(data[4])<<7) - ay := int16(uint16(data[5]) | uint16(data[6])<<7) - az := int16(uint16(data[7]) | uint16(data[8])<<7) + ax := int16(uint16(data[3]) | uint16(data[4])<<7) //nolint:gosec // ok here + ay := int16(uint16(data[5]) | uint16(data[6])<<7) //nolint:gosec // ok here + az := int16(uint16(data[7]) | uint16(data[8])<<7) //nolint:gosec // ok here - gx := int16(uint16(data[9]) | uint16(data[10])<<7) - gy := int16(uint16(data[11]) | uint16(data[12])<<7) - gz := int16(uint16(data[13]) | uint16(data[14])<<7) + gx := int16(uint16(data[9]) | uint16(data[10])<<7) //nolint:gosec // ok here + gy := int16(uint16(data[11]) | uint16(data[12])<<7) //nolint:gosec // ok here + gz := int16(uint16(data[13]) | uint16(data[14])<<7) //nolint:gosec // ok here res := &MotionData{AX: ax, AY: ay, AZ: az, GX: gx, GY: gy, GZ: gz} return res, nil diff --git a/platforms/joystick/bin/scanner.go b/platforms/joystick/bin/scanner.go index 6bda8e447..8554c9871 100644 --- a/platforms/joystick/bin/scanner.go +++ b/platforms/joystick/bin/scanner.go @@ -39,6 +39,7 @@ func readJoystick(js joystick.Joystick) { printAt(1, 5, "Buttons:") for button := 0; button < js.ButtonCount(); button++ { + //nolint:gosec // TODO: fix later if jinfo.Buttons&(1<> 8) ^ (uint16(tmp) << 8) ^ (uint16(tmp) << 3) ^ (uint16(tmp) >> 4) return crcAccum diff --git a/platforms/mavlink/mavlink_adaptor_test.go b/platforms/mavlink/mavlink_adaptor_test.go index da18a6c93..2a279a0b2 100644 --- a/platforms/mavlink/mavlink_adaptor_test.go +++ b/platforms/mavlink/mavlink_adaptor_test.go @@ -52,7 +52,7 @@ func (nullReadWriteCloser) Close() error { func initTestMavlinkAdaptor() *Adaptor { m := NewAdaptor("/dev/null") m.sp = nullReadWriteCloser{} - m.connect = func(port string) (io.ReadWriteCloser, error) { return nil, nil } + m.connect = func(port string) (io.ReadWriteCloser, error) { return nil, nil } //nolint:nilnil // ok for tests return m } diff --git a/platforms/mavlink/mavlink_driver_test.go b/platforms/mavlink/mavlink_driver_test.go index f1efef54b..624a2bb77 100644 --- a/platforms/mavlink/mavlink_driver_test.go +++ b/platforms/mavlink/mavlink_driver_test.go @@ -1,4 +1,4 @@ -//nolint:forcetypeassert // ok here +//nolint:forcetypeassert,nilnil // ok here package mavlink import ( diff --git a/platforms/opencv/README.md b/platforms/opencv/README.md index c89e25b92..8f7f64c18 100644 --- a/platforms/opencv/README.md +++ b/platforms/opencv/README.md @@ -69,3 +69,5 @@ func main() { } } ``` + +Build your application with build tag "gocv". diff --git a/platforms/opencv/camera_driver.go b/platforms/opencv/camera_driver.go index 9a4e8136c..d84f3e77d 100644 --- a/platforms/opencv/camera_driver.go +++ b/platforms/opencv/camera_driver.go @@ -1,3 +1,6 @@ +//go:build gocv +// +build gocv + package opencv import ( @@ -41,7 +44,7 @@ func NewCameraDriver(source interface{}) *CameraDriver { default: return errors.New("Unknown camera source") } - return + return nil }, } @@ -72,7 +75,7 @@ func (c *CameraDriver) Start() error { } } }() - return + return nil } // Halt stops camera driver diff --git a/platforms/opencv/camera_driver_test.go b/platforms/opencv/camera_driver_test.go index 81ecacb7f..d37811366 100644 --- a/platforms/opencv/camera_driver_test.go +++ b/platforms/opencv/camera_driver_test.go @@ -1,3 +1,6 @@ +//go:build gocv +// +build gocv + package opencv import ( diff --git a/platforms/opencv/helpers_test.go b/platforms/opencv/helpers_test.go index b8c7d63f2..e04299f6e 100644 --- a/platforms/opencv/helpers_test.go +++ b/platforms/opencv/helpers_test.go @@ -1,3 +1,6 @@ +//go:build gocv +// +build gocv + package opencv import ( diff --git a/platforms/opencv/utils.go b/platforms/opencv/utils.go index 7e2641a19..b0dedb7a7 100644 --- a/platforms/opencv/utils.go +++ b/platforms/opencv/utils.go @@ -1,3 +1,6 @@ +//go:build gocv +// +build gocv + package opencv import ( diff --git a/platforms/opencv/utils_test.go b/platforms/opencv/utils_test.go index 775f2df60..eb4879eb8 100644 --- a/platforms/opencv/utils_test.go +++ b/platforms/opencv/utils_test.go @@ -1,3 +1,6 @@ +//go:build gocv +// +build gocv + package opencv import ( diff --git a/platforms/opencv/window_driver.go b/platforms/opencv/window_driver.go index a1130e521..943dd2756 100644 --- a/platforms/opencv/window_driver.go +++ b/platforms/opencv/window_driver.go @@ -1,3 +1,6 @@ +//go:build gocv +// +build gocv + package opencv import ( @@ -39,11 +42,11 @@ func (w *WindowDriver) Connection() gobot.Connection { return nil } // Start starts window thread and driver func (w *WindowDriver) Start() error { w.start(w) - return + return nil } // Halt returns true if camera is halted successfully -func (w *WindowDriver) Halt() error { return } +func (w *WindowDriver) Halt() error { return nil } // ShowImage displays image in window func (w *WindowDriver) ShowImage(img gocv.Mat) { diff --git a/platforms/opencv/window_driver_test.go b/platforms/opencv/window_driver_test.go index 36bebcf90..042162233 100644 --- a/platforms/opencv/window_driver_test.go +++ b/platforms/opencv/window_driver_test.go @@ -1,3 +1,6 @@ +//go:build gocv +// +build gocv + package opencv import ( diff --git a/platforms/parrot/bebop/client/client.go b/platforms/parrot/bebop/client/client.go index fc4c391c6..81da02887 100644 --- a/platforms/parrot/bebop/client/client.go +++ b/platforms/parrot/bebop/client/client.go @@ -435,30 +435,35 @@ func (b *Bebop) generatePcmd() *bytes.Buffer { cmd.Write(tmp.Bytes()) tmp = &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(tmp, binary.LittleEndian, uint8(b.Pcmd.Flag)); err != nil { panic(err) } cmd.Write(tmp.Bytes()) tmp = &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(tmp, binary.LittleEndian, int8(b.Pcmd.Roll)); err != nil { panic(err) } cmd.Write(tmp.Bytes()) tmp = &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(tmp, binary.LittleEndian, int8(b.Pcmd.Pitch)); err != nil { panic(err) } cmd.Write(tmp.Bytes()) tmp = &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(tmp, binary.LittleEndian, int8(b.Pcmd.Yaw)); err != nil { panic(err) } cmd.Write(tmp.Bytes()) tmp = &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(tmp, binary.LittleEndian, int8(b.Pcmd.Gaz)); err != nil { panic(err) } @@ -482,6 +487,7 @@ func (b *Bebop) createAck(frame NetworkFrame) *bytes.Buffer { // libARNetwork/Sources/ARNETWORK_Manager.h#ARNETWORK_Manager_IDOutputToIDAck // + //nolint:gosec // TODO: fix later return b.nwFrameGenerator.generate(bytes.NewBuffer([]byte{uint8(frame.Seq)}), ARNETWORKAL_FRAME_TYPE_ACK, byte(uint16(frame.Id)+(ARNETWORKAL_MANAGER_DEFAULT_ID_MAX/2)), @@ -755,14 +761,17 @@ func (b *Bebop) createARStreamACK(frame ARStreamFrame) *bytes.Buffer { b.tmpFrame.fragments[frame.FragmentNumber] = frame.Frame if frame.FragmentNumber < 64 { + //nolint:gosec // TODO: fix later b.tmpFrame.arstreamACK.LowPacketsAck |= uint64(1) << uint64(frame.FragmentNumber) } else { + //nolint:gosec // TODO: fix later b.tmpFrame.arstreamACK.HighPacketsAck |= uint64(1) << uint64(frame.FragmentNumber-64) } ackPacket := &bytes.Buffer{} tmp := &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(tmp, binary.LittleEndian, uint16(b.tmpFrame.arstreamACK.FrameNumber)); err != nil { panic(err) } diff --git a/platforms/parrot/bebop/client/networkframegenerator.go b/platforms/parrot/bebop/client/networkframegenerator.go index af06e356b..44b189428 100644 --- a/platforms/parrot/bebop/client/networkframegenerator.go +++ b/platforms/parrot/bebop/client/networkframegenerator.go @@ -40,11 +40,7 @@ func (nwg *nwFrameGenerator) generate(cmd *bytes.Buffer, frameType byte, id byte nwg.seq[id] = 0 } - nwg.seq[id]++ - - if nwg.seq[id] > 255 { - nwg.seq[id] = 0 - } + nwg.seq[id]++ // automatically rollover to 0 when > 255 is fine ret := &bytes.Buffer{} ret.WriteByte(frameType) @@ -52,6 +48,7 @@ func (nwg *nwFrameGenerator) generate(cmd *bytes.Buffer, frameType byte, id byte ret.WriteByte(nwg.seq[id]) size := &bytes.Buffer{} + //nolint:gosec // TODO: fix later if err := binary.Write(size, binary.LittleEndian, uint32(cmd.Len()+nwg.hlen)); err != nil { panic(err) } diff --git a/platforms/particle/adaptor_test.go b/platforms/particle/adaptor_test.go index 69fc29675..6ddbcfb14 100644 --- a/platforms/particle/adaptor_test.go +++ b/platforms/particle/adaptor_test.go @@ -29,6 +29,7 @@ func getDummyResponseForPath(t *testing.T, path string, dummyResponse string) *h return createTestServer(func(w http.ResponseWriter, r *http.Request) { actualPath := "/v1/devices" + path if r.URL.Path != actualPath { + //nolint:testifylint // TODO: fix later require.Fail(t, "Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path) } _, _ = w.Write(dummyData) @@ -48,6 +49,7 @@ func getDummyResponseForPathWithParams( return createTestServer(func(w http.ResponseWriter, r *http.Request) { actualPath := "/v1/devices" + path if r.URL.Path != actualPath { + //nolint:testifylint // TODO: fix later require.Fail(t, "Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path) } diff --git a/system/digitalpin_gpiod.go b/system/digitalpin_gpiod.go index 7ebe9f85c..1b979f70f 100644 --- a/system/digitalpin_gpiod.go +++ b/system/digitalpin_gpiod.go @@ -1,13 +1,14 @@ package system import ( + "errors" "fmt" "log" "strconv" "strings" "time" - "github.com/warthog618/gpiod" + gpiod "github.com/warthog618/go-gpiocdev" "gobot.io/x/gobot/v2" ) @@ -117,7 +118,8 @@ func (d *digitalPinGpiod) Unexport() error { if len(errs) == 0 { return nil } - return fmt.Errorf(strings.Join(errs, ",")) + + return errors.New(strings.Join(errs, ",")) } // Write writes the given value to the character device. Implements the interface gobot.DigitalPinner. diff --git a/system/digitalpin_poll_test.go b/system/digitalpin_poll_test.go index d72011008..0c8a0c5eb 100644 --- a/system/digitalpin_poll_test.go +++ b/system/digitalpin_poll_test.go @@ -1,7 +1,7 @@ package system import ( - "fmt" + "errors" "sync" "testing" "time" @@ -150,7 +150,7 @@ func Test_startEdgePolling(t *testing.T) { readVal := tc.simulateReadValues[numCallsRead-1] var err error if readVal.err != "" { - err = fmt.Errorf(readVal.err) + err = errors.New(readVal.err) } if numCallsRead >= len(tc.simulateReadValues) { close(quitChan) // ensure no further read call diff --git a/system/fs_mock_test.go b/system/fs_mock_test.go index 849c8e4ee..b271628a5 100644 --- a/system/fs_mock_test.go +++ b/system/fs_mock_test.go @@ -80,7 +80,7 @@ func TestMockFilesystemWrite(t *testing.T) { _, _ = f2.WriteString("testing") // Was written. - assert.Greater(t, f1.Seq, 0) + assert.Positive(t, f1.Seq) assert.Equal(t, "testing", f1.Contents) } @@ -98,7 +98,7 @@ func TestMockFilesystemRead(t *testing.T) { n, _ := f2.Read(buffer) // Was read. - assert.Greater(t, f1.Seq, 0) + assert.Positive(t, f1.Seq) assert.Equal(t, 3, n) assert.Equal(t, "Yip", string(buffer[:3])) diff --git a/system/i2c_device.go b/system/i2c_device.go index 2a3d83b14..f941424ba 100644 --- a/system/i2c_device.go +++ b/system/i2c_device.go @@ -382,6 +382,7 @@ func (d *i2cDevice) syscallIoctl(signal uintptr, payload unsafe.Pointer, address if err := d.openFileLazy(sender); err != nil { return err } + //nolint:gosec // TODO: fix later if _, _, errno := d.sys.syscall(Syscall_SYS_IOCTL, d.file, signal, payload, uint16(address)); errno != 0 { return fmt.Errorf("%s failed with syscall.Errno %v", sender, errno) } diff --git a/system/i2c_device_test.go b/system/i2c_device_test.go index 95725899d..bed618266 100644 --- a/system/i2c_device_test.go +++ b/system/i2c_device_test.go @@ -1,3 +1,4 @@ +//nolint:gosec // ok for test package system import ( diff --git a/system/pwmpin_sysfs.go b/system/pwmpin_sysfs.go index 859110498..4606717da 100644 --- a/system/pwmpin_sysfs.go +++ b/system/pwmpin_sysfs.go @@ -139,7 +139,7 @@ func (p *pwmPinSysFs) Period() (uint32, error) { if err != nil { return 0, fmt.Errorf(pwmPinErrorPattern, "Period", p.pin, err) } - + //nolint:gosec // TODO: fix later return uint32(val), nil } @@ -161,7 +161,7 @@ func (p *pwmPinSysFs) DutyCycle() (uint32, error) { if err != nil { return 0, fmt.Errorf(pwmPinErrorPattern, "DutyCycle", p.pin, err) } - + //nolint:gosec // TODO: fix later return uint32(val), err } diff --git a/utils.go b/utils.go index 36e58bb8d..485cb57d4 100644 --- a/utils.go +++ b/utils.go @@ -30,27 +30,27 @@ func After(t time.Duration, f func()) { time.AfterFunc(t, f) } -// Rand returns a positive random int up to max -func Rand(max int) int { - i, _ := rand.Int(rand.Reader, big.NewInt(int64(max))) +// Rand returns a positive random int up to maximum +func Rand(maximum int) int { + i, _ := rand.Int(rand.Reader, big.NewInt(int64(maximum))) return int(i.Int64()) } -// FromScale returns a converted input from min, max to 0.0...1.0. -func FromScale(input, min, max float64) float64 { - return (input - math.Min(min, max)) / (math.Max(min, max) - math.Min(min, max)) +// FromScale returns a converted input from minimum, maximum to 0.0...1.0. +func FromScale(input, minimum, maximum float64) float64 { + return (input - math.Min(minimum, maximum)) / (math.Max(minimum, maximum) - math.Min(minimum, maximum)) } -// ToScale returns a converted input from 0...1 to min...max scale. -// If input is less than min then ToScale returns min. -// If input is greater than max then ToScale returns max -func ToScale(input, min, max float64) float64 { - i := input*(math.Max(min, max)-math.Min(min, max)) + math.Min(min, max) +// ToScale returns a converted input from 0...1 to minimum...maximum scale. +// If input is less than minimum then ToScale returns minimum. +// If input is greater than maximum then ToScale returns maximum +func ToScale(input, minimum, maximum float64) float64 { + i := input*(math.Max(minimum, maximum)-math.Min(minimum, maximum)) + math.Min(minimum, maximum) switch { - case i < math.Min(min, max): - return math.Min(min, max) - case i > math.Max(min, max): - return math.Max(min, max) + case i < math.Min(minimum, maximum): + return math.Min(minimum, maximum) + case i > math.Max(minimum, maximum): + return math.Max(minimum, maximum) default: return i } From ab2cc0ffdfc954b9c9450aa8b613cbca384995ce Mon Sep 17 00:00:00 2001 From: Ron Evans Date: Tue, 5 Nov 2024 08:22:08 +0000 Subject: [PATCH 55/57] ble(module): update to 0.10 (#1084) --- go.mod | 14 +++-- go.sum | 51 +++++-------------- .../bleclient/ble_client_adaptor_test.go | 8 +-- platforms/bleclient/btwrapper.go | 2 +- platforms/bleclient/helpers_test.go | 15 +++--- 5 files changed, 36 insertions(+), 54 deletions(-) diff --git a/go.mod b/go.mod index e5283e041..2b9a38988 100644 --- a/go.mod +++ b/go.mod @@ -24,27 +24,31 @@ require ( golang.org/x/sys v0.26.0 periph.io/x/conn/v3 v3.7.1 periph.io/x/host/v3 v3.8.2 - tinygo.org/x/bluetooth v0.8.0 + tinygo.org/x/bluetooth v0.10.0 ) require ( github.com/creack/goselect v0.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/structs v1.1.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/klauspost/compress v1.17.11 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/muka/go-bluetooth v0.0.0-20240701044517-04c4f09c514e // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/saltosystems/winrt-go v0.0.0-20240110120258-ad49e9790c38 // indirect + github.com/saltosystems/winrt-go v0.0.0-20240509164145-4f7860a3bd2b // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/soypat/cyw43439 v0.0.0-20240609122733-da9153086796 // indirect + github.com/soypat/seqs v0.0.0-20240527012110-1201bab640ef // indirect github.com/tinygo-org/cbgo v0.0.4 // indirect + github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899 // indirect golang.org/x/crypto v0.28.0 // indirect - golang.org/x/sync v0.8.0 // indirect + golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 // indirect + golang.org/x/sync v0.7.0 // indirect + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d8bc81ebb..5084c6139 100644 --- a/go.sum +++ b/go.sum @@ -11,16 +11,12 @@ github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 h1:C7t6eeM github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw= github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o= github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -35,14 +31,11 @@ github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM80 github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/muka/go-bluetooth v0.0.0-20240701044517-04c4f09c514e h1:1Sc4DqlgszKejMkjydCSq8zOKmF+hr8odAl5JoBZ+ec= -github.com/muka/go-bluetooth v0.0.0-20240701044517-04c4f09c514e/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE= github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= @@ -53,67 +46,51 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY= github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo= -github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/saltosystems/winrt-go v0.0.0-20240110120258-ad49e9790c38 h1:YcsdT0vhLMBWScwoO9FHZdjcFqjIWfQENMzq0PNxODs= -github.com/saltosystems/winrt-go v0.0.0-20240110120258-ad49e9790c38/go.mod h1:CIltaIm7qaANUIvzr0Vmz71lmQMAIbGJ7cvgzX7FMfA= +github.com/saltosystems/winrt-go v0.0.0-20240509164145-4f7860a3bd2b h1:du3zG5fd8snsFN6RBoLA7fpaYV9ZQIsyH9snlk2Zvik= +github.com/saltosystems/winrt-go v0.0.0-20240509164145-4f7860a3bd2b/go.mod h1:CIltaIm7qaANUIvzr0Vmz71lmQMAIbGJ7cvgzX7FMfA= github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f h1:1R9KdKjCNSd7F8iGTxIpoID9prlYH8nuNYKt0XvweHA= github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f/go.mod h1:vQhwQ4meQEDfahT5kd61wLAF5AAeh5ZPLVI4JJ/tYo8= github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/soypat/cyw43439 v0.0.0-20240609122733-da9153086796 h1:1/r2URInjjFtWqT61gU7YGVCq3BRyXt/C7z4oLRF9Lo= +github.com/soypat/cyw43439 v0.0.0-20240609122733-da9153086796/go.mod h1:1Otjk6PRhfzfcVHeWMEeku/VntFqWghUwuSQyivb2vE= +github.com/soypat/seqs v0.0.0-20240527012110-1201bab640ef h1:phH95I9wANjTYw6bSYLZDQfNvao+HqYDom8owbNa0P4= +github.com/soypat/seqs v0.0.0-20240527012110-1201bab640ef/go.mod h1:oCVCNGCHMKoBj97Zp9znLbQ1nHxpkmOY9X+UAGzOxc8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/suapapa/go_eddystone v1.3.1/go.mod h1:bXC11TfJOS+3g3q/Uzd7FKd5g62STQEfeEIhcKe4Qy8= github.com/tinygo-org/cbgo v0.0.4 h1:3D76CRYbH03Rudi8sEgs/YO0x3JIMdyq8jlQtk/44fU= github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk= +github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899 h1:/DyaXDEWMqoVUVEJVJIlNk1bXTbFs8s3Q4GdPInSKTQ= +github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899/go.mod h1:LU7Dw00NJ+N86QkeTGjMLNkYcEYMor6wTDpTCu0EaH8= github.com/warthog618/go-gpiocdev v0.9.1 h1:pwHPaqjJfhCipIQl78V+O3l9OKHivdRDdmgXYbmhuCI= github.com/warthog618/go-gpiocdev v0.9.1/go.mod h1:dN3e3t/S2aSNC+hgigGE/dBW8jE1ONk9bDSEYfoPyl8= github.com/warthog618/go-gpiosim v0.1.1 h1:MRAEv+T+itmw+3GeIGpQJBfanUVyg0l3JCTwHtwdre4= github.com/warthog618/go-gpiosim v0.1.1/go.mod h1:YXsnB+I9jdCMY4YAlMSRrlts25ltjmuIsrnoUrBLdqU= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8= go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= gocv.io/x/gocv v0.39.0 h1:vWHupDE22LebZW6id2mVeT767j1YS8WqGt+ZiV7XJXE= gocv.io/x/gocv v0.39.0/go.mod h1:zYdWMj29WAEznM3Y8NsU3A0TRq/wR/cy75jeUypThqU= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 h1:/yRP+0AN7mf5DkD3BAI6TOFnd51gEoDEb8o35jIFtgw= +golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -124,5 +101,5 @@ periph.io/x/conn/v3 v3.7.1 h1:tMjNv3WO8jEz/ePuXl7y++2zYi8LsQ5otbmqGKy3Myg= periph.io/x/conn/v3 v3.7.1/go.mod h1:c+HCVjkzbf09XzcqZu/t+U8Ss/2QuJj0jgRF6Nye838= periph.io/x/host/v3 v3.8.2 h1:ayKUDzgUCN0g8+/xM9GTkWaOBhSLVcVHGTfjAOi8OsQ= periph.io/x/host/v3 v3.8.2/go.mod h1:yFL76AesNHR68PboofSWYaQTKmvPXsQH2Apvp/ls/K4= -tinygo.org/x/bluetooth v0.8.0 h1:WmuRebsODcUUIlGhesyuNRIAEIUCErhKlrZ9K9aimdI= -tinygo.org/x/bluetooth v0.8.0/go.mod h1:cfsVc0/nGo3nzi6+CeQaXb+anNlmEnSABkKsxer8OAE= +tinygo.org/x/bluetooth v0.10.0 h1:42n8qj2tuF5AfdbAUR2Nv45EhtVmbDFH6UoWnt6lzZQ= +tinygo.org/x/bluetooth v0.10.0/go.mod h1:t/Vm2a/rslsBoqFQKCBsWQw/cmRicQq+8Tl3tj5RCRI= diff --git a/platforms/bleclient/ble_client_adaptor_test.go b/platforms/bleclient/ble_client_adaptor_test.go index 614c6a04c..f95f9c375 100644 --- a/platforms/bleclient/ble_client_adaptor_test.go +++ b/platforms/bleclient/ble_client_adaptor_test.go @@ -38,7 +38,7 @@ func TestConnect(t *testing.T) { tests := map[string]struct { identifier string extAdapter *btTestAdapter - extDevice *btTestDevice + extDevice btTestDevice wantAddress string wantName string wantErr string @@ -50,7 +50,7 @@ func TestConnect(t *testing.T) { rssi: rssi, payload: &btTestPayload{name: deviceName}, }, - extDevice: &btTestDevice{}, + extDevice: btTestDevice{}, wantAddress: deviceAddress, wantName: deviceName, }, @@ -61,7 +61,7 @@ func TestConnect(t *testing.T) { rssi: rssi, payload: &btTestPayload{name: deviceName}, }, - extDevice: &btTestDevice{}, + extDevice: btTestDevice{}, wantAddress: deviceAddress, wantName: deviceName, }, @@ -122,7 +122,7 @@ func TestConnect(t *testing.T) { deviceAddress: deviceAddress, payload: &btTestPayload{name: "disco_err"}, }, - extDevice: &btTestDevice{ + extDevice: btTestDevice{ simulateDiscoverServicesErr: true, }, wantAddress: deviceAddress, diff --git a/platforms/bleclient/btwrapper.go b/platforms/bleclient/btwrapper.go index 011526a31..2072c1017 100644 --- a/platforms/bleclient/btwrapper.go +++ b/platforms/bleclient/btwrapper.go @@ -18,7 +18,7 @@ type bluetoothExtAdapterer interface { Enable() error Scan(callback func(*bluetooth.Adapter, bluetooth.ScanResult)) error StopScan() error - Connect(address bluetooth.Address, params bluetooth.ConnectionParams) (*bluetooth.Device, error) + Connect(address bluetooth.Address, params bluetooth.ConnectionParams) (bluetooth.Device, error) } type bluetoothExtCharacteristicer interface { diff --git a/platforms/bleclient/helpers_test.go b/platforms/bleclient/helpers_test.go index 459d9b412..39db09397 100644 --- a/platforms/bleclient/helpers_test.go +++ b/platforms/bleclient/helpers_test.go @@ -53,13 +53,12 @@ func (bta *btTestAdapter) StopScan() error { return nil } -func (bta *btTestAdapter) Connect(_ bluetooth.Address, _ bluetooth.ConnectionParams) (*bluetooth.Device, error) { +func (bta *btTestAdapter) Connect(addr bluetooth.Address, _ bluetooth.ConnectionParams) (bluetooth.Device, error) { if bta.simulateConnectErr { - return nil, fmt.Errorf("adapter connect error") + return bluetooth.Device{}, fmt.Errorf("adapter connect error") } - //nolint:nilnil // for this test we can not return a *bluetooth.Device - return nil, nil + return bluetooth.Device{Address: addr}, nil } type btTestPayload struct { @@ -72,14 +71,16 @@ func (*btTestPayload) HasServiceUUID(bluetooth.UUID) bool { return true } func (*btTestPayload) Bytes() []byte { return nil } -func (*btTestPayload) ManufacturerData() map[uint16][]byte { return nil } +func (*btTestPayload) ManufacturerData() []bluetooth.ManufacturerDataElement { return nil } + +func (*btTestPayload) ServiceData() []bluetooth.ServiceDataElement { return nil } type btTestDevice struct { simulateDiscoverServicesErr bool simulateDisconnectErr bool } -func (btd *btTestDevice) DiscoverServices(_ []bluetooth.UUID) ([]bluetooth.DeviceService, error) { +func (btd btTestDevice) DiscoverServices(_ []bluetooth.UUID) ([]bluetooth.DeviceService, error) { if btd.simulateDiscoverServicesErr { return nil, fmt.Errorf("device discover services error") } @@ -88,7 +89,7 @@ func (btd *btTestDevice) DiscoverServices(_ []bluetooth.UUID) ([]bluetooth.Devic return nil, nil } -func (btd *btTestDevice) Disconnect() error { +func (btd btTestDevice) Disconnect() error { if btd.simulateDisconnectErr { return fmt.Errorf("device disconnect error") } From 0d700b1b1da3f2303ede5f58fce1a91215343e2e Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 5 Nov 2024 10:25:52 +0100 Subject: [PATCH 56/57] firmata: try to stabilize tests (#1097) --- platforms/firmata/client/client_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/firmata/client/client_test.go b/platforms/firmata/client/client_test.go index c903b6374..27ecafe9e 100644 --- a/platforms/firmata/client/client_test.go +++ b/platforms/firmata/client/client_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" ) -const semPublishWait = 20 * time.Millisecond +const semPublishWait = 30 * time.Millisecond type readWriteCloser struct { id string From b5f5ac6dd8385562cfa1553140beade20268e7bd Mon Sep 17 00:00:00 2001 From: Thomas Kohler Date: Tue, 5 Nov 2024 10:35:56 +0100 Subject: [PATCH 57/57] docs(core): prepare for release v2.4.0 (#1095) --- .chglog/README.md | 8 ++++---- CHANGELOG.md | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/.chglog/README.md b/.chglog/README.md index 48f775df0..85aba2d24 100644 --- a/.chglog/README.md +++ b/.chglog/README.md @@ -8,7 +8,7 @@ It is possible to test the tool by `git-chglog --init` without overriding anythi ## Usage -Example for a new release "v2.3.0": +Example for a new release "v2.4.0": ```sh # optional update tool by: go install github.com/git-chglog/git-chglog/cmd/git-chglog@latest @@ -17,14 +17,14 @@ git pull git fetch --tags git checkout dev git pull upstream dev -git checkout -b rel/prepare_for_release_v230 -git-chglog --config .chglog/config_gobot.yml --no-case --next-tag v2.3.0 v2.2.0.. > .chglog/chglog_tmp.md +git checkout -b rel/prepare_for_release_v240 +git-chglog --config .chglog/config_gobot.yml --no-case --next-tag v2.4.0 v2.3.0.. > .chglog/chglog_tmp.md ``` ## Compare If unsure about any result of running git-chglog, just use: -`git log --since=2023-10-30 --pretty="- %s"` +`git log --since=2024-01-07 --pretty="- %s"` ## Manual adjustment diff --git a/CHANGELOG.md b/CHANGELOG.md index 45da52407..9a1389ef1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,51 @@ # CHANGELOG -## [Unreleased](https://github.com/hybridgroup/gobot/compare/v2.3.0...HEAD) +## [Unreleased](https://github.com/hybridgroup/gobot/compare/v2.4.0...HEAD) + +## [v2.4.0](https://github.com/hybridgroup/gobot/compare/v2.3.0...v2.4.0) (2024-11-05) + +### Bebop + +* fix concurrent map writes ([#1063](https://github.com/hybridgroup/gobot/issues/1063)) + +### Ble + +* add support for functional options, add tests ([#1059](https://github.com/hybridgroup/gobot/issues/1059)) +* introduce in drivers folder ([#1057](https://github.com/hybridgroup/gobot/issues/1057)) +* **client:** add scan timout ([#1051](https://github.com/hybridgroup/gobot/issues/1051)) +* **module:** update tinygo.org/x/bluetooth to v0.10 and adapt code ([#1084](https://github.com/hybridgroup/gobot/issues/1084)) + +### Build + +* **go, deps:** switch to Go 1.22 and update modules, linter v1.61.0 and adapt code ([#1093](https://github.com/hybridgroup/gobot/issues/1093),[#1092](https://github.com/hybridgroup/gobot/issues/1092)) +* **go, deps:** switch to Go 1.20 and update modules ([#1067](https://github.com/hybridgroup/gobot/issues/1067)) +* **linter:** update linter to v1.56.1 and fix issues ([#1068](https://github.com/hybridgroup/gobot/issues/1068)) + +### Doc + +* update links to release or tagged branch ([#1069](https://github.com/hybridgroup/gobot/issues/1069)) +* **core:** prepare for release v2.4.0 + +### Examples + +* fix missing checks of return values ([#1060](https://github.com/hybridgroup/gobot/issues/1060)) + +### Gobot + +* rename Master to Manager ([#1070](https://github.com/hybridgroup/gobot/issues/1070)) + +### Megapi + +* use serialport adaptor and move driver to drivers/serial ([#1062](https://github.com/hybridgroup/gobot/issues/1062)) + +### Neurosky + +* use serialport adaptor and move driver to drivers/serial ([#1061](https://github.com/hybridgroup/gobot/issues/1061)) + +### Test + +* try to stabilize eventer tests ([#1066](https://github.com/hybridgroup/gobot/issues/1066)) +* try to stabilize firmata tests ([#1097](https://github.com/hybridgroup/gobot/issues/1097)) ## [v2.3.0](https://github.com/hybridgroup/gobot/compare/v2.2.0...v2.3.0) (2024-01-06)