diff --git a/.circleci/config.yml b/.circleci/config.yml
index 681dcbfa9..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.19
+ - image: cimg/go:1.22
steps:
- checkout
- run:
@@ -31,7 +31,7 @@ jobs:
"test_platforms":
docker:
- - image: cimg/go:1.19
+ - image: cimg/go:1.22
steps:
- checkout
- run:
@@ -45,7 +45,7 @@ jobs:
"check_examples":
docker:
- - image: cimg/go:1.19
+ - image: cimg/go:1.22
steps:
- checkout
- run:
@@ -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.61.0
+ 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/.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 dd454656b..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.19'
+ 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.55.2
+ 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 cced8fe17..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++)
@@ -168,6 +163,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/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/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/Makefile b/Makefile
index e3c7883f0..faf3056f5 100644
--- a/Makefile
+++ b/Makefile
@@ -5,14 +5,14 @@ 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)
# 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) -tags libusb
# Run tests on nearly all directories without test cache
test:
@@ -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,libusb --disable forcetypeassert --disable noctx
else
go build -o /tmp/gobot_examples/$@ ./$@
endif
diff --git a/README.md b/README.md
index a9e48b4c4..dd3e18b34 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.
@@ -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)
+ }
}
```
@@ -101,11 +105,12 @@ 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")
+ adaptor := serialport.NewAdaptor("/dev/rfcomm0")
driver := sphero.NewSpheroDriver(adaptor)
work := func() {
@@ -120,7 +125,9 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
@@ -140,21 +147,27 @@ 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)
}
}
```
-### "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
@@ -166,18 +179,19 @@ 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/spherocommon"
+ "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)
- spheroDriver.SetName("Sphero" + port)
+ spheroAdaptor := serialport.NewAdaptor(port)
+ spheroDriver := sphero.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero" + port))
work := func() {
spheroDriver.Stop()
- spheroDriver.On(sphero.Collision, func(data interface{}) {
+ _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) {
fmt.Println("Collision Detected!")
})
@@ -202,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",
@@ -213,10 +227,12 @@ func main() {
}
for _, port := range spheros {
- master.AddRobot(NewSwarmBot(port))
+ manager.AddRobot(NewSwarmBot(port))
}
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
```
@@ -225,51 +241,83 @@ 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/ble)
-- [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)
-- [Sphero](http://www.sphero.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/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:
-
-- [GPIO](https://en.wikipedia.org/wiki/General_Purpose_Input/Output) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/gpio)
+- [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/blob/release/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/blob/release/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/blob/release/drivers/gpio)
- AIP1640 LED Dot Matrix/7 Segment Controller
- Button
- Buzzer
@@ -294,24 +342,10 @@ 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:
+Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of drivers provided using
+the `gobot/drivers/i2c` 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:
-
-- [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
@@ -351,10 +385,18 @@ 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/blob/release/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:
-- [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
@@ -366,8 +408,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
@@ -376,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()
@@ -413,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/adaptor.go b/adaptor.go
index 5456136f7..cb66b8315 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(data []byte)) error
+ WithoutResponses(use bool)
+}
+
// Porter is the interface that describes an adaptor's port
type Porter interface {
Port() string
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/basic_auth.go b/api/basic_auth.go
index 698a00657..0548dda39 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)),
@@ -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/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/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..633a086e0 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,81 +59,90 @@ 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)
}
}
-# 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()
+# Manager Gobot
+
+Finally, you can use Manager 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/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 := sphero.NewSpheroDriver(spheroAdaptor, serial.WithName("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() {
+ manager := gobot.NewManager()
+ api.NewAPI(manager).Start()
+
+ spheros := []string{
+ "/dev/rfcomm0",
+ "/dev/rfcomm1",
+ "/dev/rfcomm2",
+ "/dev/rfcomm3",
+ }
+
+ for _, port := range spheros {
+ manager.AddRobot(NewSwarmBot(port))
+ }
+
+ if err := manager.Start(); err != nil {
+ panic(err)
}
+ }
Copyright (c) 2013-2018 The Hybrid Group. Licensed under the Apache 2.0 license.
*/
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
new file mode 100644
index 000000000..2eb43e50c
--- /dev/null
+++ b/drivers/MIGRATION.md
@@ -0,0 +1,367 @@
+# 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 drivers are listed
+here and a migration strategy is provided.
+
+## Switch from version 2.3.0 (ble and sphero adaptors affected)
+
+### 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])
+...
+```
+
+### 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
+needs to be adjusted. In addition all events now have a suffix "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/spherocommon"
+ "gobot.io/x/gobot/v2/drivers/serial"
+ "gobot.io/x/gobot/v2/platforms/serialport"
+ ...
+)
+...
+ adaptor := serialport.NewAdaptor("/dev/rfcomm0")
+ spheroDriver := sphero.NewSpheroDriver(adaptor)
+...
+ _ = spheroDriver.On(sphero.CollisionEvent, func(data interface{}) {
+...
+```
+
+### Neurosky adaptor split off
+
+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
+// 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{}) {
+...
+```
+
+### 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"
+
+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))
+```
+
+### 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.
+
+```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"))
+```
+
+### gpio.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())
+```
+
+### 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.
+
+```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())
+```
+
+### gpio.HD44780Driver: make 'SetRWPin()' an option
+
+```go
+// old
+d := gpio.NewHD44780Driver(adaptor, ...)
+d.SetRWPin("10")
+
+// new
+d := gpio.NewHD44780Driver(adaptor, ..., gpio.WithHD44780RWPin("10"))
+```
+
+### gpio.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()
+```
+
+### gpio.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/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/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/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.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/aio/temperature_sensor_driver_test.go b/drivers/aio/temperature_sensor_driver_test.go
index 0b9d2b3d5..a1662c1bb 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,25 +177,26 @@ 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")
}
}
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):
- 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/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..9ce222c9c
--- /dev/null
+++ b/drivers/ble/battery_driver.go
@@ -0,0 +1,37 @@
+package ble
+
+import (
+ "bytes"
+
+ "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, opts ...OptionApplier) *BatteryDriver {
+ d := &BatteryDriver{
+ Driver: NewDriver(a, "Battery", nil, nil, opts...),
+ Eventer: gobot.NewEventer(),
+ }
+
+ return d
+}
+
+// GetBatteryLevel reads and returns the current battery level
+func (d *BatteryDriver) GetBatteryLevel() (uint8, error) {
+ c, err := d.Adaptor().ReadCharacteristic(batteryCharaShort)
+ if err != nil {
+ return 0, err
+ }
+ buf := bytes.NewBuffer(c)
+ val, _ := buf.ReadByte()
+ level := val
+ return level, nil
+}
diff --git a/drivers/ble/battery_driver_test.go b/drivers/ble/battery_driver_test.go
new file mode 100644
index 000000000..9fe9f5f63
--- /dev/null
+++ b/drivers/ble/battery_driver_test.go
@@ -0,0 +1,52 @@
+package ble
+
+import (
+ "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 = (*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) {
+ if cUUID == "2a19" {
+ return []byte{20}, nil
+ }
+
+ return nil, nil
+ })
+ // 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
new file mode 100644
index 000000000..3634cbe8a
--- /dev/null
+++ b/drivers/ble/ble_driver.go
@@ -0,0 +1,126 @@
+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,
+ opts ...OptionApplier,
+) *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{},
+ }
+
+ 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 {
+ 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 [ble.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..14cf1dbbd
--- /dev/null
+++ b/drivers/ble/ble_driver_test.go
@@ -0,0 +1,100 @@
+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 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"
+ 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")
+}
+
+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
new file mode 100644
index 000000000..ef6949df7
--- /dev/null
+++ b/drivers/ble/device_information_driver.go
@@ -0,0 +1,86 @@
+package ble
+
+import (
+ "bytes"
+
+ "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, opts ...OptionApplier) *DeviceInformationDriver {
+ n := &DeviceInformationDriver{
+ Driver: NewDriver(a, "DeviceInformation", nil, nil, opts...),
+ Eventer: gobot.NewEventer(),
+ }
+
+ return n
+}
+
+// GetModelNumber returns the model number for the BLE Peripheral
+func (d *DeviceInformationDriver) GetModelNumber() (string, error) {
+ c, err := d.Adaptor().ReadCharacteristic(deviceInformationModelNumberCharaShort)
+ if err != nil {
+ return "", err
+ }
+ buf := bytes.NewBuffer(c)
+ model := buf.String()
+ return model, nil
+}
+
+// GetFirmwareRevision returns the firmware revision for the BLE Peripheral
+func (d *DeviceInformationDriver) GetFirmwareRevision() (string, error) {
+ c, err := d.Adaptor().ReadCharacteristic(deviceInformationFirmwareRevisionCharaShort)
+ if err != nil {
+ return "", err
+ }
+ buf := bytes.NewBuffer(c)
+ val := buf.String()
+ return val, nil
+}
+
+// GetHardwareRevision returns the hardware revision for the BLE Peripheral
+func (d *DeviceInformationDriver) GetHardwareRevision() (string, error) {
+ c, err := d.Adaptor().ReadCharacteristic(deviceInformationHardwareRevisionCharaShort)
+ if err != nil {
+ return "", err
+ }
+ buf := bytes.NewBuffer(c)
+ val := buf.String()
+ return val, nil
+}
+
+// GetManufacturerName returns the manufacturer name for the BLE Peripheral
+func (d *DeviceInformationDriver) GetManufacturerName() (string, error) {
+ c, err := d.Adaptor().ReadCharacteristic(deviceInformationManufacturerNameCharaShort)
+ if err != nil {
+ return "", err
+ }
+ buf := bytes.NewBuffer(c)
+ val := buf.String()
+ return val, nil
+}
+
+// GetPnPId returns the PnP ID for the BLE Peripheral
+func (d *DeviceInformationDriver) GetPnPId() (string, error) {
+ c, err := d.Adaptor().ReadCharacteristic(deviceInformationPnPIdCharaShort)
+ if err != nil {
+ return "", err
+ }
+ buf := bytes.NewBuffer(c)
+ val := buf.String()
+ return val, nil
+}
diff --git a/drivers/ble/device_information_driver_test.go b/drivers/ble/device_information_driver_test.go
new file mode 100644
index 000000000..38f362b5b
--- /dev/null
+++ b/drivers/ble/device_information_driver_test.go
@@ -0,0 +1,84 @@
+package ble
+
+import (
+ "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 = (*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())
+ // 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())
+ // 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())
+ // 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())
+ // 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())
+ // act
+ pid, err := d.GetPnPId()
+ // assert
+ require.NoError(t, err)
+ assert.Equal(t, "2a50", pid)
+}
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 62%
rename from platforms/ble/generic_access_driver.go
rename to drivers/ble/generic_access_driver.go
index 3b3f40c08..cdf89a298 100644
--- a/platforms/ble/generic_access_driver.go
+++ b/drivers/ble/generic_access_driver.go
@@ -3,78 +3,57 @@ package ble
import (
"bytes"
"encoding/binary"
- "log"
"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, opts ...OptionApplier) *GenericAccessDriver {
+ d := &GenericAccessDriver{
+ Driver: NewDriver(a, "GenericAccess", nil, nil, opts...),
+ 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, 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 (b *GenericAccessDriver) GetAppearance() string {
- c, err := b.adaptor().ReadCharacteristic("2a01")
+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
new file mode 100644
index 000000000..50d7a65c5
--- /dev/null
+++ b/drivers/ble/generic_access_driver_test.go
@@ -0,0 +1,61 @@
+package ble
+
+import (
+ "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 = (*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())
+ // 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) {
+ if cUUID == "2a01" {
+ return []byte{128, 0}, nil
+ }
+ return nil, nil
+ })
+ // act
+ app, err := d.GetAppearance()
+ // assert
+ require.NoError(t, err)
+ assert.Equal(t, "Generic Computer", app)
+}
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..9ffe4c732
--- /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, opts ...ble.OptionApplier) *AccelerometerDriver {
+ d := &AccelerometerDriver{
+ Eventer: gobot.NewEventer(),
+ }
+ d.Driver = ble.NewDriver(a, "Microbit Accelerometer", d.initialize, nil, opts...)
+
+ 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) {
+ 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/drivers/ble/microbit/accelerometer_driver_test.go b/drivers/ble/microbit/accelerometer_driver_test.go
new file mode 100644
index 000000000..e783a7bc4
--- /dev/null
+++ b/drivers/ble/microbit/accelerometer_driver_test.go
@@ -0,0 +1,66 @@
+//nolint:forcetypeassert,dupl // ok here
+package microbit
+
+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/ble"
+ "gobot.io/x/gobot/v2/drivers/ble/testutil"
+)
+
+var _ gobot.Driver = (*AccelerometerDriver)(nil)
+
+func TestNewAccelerometerDriver(t *testing.T) {
+ d := NewAccelerometerDriver(testutil.NewBleTestAdaptor())
+ assert.IsType(t, &AccelerometerDriver{}, d)
+ assert.True(t, strings.HasPrefix(d.Name(), "Microbit Accelerometer"))
+ 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())
+ require.NoError(t, d.Halt())
+}
+
+func TestAccelerometerReadData(t *testing.T) {
+ sem := make(chan bool)
+ a := testutil.NewBleTestAdaptor()
+ d := NewAccelerometerDriver(a)
+ 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
+ })
+
+ require.NoError(t, err)
+
+ a.SendTestDataToSubscriber([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24})
+
+ select {
+ case <-sem:
+ case <-time.After(100 * time.Millisecond):
+ require.Fail(t, "Microbit Event \"Accelerometer\" was not published")
+ }
+}
diff --git a/drivers/ble/microbit/button_driver.go b/drivers/ble/microbit/button_driver.go
new file mode 100644
index 000000000..e0b2c7bbb
--- /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, opts ...ble.OptionApplier) *ButtonDriver {
+ d := &ButtonDriver{
+ Eventer: gobot.NewEventer(),
+ }
+
+ d.Driver = ble.NewDriver(a, "Microbit Button", d.initialize, nil, opts...)
+
+ 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) {
+ d.Publish(d.Event(ButtonAEvent), data)
+ }); err != nil {
+ return err
+ }
+
+ // subscribe to button B notifications
+ 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
new file mode 100644
index 000000000..d5d44de16
--- /dev/null
+++ b/drivers/ble/microbit/button_driver_test.go
@@ -0,0 +1,61 @@
+package microbit
+
+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/ble"
+ "gobot.io/x/gobot/v2/drivers/ble/testutil"
+)
+
+var _ gobot.Driver = (*ButtonDriver)(nil)
+
+func TestNewButtonDriver(t *testing.T) {
+ d := NewButtonDriver(testutil.NewBleTestAdaptor())
+ assert.IsType(t, &ButtonDriver{}, d)
+ assert.True(t, strings.HasPrefix(d.Name(), "Microbit Button"))
+ 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())
+ require.NoError(t, d.Halt())
+}
+
+func TestButtonReadData(t *testing.T) {
+ sem := make(chan bool)
+ a := testutil.NewBleTestAdaptor()
+ d := NewButtonDriver(a)
+ require.NoError(t, d.Start())
+
+ err := d.On("buttonB", func(data interface{}) {
+ sem <- true
+ })
+ require.NoError(t, err)
+
+ a.SendTestDataToSubscriber([]byte{1})
+
+ select {
+ case <-sem:
+ case <-time.After(100 * time.Millisecond):
+ require.Fail(t, "Microbit Event \"ButtonB\" was not published")
+ }
+}
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..bcf76bd76
--- /dev/null
+++ b/drivers/ble/microbit/io_pin_driver.go
@@ -0,0 +1,256 @@
+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, opts ...ble.OptionApplier) *IOPinDriver {
+ d := &IOPinDriver{
+ Eventer: gobot.NewEventer(),
+ }
+
+ d.Driver = ble.NewDriver(a, "Microbit IO Pins", d.initialize, nil, opts...)
+
+ 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) //nolint:gosec // ok here
+ }
+
+ 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{}
+ //nolint:gosec // TODO: fix later
+ 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) //nolint:gosec // ok here
+ }
+
+ 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{}
+ //nolint:gosec // TODO: fix later
+ 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 {
+ //nolint:gosec // TODO: fix later
+ 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 {
+ //nolint:gosec // TODO: fix later
+ 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 {
+ //nolint:gosec // TODO: fix later
+ 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 {
+ //nolint:gosec // TODO: fix later
+ if bit.IsSet(d.ioMask, uint8(pin)) {
+ return d.WritePinIOConfig(bit.Clear(d.ioMask, uint8(pin))) //nolint:gosec // TODO: fix later
+ }
+
+ 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..3bdce9f1e
--- /dev/null
+++ b/drivers/ble/microbit/io_pin_driver_test.go
@@ -0,0 +1,178 @@
+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"
+ "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 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)
+ 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..7116c4671 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, opts ...ble.OptionApplier) *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, opts...)
-// 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/drivers/ble/microbit/led_driver_test.go b/drivers/ble/microbit/led_driver_test.go
new file mode 100644
index 000000000..a3ea15b55
--- /dev/null
+++ b/drivers/ble/microbit/led_driver_test.go
@@ -0,0 +1,62 @@
+package microbit
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "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"
+)
+
+var _ gobot.Driver = (*LEDDriver)(nil)
+
+func initTestLEDDriver() *LEDDriver {
+ d := NewLEDDriver(testutil.NewBleTestAdaptor())
+ return d
+}
+
+func TestNewLEDDriver(t *testing.T) {
+ d := NewLEDDriver(testutil.NewBleTestAdaptor())
+ assert.IsType(t, &LEDDriver{}, d)
+ assert.True(t, strings.HasPrefix(d.Name(), "Microbit LED"))
+ 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}))
+}
+
+func TestLEDWriteText(t *testing.T) {
+ d := initTestLEDDriver()
+ require.NoError(t, d.WriteText("Hello"))
+}
+
+func TestLEDCommands(t *testing.T) {
+ d := initTestLEDDriver()
+ 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/drivers/ble/microbit/magnetometer_driver.go b/drivers/ble/microbit/magnetometer_driver.go
new file mode 100644
index 000000000..630762210
--- /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, opts ...ble.OptionApplier) *MagnetometerDriver {
+ d := &MagnetometerDriver{
+ Eventer: gobot.NewEventer(),
+ }
+ d.Driver = ble.NewDriver(a, "Microbit Magnetometer", d.initialize, nil, opts...)
+
+ 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) {
+ 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/drivers/ble/microbit/magnetometer_driver_test.go b/drivers/ble/microbit/magnetometer_driver_test.go
new file mode 100644
index 000000000..8f14dc8ca
--- /dev/null
+++ b/drivers/ble/microbit/magnetometer_driver_test.go
@@ -0,0 +1,69 @@
+//nolint:forcetypeassert,dupl // ok here
+package microbit
+
+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/ble"
+ "gobot.io/x/gobot/v2/drivers/ble/testutil"
+)
+
+var _ gobot.Driver = (*MagnetometerDriver)(nil)
+
+func initTestMagnetometerDriver() *MagnetometerDriver {
+ d := NewMagnetometerDriver(testutil.NewBleTestAdaptor())
+ return d
+}
+
+func TestMagnetometerDriver(t *testing.T) {
+ d := NewMagnetometerDriver(testutil.NewBleTestAdaptor())
+ assert.IsType(t, &MagnetometerDriver{}, d)
+ assert.True(t, strings.HasPrefix(d.Name(), "Microbit Magnetometer"))
+ 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())
+ require.NoError(t, d.Halt())
+}
+
+func TestMagnetometerReadData(t *testing.T) {
+ sem := make(chan bool)
+ a := testutil.NewBleTestAdaptor()
+ d := NewMagnetometerDriver(a)
+ 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.SendTestDataToSubscriber([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24})
+
+ select {
+ case <-sem:
+ case <-time.After(100 * time.Millisecond):
+ require.Fail(t, "Microbit Event \"Magnetometer\" was not published")
+ }
+}
diff --git a/drivers/ble/microbit/temperature_driver.go b/drivers/ble/microbit/temperature_driver.go
new file mode 100644
index 000000000..5e86a3249
--- /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, opts ...ble.OptionApplier) *TemperatureDriver {
+ d := &TemperatureDriver{
+ Eventer: gobot.NewEventer(),
+ }
+ d.Driver = ble.NewDriver(a, "Microbit Temperature", d.initialize, nil, opts...)
+
+ 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) {
+ var l int8
+ buf := bytes.NewBuffer(data)
+ val, _ := buf.ReadByte()
+ l = int8(val)
+
+ d.Publish(d.Event(TemperatureEvent), l)
+ })
+}
diff --git a/drivers/ble/microbit/temperature_driver_test.go b/drivers/ble/microbit/temperature_driver_test.go
new file mode 100644
index 000000000..ca49650ab
--- /dev/null
+++ b/drivers/ble/microbit/temperature_driver_test.go
@@ -0,0 +1,66 @@
+package microbit
+
+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/ble"
+ "gobot.io/x/gobot/v2/drivers/ble/testutil"
+)
+
+var _ gobot.Driver = (*TemperatureDriver)(nil)
+
+func initTestTemperatureDriver() *TemperatureDriver {
+ d := NewTemperatureDriver(testutil.NewBleTestAdaptor())
+ return d
+}
+
+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())
+ require.NoError(t, d.Halt())
+}
+
+func TestTemperatureReadData(t *testing.T) {
+ sem := make(chan bool)
+ a := testutil.NewBleTestAdaptor()
+ d := NewTemperatureDriver(a)
+ 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.SendTestDataToSubscriber([]byte{0x22})
+
+ select {
+ case <-sem:
+ case <-time.After(100 * time.Millisecond):
+ require.Fail(t, "Microbit Event \"Temperature\" was not published")
+ }
+}
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..4dee03ef5
--- /dev/null
+++ b/drivers/ble/parrot/minidrone_driver.go
@@ -0,0 +1,509 @@
+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, opts ...ble.OptionApplier) *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, opts...)
+
+ 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) {
+ 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) {
+ 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)
+ }
+ //nolint:gosec // TODO: fix later
+ 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)
+ }
+ //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)
+ }
+ 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 74%
rename from platforms/parrot/minidrone/minidrone_driver_test.go
rename to drivers/ble/parrot/minidrone_driver_test.go
index cd6bb4e06..add322d30 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,123 @@ 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"
)
-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 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 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 +133,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 +165,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..86aefe28c
--- /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, opts ...OptionApplier) *SerialPortDriver {
+ d := &SerialPortDriver{
+ Driver: NewDriver(a, "BleSerial", nil, nil, opts...),
+ 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) {
+ 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..9b2df6316
--- /dev/null
+++ b/drivers/ble/serial_port_test.go
@@ -0,0 +1,208 @@
+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"
+)
+
+var _ gobot.Driver = (*SerialPortDriver)(nil)
+
+var _ io.ReadWriteCloser = (*SerialPortDriver)(nil)
+
+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/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..7a75f9964
--- /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/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/ble/sphero/sphero_bb8_driver.go b/drivers/ble/sphero/sphero_bb8_driver.go
new file mode 100644
index 000000000..022359ac6
--- /dev/null
+++ b/drivers/ble/sphero/sphero_bb8_driver.go
@@ -0,0 +1,29 @@
+package sphero
+
+import (
+ "gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/drivers/ble"
+ "gobot.io/x/gobot/v2/drivers/common/spherocommon"
+)
+
+// BB8Driver represents a Sphero BB-8
+type BB8Driver struct {
+ *OllieDriver
+}
+
+// NewBB8Driver creates a driver for a Sphero BB-8
+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
+func bb8DefaultCollisionConfig() spherocommon.CollisionConfig {
+ return spherocommon.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..145c9c41e
--- /dev/null
+++ b/drivers/ble/sphero/sphero_bb8_driver_test.go
@@ -0,0 +1,34 @@
+package sphero
+
+import (
+ "strings"
+ "testing"
+
+ "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"
+)
+
+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())
+}
+
+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
new file mode 100644
index 000000000..a2dfcb54d
--- /dev/null
+++ b/drivers/ble/sphero/sphero_ollie_driver.go
@@ -0,0 +1,450 @@
+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/spherocommon"
+)
+
+// 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 spherocommon.CollisionConfig
+ seq uint8
+ collisionResponse []uint8
+ packetChannel chan *packet
+ asyncBuffer []byte
+ asyncMessage []byte
+ locatorCallback func(p Point2D)
+ powerstateCallback func(p spherocommon.PowerStatePacket)
+}
+
+// NewOllieDriver creates a driver for a Sphero Ollie
+func NewOllieDriver(a gobot.BLEConnector, opts ...ble.OptionApplier) *OllieDriver {
+ return newOllieBaseDriver(a, "Ollie", ollieDefaultCollisionConfig(), opts...)
+}
+
+func newOllieBaseDriver(
+ a gobot.BLEConnector, name string,
+ dcc spherocommon.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, opts...)
+
+ d.AddEvent(spherocommon.ErrorEvent)
+ d.AddEvent(spherocommon.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 spherocommon.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 spherocommon.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) {
+ //nolint:gosec // TODO: fix later
+ 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 spherocommon.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(spherocommon.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) {
+ // 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 spherocommon.DataStreamingPacket
+ buffer := bytes.NewBuffer(data[5:]) // skip header
+ if err := binary.Read(buffer, binary.BigEndian, &dataPacket); err != nil {
+ panic(err)
+ }
+
+ d.Publish(spherocommon.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) //nolint:gosec // ok here
+ } else {
+ x = int16(ux)
+ }
+
+ if uy > 32255 {
+ y = int16(uy - 65535) //nolint:gosec // ok here
+ } else {
+ y = int16(uy)
+ }
+
+ d.locatorCallback(Point2D{X: x, Y: y})
+}
+
+func (d *OllieDriver) handlePowerStateDetected(data []uint8) {
+ var dataPacket spherocommon.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 != spherocommon.CalculateChecksum(d.collisionResponse[2:size-1]) {
+ return
+ }
+
+ 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(spherocommon.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)} //nolint:gosec // TODO: fix later
+ buf := append(hdr, body...)
+
+ packet := &packet{
+ body: body,
+ header: hdr,
+ checksum: spherocommon.CalculateChecksum(buf[2:]),
+ }
+
+ return packet
+}
+
+// ollieDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults
+func ollieDefaultCollisionConfig() spherocommon.CollisionConfig {
+ return spherocommon.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 53%
rename from platforms/sphero/ollie/ollie_driver_test.go
rename to drivers/ble/sphero/sphero_ollie_driver_test.go
index b736c0d82..1c06021d0 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,39 @@ 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"
+ "gobot.io/x/gobot/v2/drivers/ble/testutil"
+ "gobot.io/x/gobot/v2/drivers/common/spherocommon"
)
-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 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 TestOllieDriverStartAndHalt(t *testing.T) {
+func TestOllieStartAndHalt(t *testing.T) {
d := initTestOllieDriver()
require.NoError(t, d.Start())
require.NoError(t, d.Halt())
@@ -60,22 +75,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)
}
}
func TestDataStreaming(t *testing.T) {
d := initTestOllieDriver()
- _ = d.SetDataStreamingConfig(sphero.DefaultDataStreamingConfig())
+ err := d.SetDataStreamingConfig(spherocommon.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.(spherocommon.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 +107,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)
}
// 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
new file mode 100644
index 000000000..4748b3ec6
--- /dev/null
+++ b/drivers/ble/sphero/sphero_sprkplus_driver.go
@@ -0,0 +1,29 @@
+package sphero
+
+import (
+ "gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/drivers/ble"
+ "gobot.io/x/gobot/v2/drivers/common/spherocommon"
+)
+
+// SPRKPlusDriver represents a Sphero SPRK+
+type SPRKPlusDriver struct {
+ *OllieDriver
+}
+
+// NewSPRKPlusDriver creates a driver for a Sphero SPRK+
+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
+func sprkplusDefaultCollisionConfig() spherocommon.CollisionConfig {
+ return spherocommon.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..ed74f2d85
--- /dev/null
+++ b/drivers/ble/sphero/sphero_sprkplus_driver_test.go
@@ -0,0 +1,34 @@
+package sphero
+
+import (
+ "strings"
+ "testing"
+
+ "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"
+)
+
+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())
+}
+
+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
new file mode 100644
index 000000000..58f8e558e
--- /dev/null
+++ b/drivers/ble/testutil/testutil.go
@@ -0,0 +1,114 @@
+package testutil
+
+import (
+ "fmt"
+ "sync"
+
+ "gobot.io/x/gobot/v2"
+)
+
+var _ gobot.BLEConnector = (*bleTestClientAdaptor)(nil)
+
+type bleTestClientAdaptor struct {
+ name string
+ address string
+ mtx sync.Mutex
+ withoutResponses bool
+
+ simulateConnectErr bool
+ simulateSubscribeErr bool
+ simulateDisconnectErr bool
+ readCharacteristicFunc func(string) ([]byte, error)
+ writeCharacteristicFunc func(string, []byte) error
+ subscribeFunc func([]byte)
+ subscribeCharaUUID string
+}
+
+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) SubscribeCharaUUID() string {
+ return t.subscribeCharaUUID
+}
+
+func (t *bleTestClientAdaptor) SetReadCharacteristicTestFunc(f func(cUUID string) (data []byte, err error)) {
+ t.mtx.Lock()
+ defer t.mtx.Unlock()
+ t.readCharacteristicFunc = f
+}
+
+func (t *bleTestClientAdaptor) SetWriteCharacteristicTestFunc(f func(cUUID string, data []byte) error) {
+ t.mtx.Lock()
+ defer t.mtx.Unlock()
+ t.writeCharacteristicFunc = f
+}
+
+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)
+}
+
+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) 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.readCharacteristicFunc(cUUID)
+}
+
+func (t *bleTestClientAdaptor) WriteCharacteristic(cUUID string, data []byte) error {
+ t.mtx.Lock()
+ defer t.mtx.Unlock()
+ return t.writeCharacteristicFunc(cUUID, data)
+}
+
+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/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/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
new file mode 100644
index 000000000..843166825
--- /dev/null
+++ b/drivers/common/spherocommon/spherocommon.go
@@ -0,0 +1,33 @@
+package spherocommon
+
+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)) //nolint:gosec // TODO: fix later
+}
diff --git a/platforms/sphero/sphero_packets.go b/drivers/common/spherocommon/spherocommon_packets.go
similarity index 80%
rename from platforms/sphero/sphero_packets.go
rename to drivers/common/spherocommon/spherocommon_packets.go
index 33b17c9e8..d06d08469 100644
--- a/platforms/sphero/sphero_packets.go
+++ b/drivers/common/spherocommon/spherocommon_packets.go
@@ -1,17 +1,8 @@
-package sphero
-
-// DefaultLocatorConfig returns a LocatorConfig with defaults
-func DefaultLocatorConfig() LocatorConfig {
- return LocatorConfig{
- Flags: 0x01,
- X: 0x00,
- Y: 0x00,
- YawTare: 0x00,
- }
-}
+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
@@ -24,21 +15,9 @@ 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.
+// 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.
@@ -60,35 +39,9 @@ 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
+// 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
@@ -102,6 +55,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/common/spherocommon/spherocommon_test.go b/drivers/common/spherocommon/spherocommon_test.go
new file mode 100644
index 000000000..3ee8b2a82
--- /dev/null
+++ b/drivers/common/spherocommon/spherocommon_test.go
@@ -0,0 +1,24 @@
+package spherocommon
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+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 {
+ require.Fail(t, "Expected %x, got %x for data %x.", tt.checksum, actual, tt.data)
+ }
+ }
+}
diff --git a/drivers/gpio/MIGRATION.md b/drivers/gpio/MIGRATION.md
deleted file mode 100644
index c493e1b4a..000000000
--- a/drivers/gpio/MIGRATION.md
+++ /dev/null
@@ -1,195 +0,0 @@
-# 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/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/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/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/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/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/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/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/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/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/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/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.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/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/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/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/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.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/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/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/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_connection.go b/drivers/i2c/i2c_connection.go
index 3f402a8d3..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
@@ -110,25 +110,12 @@ 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 {
result -= 1 << 16
}
- return int16(result)
+ return int16(result) //nolint:gosec // ok here
}
func swapBytes(value uint16) uint16 {
diff --git a/drivers/i2c/i2c_connection_test.go b/drivers/i2c/i2c_connection_test.go
index fdce313d2..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
}
@@ -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/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/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/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/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.go b/drivers/i2c/mcp23017_driver.go
index d54abee76..80def1220 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
@@ -272,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
}
}
@@ -289,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
}
}
@@ -322,10 +323,10 @@ func (m *MCP23017Driver) write(reg uint8, pin uint8, state bitState) error {
}
var val uint8
- if state == clear {
- val = clearBit(valOrg, pin)
+ if state == clearBit {
+ val = uint8(bit.Clear(int(valOrg), pin)) //nolint:gosec // TODO: fix later
} else {
- val = setBit(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 5723c46d8..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 (
@@ -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..01d1c7ed4 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"))
@@ -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/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.go b/drivers/i2c/pca9501_driver.go
index daa7da583..b68730b2e 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)) //nolint:gosec // TODO: fix later
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)) //nolint:gosec // TODO: fix later
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)) //nolint:gosec // TODO: fix later
if err != nil {
return 0, err
}
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/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/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.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/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.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/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.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/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.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/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/veml7700_driver.go b/drivers/i2c/veml7700_driver.go
new file mode 100644
index 000000000..769a02041
--- /dev/null
+++ b/drivers/i2c/veml7700_driver.go
@@ -0,0 +1,143 @@
+package i2c
+
+const (
+ defaultVEML7700Address = 0x10
+)
+
+const (
+ ALS_GAIN_1 = 0x0
+ ALS_GAIN_2 = 0x1
+ ALS_GAIN_1_4 = 0x3
+ ALS_GAIN_1_8 = 0x2
+)
+
+const (
+ ALS_25MS = 0xC
+ ALS_50MS = 0x8
+ ALS_100MS = 0x0
+ ALS_200MS = 0x1
+ ALS_400MS = 0x2
+ ALS_800MS = 0x3
+)
+
+type VEML7700Driver struct {
+ *Driver
+ gain byte
+ integrationTime byte
+}
+
+func NewVEML7700Driver(c Connector, options ...func(Config)) *VEML7700Driver {
+ v := &VEML7700Driver{
+ Driver: NewDriver(c, "VEML7700", defaultVEML7700Address),
+ }
+ v.afterStart = v.initialize
+
+ for _, option := range options {
+ option(v)
+ }
+
+ return v
+}
+
+func (v *VEML7700Driver) initialize() error {
+ if err := v.setGain(ALS_GAIN_1_8); err != nil {
+ return err
+ }
+ if err := v.setIntegrationTime(ALS_100MS); err != nil {
+ return err
+ }
+ return v.setShutdown(false)
+}
+
+func (v *VEML7700Driver) ReadRawLight() (uint16, error) {
+ buf := make([]byte, 2)
+ if err := v.connection.ReadBlockData(0x04, buf); err != nil {
+ return 0, err
+ }
+ return uint16(buf[0]) | (uint16(buf[1]) << 8), nil
+}
+
+func (v *VEML7700Driver) ReadRawWhite() (uint16, error) {
+ buf := make([]byte, 2)
+ if err := v.connection.ReadBlockData(0x05, buf); err != nil {
+ return 0, err
+ }
+ return uint16(buf[0]) | (uint16(buf[1]) << 8), nil
+}
+
+func (v *VEML7700Driver) setShutdown(state bool) error {
+ var shutdown byte
+ if state {
+ shutdown = 1
+ } else {
+ shutdown = 0
+ }
+ return v.connection.WriteBlockData(0x00, []byte{shutdown})
+}
+
+func (v *VEML7700Driver) setGain(gain byte) error {
+ v.gain = gain
+ return v.connection.WriteBlockData(0x00, []byte{gain})
+}
+
+func (v *VEML7700Driver) setIntegrationTime(integrationTime byte) error {
+ v.integrationTime = integrationTime
+ return v.connection.WriteBlockData(0x00, []byte{integrationTime})
+}
+
+func (v *VEML7700Driver) GainValue() float64 {
+ switch v.gain {
+ case ALS_GAIN_2:
+ return 2.0
+ case ALS_GAIN_1:
+ return 1.0
+ case ALS_GAIN_1_4:
+ return 0.25
+ case ALS_GAIN_1_8:
+ return 0.125
+ default:
+ return 1.0
+ }
+}
+
+// IntegrationTimeValue returns the current integration time in milliseconds
+func (v *VEML7700Driver) IntegrationTimeValue() int {
+ switch v.integrationTime {
+ case ALS_25MS:
+ return 25
+ case ALS_50MS:
+ return 50
+ case ALS_100MS:
+ return 100
+ case ALS_200MS:
+ return 200
+ case ALS_400MS:
+ return 400
+ case ALS_800MS:
+ return 800
+ default:
+ return 100
+ }
+}
+
+func (v *VEML7700Driver) Lux() (float64, error) {
+ light, err := v.ReadRawLight()
+ if err != nil {
+ return 0, err
+ }
+ resolution := v.resolution()
+ return resolution * float64(light), nil
+}
+
+func (v *VEML7700Driver) resolution() float64 {
+ resolutionAtMax := 0.0036
+ gainMax := 2.0
+ integrationTimeMax := 800.0
+ integrationTimeValue := float64(v.IntegrationTimeValue())
+ gainValue := v.GainValue()
+
+ if gainValue == gainMax && integrationTimeValue == integrationTimeMax {
+ return resolutionAtMax
+ }
+ return resolutionAtMax * (integrationTimeMax / integrationTimeValue) * (gainMax / gainValue)
+}
diff --git a/drivers/i2c/veml7700_driver_test.go b/drivers/i2c/veml7700_driver_test.go
new file mode 100644
index 000000000..435bc504f
--- /dev/null
+++ b/drivers/i2c/veml7700_driver_test.go
@@ -0,0 +1,83 @@
+package i2c
+
+import (
+ "bytes"
+ "errors"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "gobot.io/x/gobot/v2"
+)
+
+// this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver
+// and tests all implementations, so no further tests needed here for gobot.Driver interface
+var _ gobot.Driver = (*VEML7700Driver)(nil)
+
+func initTestVEML7700DriverWithStubbedAdaptor() (*VEML7700Driver, *i2cTestAdaptor) {
+ a := newI2cTestAdaptor()
+ d := NewVEML7700Driver(a)
+ if err := d.Start(); err != nil {
+ panic(err)
+ }
+ return d, a
+}
+
+func TestNewVEML7700Driver(t *testing.T) {
+ var di interface{} = NewVEML7700Driver(newI2cTestAdaptor())
+ d, ok := di.(*VEML7700Driver)
+ if !ok {
+ t.Errorf("NewVEML7700Driver() should have returned a *VEML7700Driver")
+ }
+ assert.NotNil(t, d.Driver)
+ assert.True(t, strings.HasPrefix(d.Name(), "VEML7700"))
+ assert.Equal(t, 0x10, d.defaultAddress)
+}
+
+func TestVEML7700Options(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 := NewVEML7700Driver(newI2cTestAdaptor(), WithBus(2))
+ assert.Equal(t, 2, d.GetBusOrDefault(1))
+}
+
+func TestVEML7700Start(t *testing.T) {
+ d := NewVEML7700Driver(newI2cTestAdaptor())
+ require.NoError(t, d.Start())
+}
+
+func TestVEML7700Halt(t *testing.T) {
+ d, _ := initTestVEML7700DriverWithStubbedAdaptor()
+ require.NoError(t, d.Halt())
+}
+
+func TestVEML7700NullLux(t *testing.T) {
+ d, _ := initTestVEML7700DriverWithStubbedAdaptor()
+ lux, _ := d.Lux()
+ assert.Equal(t, 0.0, lux)
+}
+
+func TestVEML7700Lux(t *testing.T) {
+ d, a := initTestVEML7700DriverWithStubbedAdaptor()
+ a.i2cReadImpl = func(b []byte) (int, error) {
+ buf := new(bytes.Buffer)
+ buf.Write([]byte{0x05, 0xb0})
+ copy(b, buf.Bytes())
+ return buf.Len(), nil
+ }
+
+ lux, _ := d.Lux()
+ assert.Equal(t, 20764.108799999998, lux)
+}
+
+func TestVEML7700LuxError(t *testing.T) {
+ d, a := initTestVEML7700DriverWithStubbedAdaptor()
+ a.i2cReadImpl = func(b []byte) (int, error) {
+ return 0, errors.New("wrong number of bytes read")
+ }
+
+ _, err := d.Lux()
+ require.ErrorContains(t, err, "wrong number of bytes read")
+}
diff --git a/drivers/i2c/wiichuck_driver_test.go b/drivers/i2c/wiichuck_driver_test.go
index 0f2b40109..654c7ced2 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")
}
}
@@ -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
})
@@ -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")
}
}
@@ -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
})
@@ -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/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..207c83b11
--- /dev/null
+++ b/drivers/serial/README.md
@@ -0,0 +1,17 @@
+# 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
+- Neurosky: MindWave
+- MegaPi: MotorDriver
diff --git a/drivers/serial/doc.go b/drivers/serial/doc.go
new file mode 100644
index 000000000..bae3f9291
--- /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/release/drivers/serial/README.md
+*/
+package serial // import "gobot.io/x/gobot/v2/drivers/serial"
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/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 70%
rename from platforms/neurosky/neurosky_driver_test.go
rename to drivers/serial/neurosky/mindwave_driver_test.go
index 00dd62a78..5236eccde 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,30 +38,25 @@ 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:
case <-time.After(100 * time.Millisecond):
{
- t.Errorf("error was not emitted")
+ require.Fail(t, "error was not emitted")
}
}
@@ -79,88 +71,88 @@ 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
})
select {
case <-sem:
case <-time.After(100 * time.Millisecond):
- t.Errorf("Event \"extended\" was not published")
+ require.Fail(t, "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
new file mode 100644
index 000000000..ac6b428c1
--- /dev/null
+++ b/drivers/serial/serial_driver.go
@@ -0,0 +1,122 @@
+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,
+ 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: afterStart,
+ beforeHalt: beforeHalt,
+ 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 {
+ 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 [serial.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()
+}
+
+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
new file mode 100644
index 000000000..a7109d94e
--- /dev/null
+++ b/drivers/serial/serial_driver_test.go
@@ -0,0 +1,85 @@
+package serial
+
+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/serial/testutil"
+)
+
+var _ gobot.Driver = (*Driver)(nil)
+
+func initTestDriver() *Driver {
+ a := testutil.NewSerialTestAdaptor()
+ d := NewDriver(a, "SERIAL_BASIC", nil, nil)
+ return d
+}
+
+func TestNewDriver(t *testing.T) {
+ // arrange
+ const name = "mybot"
+ a := testutil.NewSerialTestAdaptor()
+ // 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_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 := testutil.NewSerialTestAdaptor()
+ // 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"
+ 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/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/sphero_driver.go b/drivers/serial/sphero/sphero_driver.go
new file mode 100644
index 000000000..907d171bd
--- /dev/null
+++ b/drivers/serial/sphero/sphero_driver.go
@@ -0,0 +1,480 @@
+package sphero
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "log"
+ "time"
+
+ "gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/drivers/common/spherocommon"
+ "gobot.io/x/gobot/v2/drivers/serial"
+)
+
+type spheroSerialAdaptor interface {
+ gobot.Adaptor
+ serial.SerialReader
+ serial.SerialWriter
+
+ IsConnected() bool
+}
+
+type packet struct {
+ header []uint8
+ body []uint8
+ checksum uint8
+}
+
+// SpheroDriver Represents a Sphero 2.0
+type SpheroDriver struct {
+ *serial.Driver
+ gobot.Eventer
+ 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.
+//
+// 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, opts ...serial.OptionApplier) *SpheroDriver {
+ d := &SpheroDriver{
+ Eventer: gobot.NewEventer(),
+ packetChannel: make(chan *packet, 1024),
+ responseChannel: make(chan []uint8, 1024),
+ shutdownWaitTime: 1 * time.Second,
+ }
+ d.Driver = serial.NewDriver(a, "Sphero", d.initialize, d.shutdown, opts...)
+
+ 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{} {
+ 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(spherocommon.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(spherocommon.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) {
+ //nolint:gosec // TODO: fix later
+ 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) {
+ //nolint:gosec // TODO: fix later
+ d.sendCraftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x30)
+}
+
+// ConfigureLocator configures and enables the Locator
+func (d *SpheroDriver) ConfigureLocator(lc spherocommon.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 spherocommon.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 spherocommon.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 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(spherocommon.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 != spherocommon.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.
+func (d *SpheroDriver) shutdown() error {
+ if d.adaptor().IsConnected() {
+ gobot.Every(10*time.Millisecond, func() {
+ d.Stop()
+ })
+ time.Sleep(d.shutdownWaitTime)
+ }
+ 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 spherocommon.CollisionPacket
+ buffer := bytes.NewBuffer(data[5:]) // skip header
+ if err := binary.Read(buffer, binary.BigEndian, &collision); err != nil {
+ panic(err)
+ }
+ d.Publish(spherocommon.CollisionEvent, collision)
+}
+
+func (d *SpheroDriver) handleDataStreaming(data []uint8) {
+ // ensure data is the right length:
+ if len(data) != 90 {
+ return
+ }
+ 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(spherocommon.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)} //nolint:gosec // TODO: fix later
+ buf := append(hdr, body...)
+
+ packet := &packet{
+ body: body,
+ header: hdr,
+ checksum: spherocommon.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 Sphero serial connector\n", d.Name())
+ return nil
+}
+
+// spheroDefaultCollisionConfig returns a CollisionConfig with sensible collision defaults
+func spheroDefaultCollisionConfig() spherocommon.CollisionConfig {
+ return spherocommon.CollisionConfig{
+ Method: 0x01,
+ Xt: 0x80,
+ Yt: 0x80,
+ Xs: 0x80,
+ Ys: 0x80,
+ Dead: 0x60,
+ }
+}
+
+// spheroDefaultLocatorConfig returns a LocatorConfig with defaults
+func spheroDefaultLocatorConfig() spherocommon.LocatorConfig {
+ return spherocommon.LocatorConfig{
+ Flags: 0x01,
+ X: 0x00,
+ Y: 0x00,
+ YawTare: 0x00,
+ }
+}
diff --git a/platforms/sphero/sphero_driver_test.go b/drivers/serial/sphero/sphero_driver_test.go
similarity index 62%
rename from platforms/sphero/sphero_driver_test.go
rename to drivers/serial/sphero/sphero_driver_test.go
index 4004d083f..9ed175bf8 100644
--- a/platforms/sphero/sphero_driver_test.go
+++ b/drivers/serial/sphero/sphero_driver_test.go
@@ -11,24 +11,39 @@ import (
"github.com/stretchr/testify/require"
"gobot.io/x/gobot/v2"
+ "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, _ := initTestSpheroAdaptor()
- _ = a.Connect()
- return NewSpheroDriver(a)
+ a := testutil.NewSerialTestAdaptor()
+ d := NewSpheroDriver(a)
+ d.shutdownWaitTime = 0 // to speed up the tests
+ return d
}
-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 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 := testutil.NewSerialTestAdaptor()
+ // act
+ d := NewSpheroDriver(a, serial.WithName(newName))
+ // assert
+ assert.Equal(t, newName, d.Name())
}
-func TestSpheroDriver(t *testing.T) {
+func TestSpheroCommands(t *testing.T) {
d := initTestSpheroDriver()
var ret interface{}
@@ -80,30 +95,29 @@ 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 := testutil.NewSerialTestAdaptor()
+ _ = a.Connect()
+ d := NewSpheroDriver(a)
+ d.shutdownWaitTime = 0 // to speed up the tests
require.NoError(t, d.Halt())
}
-func TestSpheroDriverSetDataStreaming(t *testing.T) {
+func TestSpheroSetDataStreaming(t *testing.T) {
d := initTestSpheroDriver()
- d.SetDataStreaming(DefaultDataStreamingConfig())
+ d.SetDataStreaming(spherocommon.DefaultDataStreamingConfig())
data := <-d.packetChannel
buf := new(bytes.Buffer)
- _ = binary.Write(buf, binary.BigEndian, DefaultDataStreamingConfig())
+ _ = binary.Write(buf, binary.BigEndian, spherocommon.DefaultDataStreamingConfig())
assert.Equal(t, buf.Bytes(), data.body)
@@ -119,20 +133,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 := spherocommon.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 +161,9 @@ func TestConfigureLocator(t *testing.T) {
assert.Nil(t, ret)
data = <-d.packetChannel
- lconfig := 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)
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/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/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/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/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.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/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/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/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/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..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()
@@ -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..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 (
@@ -23,7 +24,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 +36,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_device_info.go b/examples/ble_device_info.go
deleted file mode 100644
index 5c612d302..000000000
--- a/examples/ble_device_info.go
+++ /dev/null
@@ -1,45 +0,0 @@
-//go:build example
-// +build example
-
-//
-// Do not build by default.
-
-/*
- How to run
- Pass the Bluetooth address or name as the first param:
-
- go run examples/ble_device_info.go BB-1234
-
- NOTE: sudo is required to use BLE in Linux
-*/
-
-package main
-
-import (
- "fmt"
- "os"
-
- "gobot.io/x/gobot/v2"
- "gobot.io/x/gobot/v2/platforms/ble"
-)
-
-func main() {
- bleAdaptor := ble.NewClientAdaptor(os.Args[1])
- 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())
- }
-
- robot := gobot.NewRobot("bleBot",
- []gobot.Connection{bleAdaptor},
- []gobot.Device{info},
- work,
- )
-
- robot.Start()
-}
diff --git a/examples/ble_generic_access.go b/examples/ble_generic_access.go
deleted file mode 100644
index 761315192..000000000
--- a/examples/ble_generic_access.go
+++ /dev/null
@@ -1,42 +0,0 @@
-//go:build example
-// +build example
-
-//
-// Do not build by default.
-
-/*
- How to run
- Pass the Bluetooth address or name as the first param:
-
- go run examples/ble_generic_access.go BB-1234
-
- NOTE: sudo is required to use BLE in Linux
-*/
-
-package main
-
-import (
- "fmt"
- "os"
-
- "gobot.io/x/gobot/v2"
- "gobot.io/x/gobot/v2/platforms/ble"
-)
-
-func main() {
- bleAdaptor := ble.NewClientAdaptor(os.Args[1])
- access := ble.NewGenericAccessDriver(bleAdaptor)
-
- work := func() {
- fmt.Println("Device name:", access.GetDeviceName())
- fmt.Println("Appearance:", access.GetAppearance())
- }
-
- robot := gobot.NewRobot("bleBot",
- []gobot.Connection{bleAdaptor},
- []gobot.Device{access},
- work,
- )
-
- robot.Start()
-}
diff --git a/examples/ble_multiple_info.go b/examples/ble_multiple_info.go
deleted file mode 100644
index 8f8b3100b..000000000
--- a/examples/ble_multiple_info.go
+++ /dev/null
@@ -1,58 +0,0 @@
-//go:build example
-// +build example
-
-//
-// Do not build by default.
-
-/*
- How to run
- Pass the Bluetooth address or name as the first param:
-
- go run examples/ble_multiple_info.go BB-1234 BB-1235
-
- NOTE: sudo is required to use BLE in Linux
-*/
-
-package main
-
-import (
- "fmt"
- "os"
-
- "gobot.io/x/gobot/v2"
- "gobot.io/x/gobot/v2/api"
- "gobot.io/x/gobot/v2/platforms/ble"
-)
-
-func NewSwarmBot(port string) *gobot.Robot {
- bleAdaptor := ble.NewClientAdaptor(port)
- 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())
- }
-
- robot := gobot.NewRobot("bot "+port,
- []gobot.Connection{bleAdaptor},
- []gobot.Device{info},
- work,
- )
-
- return robot
-}
-
-func main() {
- master := gobot.NewMaster()
- api.NewAPI(master).Start()
-
- for _, port := range os.Args[1:] {
- bot := NewSwarmBot(port)
- master.AddRobot(bot)
- }
-
- master.Start()
-}
diff --git a/examples/ble_battery.go b/examples/bleclient_battery.go
similarity index 60%
rename from examples/ble_battery.go
rename to examples/bleclient_battery.go
index ee8fb04f0..b84d0e62d 100644
--- a/examples/ble_battery.go
+++ b/examples/bleclient_battery.go
@@ -21,16 +21,21 @@ 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], bleclient.WithScanTimeout(30*time.Second))
battery := ble.NewBatteryDriver(bleAdaptor)
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)
})
}
@@ -40,5 +45,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/bb8-collision.go b/examples/bleclient_bb8-collision.go
similarity index 66%
rename from examples/bb8-collision.go
rename to examples/bleclient_bb8-collision.go
index 0b4df325d..d5573a574 100644
--- a/examples/bb8-collision.go
+++ b/examples/bleclient_bb8-collision.go
@@ -20,16 +20,16 @@ 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{}) {
+ _ = 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/bb8.go b/examples/bleclient_bb8.go
similarity index 69%
rename from examples/bb8.go
rename to examples/bleclient_bb8.go
index 8fc5dfc81..18500cc99 100644
--- a/examples/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 (
@@ -20,13 +21,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() {
@@ -43,5 +44,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/bleclient_device_info.go b/examples/bleclient_device_info.go
new file mode 100644
index 000000000..0b8adfce1
--- /dev/null
+++ b/examples/bleclient_device_info.go
@@ -0,0 +1,73 @@
+//go:build example
+// +build example
+
+//
+// Do not build by default.
+
+/*
+ How to run
+ Pass the Bluetooth address or name as the first param:
+
+ go run examples/ble_device_info.go BB-1234
+
+ NOTE: sudo is required to use BLE in Linux
+*/
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "time"
+
+ "gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/drivers/ble"
+ "gobot.io/x/gobot/v2/platforms/bleclient"
+)
+
+func main() {
+ bleAdaptor := bleclient.NewAdaptor(os.Args[1], bleclient.WithScanTimeout(30*time.Second), bleclient.WithDebug())
+ info := ble.NewDeviceInformationDriver(bleAdaptor)
+
+ work := func() {
+ 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",
+ []gobot.Connection{bleAdaptor},
+ []gobot.Device{info},
+ work,
+ )
+
+ 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/bleclient_generic_access.go b/examples/bleclient_generic_access.go
new file mode 100644
index 000000000..400f4b4a8
--- /dev/null
+++ b/examples/bleclient_generic_access.go
@@ -0,0 +1,55 @@
+//go:build example
+// +build example
+
+//
+// Do not build by default.
+
+/*
+ How to run
+ Pass the Bluetooth address or name as the first param:
+
+ go run examples/ble_generic_access.go BB-1234
+
+ NOTE: sudo is required to use BLE in Linux
+*/
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "time"
+
+ "gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/drivers/ble"
+ "gobot.io/x/gobot/v2/platforms/bleclient"
+)
+
+func main() {
+ bleAdaptor := bleclient.NewAdaptor(os.Args[1], bleclient.WithScanTimeout(30*time.Second), bleclient.WithDebug())
+ access := ble.NewGenericAccessDriver(bleAdaptor)
+
+ work := func() {
+ 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",
+ []gobot.Connection{bleAdaptor},
+ []gobot.Device{access},
+ work,
+ )
+
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
+}
diff --git a/examples/microbit_accelerometer.go b/examples/bleclient_microbit_accelerometer.go
similarity index 77%
rename from examples/microbit_accelerometer.go
rename to examples/bleclient_microbit_accelerometer.go
index 0d85c72f8..1a7b301e6 100644
--- a/examples/microbit_accelerometer.go
+++ b/examples/bleclient_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)
})
}
@@ -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 80%
rename from examples/microbit_blink.go
rename to examples/bleclient_microbit_blink.go
index d453254ca..6b4d92b9d 100644
--- a/examples/microbit_blink.go
+++ b/examples/bleclient_microbit_blink.go
@@ -30,24 +30,27 @@
package main
import (
+ "fmt"
"os"
"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")
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 73%
rename from examples/microbit_buttons.go
rename to examples/bleclient_microbit_buttons.go
index afd77abd0..c7b1d5d7a 100644
--- a/examples/microbit_buttons.go
+++ b/examples/bleclient_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)
})
}
@@ -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 62%
rename from examples/microbit_buttons_leds.go
rename to examples/bleclient_microbit_buttons_leds.go
index 77cb3f0f2..b9f5ebb49 100644
--- a/examples/microbit_buttons_leds.go
+++ b/examples/bleclient_microbit_buttons_leds.go
@@ -27,35 +27,44 @@
package main
import (
+ "fmt"
"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()
+ if err := leds.UpLeftArrow(); err != nil {
+ fmt.Println(err)
+ }
return
}
- leds.Blank()
+ if err := leds.Blank(); err != nil {
+ fmt.Println(err)
+ }
})
- buttons.On(microbit.ButtonB, 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 72%
rename from examples/microbit_io_button.go
rename to examples/bleclient_microbit_io_button.go
index c9978138f..c203a7d65 100644
--- a/examples/microbit_io_button.go
+++ b/examples/bleclient_microbit_io_button.go
@@ -31,27 +31,32 @@
package main
import (
+ "fmt"
"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")
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 69%
rename from examples/microbit_led.go
rename to examples/bleclient_microbit_led.go
index a034f35b1..4d203750c 100644
--- a/examples/microbit_led.go
+++ b/examples/bleclient_microbit_led.go
@@ -27,25 +27,32 @@
package main
import (
+ "fmt"
"os"
"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() {
- 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 77%
rename from examples/microbit_magnetometer.go
rename to examples/bleclient_microbit_magnetometer.go
index ffae1d67f..90c13637e 100644
--- a/examples/microbit_magnetometer.go
+++ b/examples/bleclient_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)
})
}
@@ -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 77%
rename from examples/microbit_temperature.go
rename to examples/bleclient_microbit_temperature.go
index 821aad37b..7b21e0443 100644
--- a/examples/microbit_temperature.go
+++ b/examples/bleclient_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)
})
}
@@ -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 56%
rename from examples/minidrone.go
rename to examples/bleclient_minidrone.go
index a7a0b93b6..4832f8e1e 100644
--- a/examples/minidrone.go
+++ b/examples/bleclient_minidrone.go
@@ -16,23 +16,28 @@
package main
import (
+ "fmt"
"os"
"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()
+ 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 50%
rename from examples/minidrone_events.go
rename to examples/bleclient_minidrone_events.go
index 6005d29e7..305ed3eaa 100644
--- a/examples/minidrone_events.go
+++ b/examples/bleclient_minidrone_events.go
@@ -21,44 +21,48 @@ 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()
+ if err := drone.Land(); err != nil {
+ fmt.Println(err)
+ }
})
})
- 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.")
})
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/bleclient_minidrone_mambo_ps3.go b/examples/bleclient_minidrone_mambo_ps3.go
new file mode 100644
index 000000000..a977b89ab
--- /dev/null
+++ b/examples/bleclient_minidrone_mambo_ps3.go
@@ -0,0 +1,217 @@
+//go:build example
+// +build example
+
+//
+// Do not build by default.
+
+/*
+ How to setup
+ You must be using a PS3 or compatible controller, along with
+ one of the Parrot Mambo drones to run this example.
+
+ You run the Go program on your computer and communicate
+ wirelessly with the Mambo.
+
+ How to run
+ Pass the Bluetooth name or address as first param:
+
+ go run examples/minidrone_mambo_ps3.go "Mambo_1234"
+
+ NOTE: sudo is required to use BLE in Linux
+*/
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "sync/atomic"
+ "time"
+
+ "gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/drivers/ble/parrot"
+ "gobot.io/x/gobot/v2/platforms/bleclient"
+ "gobot.io/x/gobot/v2/platforms/joystick"
+)
+
+type pair struct {
+ x float64
+ y float64
+}
+
+var leftX, leftY, rightX, rightY atomic.Value
+
+const offset = 32767.0
+
+func main() {
+ joystickAdaptor := joystick.NewAdaptor("0")
+ stick := joystick.NewDriver(joystickAdaptor,
+ "./platforms/joystick/configs/dualshock3.json",
+ )
+
+ droneAdaptor := bleclient.NewAdaptor(os.Args[1])
+ drone := parrot.NewMinidroneDriver(droneAdaptor)
+
+ work := func() {
+ leftX.Store(float64(0.0))
+ leftY.Store(float64(0.0))
+ rightX.Store(float64(0.0))
+ rightY.Store(float64(0.0))
+
+ clawOpen := false
+
+ _ = stick.On(joystick.CirclePress, func(data interface{}) {
+ if clawOpen {
+ if err := drone.ClawControl(0, parrot.ClawClosed); err != nil {
+ fmt.Println(err)
+ }
+ clawOpen = false
+ } else {
+ if err := drone.ClawControl(0, parrot.ClawOpen); err != nil {
+ fmt.Println(err)
+ }
+ clawOpen = true
+ }
+ })
+
+ _ = stick.On(joystick.R2Press, func(data interface{}) {
+ if clawOpen {
+ if err := drone.ClawControl(0, parrot.ClawClosed); err != nil {
+ fmt.Println(err)
+ }
+ clawOpen = false
+ } else {
+ if err := drone.ClawControl(0, parrot.ClawOpen); err != nil {
+ fmt.Println(err)
+ }
+ clawOpen = true
+ }
+ })
+
+ _ = 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{}) {
+ if err := drone.Land(); err != nil {
+ fmt.Println(err)
+ }
+ })
+
+ _ = stick.On(joystick.LeftX, func(data interface{}) {
+ val := float64(data.(int16))
+ leftX.Store(val)
+ })
+
+ _ = stick.On(joystick.LeftY, func(data interface{}) {
+ val := float64(data.(int16))
+ leftY.Store(val)
+ })
+
+ _ = stick.On(joystick.RightX, func(data interface{}) {
+ val := float64(data.(int16))
+ rightX.Store(val)
+ })
+
+ _ = stick.On(joystick.RightY, func(data interface{}) {
+ val := float64(data.(int16))
+ rightY.Store(val)
+ })
+
+ gobot.Every(10*time.Millisecond, func() {
+ rightStick := getRightStick()
+
+ switch {
+ case rightStick.y < -10:
+ if err := drone.Forward(parrot.ValidatePitch(rightStick.y, offset)); err != nil {
+ fmt.Println(err)
+ }
+ case rightStick.y > 10:
+ if err := drone.Backward(parrot.ValidatePitch(rightStick.y, offset)); err != nil {
+ fmt.Println(err)
+ }
+ default:
+ if err := drone.Forward(0); err != nil {
+ fmt.Println(err)
+ }
+ }
+
+ switch {
+ case rightStick.x > 10:
+ if err := drone.Right(parrot.ValidatePitch(rightStick.x, offset)); err != nil {
+ fmt.Println(err)
+ }
+ case rightStick.x < -10:
+ if err := drone.Left(parrot.ValidatePitch(rightStick.x, offset)); err != nil {
+ fmt.Println(err)
+ }
+ default:
+ if err := drone.Right(0); err != nil {
+ fmt.Println(err)
+ }
+ }
+ })
+
+ gobot.Every(10*time.Millisecond, func() {
+ leftStick := getLeftStick()
+ switch {
+ case leftStick.y < -10:
+ if err := drone.Up(parrot.ValidatePitch(leftStick.y, offset)); err != nil {
+ fmt.Println(err)
+ }
+ case leftStick.y > 10:
+ if err := drone.Down(parrot.ValidatePitch(leftStick.y, offset)); err != nil {
+ fmt.Println(err)
+ }
+ default:
+ if err := drone.Up(0); err != nil {
+ fmt.Println(err)
+ }
+ }
+
+ switch {
+ case leftStick.x > 20:
+ if err := drone.Clockwise(parrot.ValidatePitch(leftStick.x, offset)); err != nil {
+ fmt.Println(err)
+ }
+ case leftStick.x < -20:
+ if err := drone.CounterClockwise(parrot.ValidatePitch(leftStick.x, offset)); err != nil {
+ fmt.Println(err)
+ }
+ default:
+ if err := drone.Clockwise(0); err != nil {
+ fmt.Println(err)
+ }
+ }
+ })
+ }
+
+ robot := gobot.NewRobot("minidrone",
+ []gobot.Connection{joystickAdaptor, droneAdaptor},
+ []gobot.Device{stick, drone},
+ work,
+ )
+
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
+}
+
+func getLeftStick() pair {
+ s := pair{x: 0, y: 0}
+ s.x = leftX.Load().(float64)
+ s.y = leftY.Load().(float64)
+ return s
+}
+
+func getRightStick() pair {
+ s := pair{x: 0, y: 0}
+ s.x = rightX.Load().(float64)
+ s.y = rightY.Load().(float64)
+ return s
+}
diff --git a/examples/bleclient_minidrone_ps3.go b/examples/bleclient_minidrone_ps3.go
new file mode 100644
index 000000000..409c24865
--- /dev/null
+++ b/examples/bleclient_minidrone_ps3.go
@@ -0,0 +1,206 @@
+//go:build example
+// +build example
+
+//
+// Do not build by default.
+
+/*
+ How to setup
+ You must be using a PS3 or compatible controller, along with
+ any of the Parrot Minidrone drones to run this example.
+
+ You run the Go program on your computer and communicate
+ wirelessly with the Parrot Minidrone.
+
+ How to run
+ Pass the Bluetooth name or address as first param:
+
+ go run examples/minidrone_ps3.go "Travis_1234"
+
+ NOTE: sudo is required to use BLE in Linux
+*/
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "sync/atomic"
+ "time"
+
+ "gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/drivers/ble/parrot"
+ "gobot.io/x/gobot/v2/platforms/bleclient"
+ "gobot.io/x/gobot/v2/platforms/joystick"
+)
+
+type pair struct {
+ x float64
+ y float64
+}
+
+var leftX, leftY, rightX, rightY atomic.Value
+
+const offset = 32767.0
+
+func main() {
+ joystickAdaptor := joystick.NewAdaptor("0")
+ stick := joystick.NewDriver(joystickAdaptor, "dualshock3")
+
+ droneAdaptor := bleclient.NewAdaptor(os.Args[1])
+ drone := parrot.NewMinidroneDriver(droneAdaptor)
+
+ work := func() {
+ leftX.Store(float64(0.0))
+ leftY.Store(float64(0.0))
+ rightX.Store(float64(0.0))
+ rightY.Store(float64(0.0))
+
+ recording := false
+
+ _ = stick.On(joystick.CirclePress, func(data interface{}) {
+ if recording {
+ if err := drone.StopRecording(); err != nil {
+ fmt.Println(err)
+ }
+ } else {
+ if err := drone.StartRecording(); err != nil {
+ fmt.Println(err)
+ }
+ }
+ recording = !recording
+ })
+
+ _ = stick.On(joystick.SquarePress, func(data interface{}) {
+ if err := drone.Stop(); err != nil {
+ fmt.Println(err)
+ }
+ })
+
+ _ = 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{}) {
+ if err := drone.Land(); err != nil {
+ fmt.Println(err)
+ }
+ })
+
+ _ = stick.On(joystick.LeftX, func(data interface{}) {
+ val := float64(data.(int16))
+ leftX.Store(val)
+ })
+
+ _ = stick.On(joystick.LeftY, func(data interface{}) {
+ val := float64(data.(int16))
+ leftY.Store(val)
+ })
+
+ _ = stick.On(joystick.RightX, func(data interface{}) {
+ val := float64(data.(int16))
+ rightX.Store(val)
+ })
+
+ _ = stick.On(joystick.RightY, func(data interface{}) {
+ val := float64(data.(int16))
+ rightY.Store(val)
+ })
+
+ gobot.Every(10*time.Millisecond, func() {
+ rightStick := getRightStick()
+
+ switch {
+ case rightStick.y < -10:
+ if err := drone.Forward(parrot.ValidatePitch(rightStick.y, offset)); err != nil {
+ fmt.Println(err)
+ }
+ case rightStick.y > 10:
+ if err := drone.Backward(parrot.ValidatePitch(rightStick.y, offset)); err != nil {
+ fmt.Println(err)
+ }
+ default:
+ if err := drone.Forward(0); err != nil {
+ fmt.Println(err)
+ }
+ }
+
+ switch {
+ case rightStick.x > 10:
+ if err := drone.Right(parrot.ValidatePitch(rightStick.x, offset)); err != nil {
+ fmt.Println(err)
+ }
+ case rightStick.x < -10:
+ if err := drone.Left(parrot.ValidatePitch(rightStick.x, offset)); err != nil {
+ fmt.Println(err)
+ }
+ default:
+ if err := drone.Right(0); err != nil {
+ fmt.Println(err)
+ }
+ }
+ })
+
+ gobot.Every(10*time.Millisecond, func() {
+ leftStick := getLeftStick()
+ switch {
+ case leftStick.y < -10:
+ if err := drone.Up(parrot.ValidatePitch(leftStick.y, offset)); err != nil {
+ fmt.Println(err)
+ }
+ case leftStick.y > 10:
+ if err := drone.Down(parrot.ValidatePitch(leftStick.y, offset)); err != nil {
+ fmt.Println(err)
+ }
+ default:
+ if err := drone.Up(0); err != nil {
+ fmt.Println(err)
+ }
+ }
+
+ switch {
+ case leftStick.x > 20:
+ if err := drone.Clockwise(parrot.ValidatePitch(leftStick.x, offset)); err != nil {
+ fmt.Println(err)
+ }
+ case leftStick.x < -20:
+ if err := drone.CounterClockwise(parrot.ValidatePitch(leftStick.x, offset)); err != nil {
+ fmt.Println(err)
+ }
+ default:
+ if err := drone.Clockwise(0); err != nil {
+ fmt.Println(err)
+ }
+ }
+ })
+ }
+
+ robot := gobot.NewRobot("minidrone",
+ []gobot.Connection{joystickAdaptor, droneAdaptor},
+ []gobot.Device{stick, drone},
+ work,
+ )
+
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
+}
+
+func getLeftStick() pair {
+ s := pair{x: 0, y: 0}
+ s.x = leftX.Load().(float64)
+ s.y = leftY.Load().(float64)
+ return s
+}
+
+func getRightStick() pair {
+ s := pair{x: 0, y: 0}
+ s.x = rightX.Load().(float64)
+ s.y = rightY.Load().(float64)
+ return s
+}
diff --git a/examples/ble_multiple_generic.go b/examples/bleclient_multiple_generic.go
similarity index 56%
rename from examples/ble_multiple_generic.go
rename to examples/bleclient_multiple_generic.go
index 15dd9f82d..cbccf5649 100644
--- a/examples/ble_multiple_generic.go
+++ b/examples/bleclient_multiple_generic.go
@@ -21,16 +21,26 @@ 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() {
- 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,
@@ -43,13 +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)
}
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/bleclient_multiple_info.go b/examples/bleclient_multiple_info.go
new file mode 100644
index 000000000..11afb2756
--- /dev/null
+++ b/examples/bleclient_multiple_info.go
@@ -0,0 +1,85 @@
+//go:build example
+// +build example
+
+//
+// Do not build by default.
+
+/*
+ How to run
+ Pass the Bluetooth address or name as the first param:
+
+ go run examples/ble_multiple_info.go BB-1234 BB-1235
+
+ NOTE: sudo is required to use BLE in Linux
+*/
+
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/api"
+ "gobot.io/x/gobot/v2/drivers/ble"
+ "gobot.io/x/gobot/v2/platforms/bleclient"
+)
+
+func NewSwarmBot(port string) *gobot.Robot {
+ bleAdaptor := bleclient.NewAdaptor(port)
+ info := ble.NewDeviceInformationDriver(bleAdaptor)
+
+ work := func() {
+ 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,
+ []gobot.Connection{bleAdaptor},
+ []gobot.Device{info},
+ work,
+ )
+
+ return robot
+}
+
+func main() {
+ manager := gobot.NewManager()
+ api.NewAPI(manager).Start()
+
+ for _, port := range os.Args[1:] {
+ bot := NewSwarmBot(port)
+ manager.AddRobot(bot)
+ }
+
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
+}
diff --git a/examples/ollie.go b/examples/bleclient_ollie.go
similarity index 63%
rename from examples/ollie.go
rename to examples/bleclient_ollie.go
index e98da7b11..208354df0 100644
--- a/examples/ollie.go
+++ b/examples/bleclient_ollie.go
@@ -4,6 +4,7 @@
//
// Do not build by default.
+//nolint:gosec // ok here
package main
import (
@@ -11,13 +12,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() {
@@ -34,5 +35,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/ollie_boost.go b/examples/bleclient_ollie_boost.go
similarity index 61%
rename from examples/ollie_boost.go
rename to examples/bleclient_ollie_boost.go
index 389008c48..72e1b4963 100644
--- a/examples/ollie_boost.go
+++ b/examples/bleclient_ollie_boost.go
@@ -11,20 +11,20 @@ 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
+ 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
@@ -37,5 +37,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/ollie_crazy.go b/examples/bleclient_ollie_crazy.go
similarity index 55%
rename from examples/ollie_crazy.go
rename to examples/bleclient_ollie_crazy.go
index d6a7bf9fb..4d2566b5a 100644
--- a/examples/ollie_crazy.go
+++ b/examples/bleclient_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))
})
}
@@ -33,5 +33,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/ollie_mqtt.go b/examples/bleclient_ollie_mqtt.go
similarity index 67%
rename from examples/ollie_mqtt.go
rename to examples/bleclient_ollie_mqtt.go
index 3e8998f6f..cfd9a4e48 100644
--- a/examples/ollie_mqtt.go
+++ b/examples/bleclient_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,15 +25,15 @@ 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")
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/ollie_multiple.go b/examples/bleclient_ollie_multiple.go
similarity index 69%
rename from examples/ollie_multiple.go
rename to examples/bleclient_ollie_multiple.go
index 01dadf81a..0ced0c475 100644
--- a/examples/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 (
@@ -20,13 +21,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() {
@@ -47,13 +48,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)
}
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/ollie_roll.go b/examples/bleclient_ollie_roll.go
similarity index 60%
rename from examples/ollie_roll.go
rename to examples/bleclient_ollie_roll.go
index 3ee7c30a4..bb7b51259 100644
--- a/examples/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 (
@@ -11,13 +12,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)
@@ -32,5 +33,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/ollie_spin.go b/examples/bleclient_ollie_spin.go
similarity index 55%
rename from examples/ollie_spin.go
rename to examples/bleclient_ollie_spin.go
index 736e9a4e4..4851826c2 100644
--- a/examples/ollie_spin.go
+++ b/examples/bleclient_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))
})
}
@@ -33,5 +33,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/sprkplus.go b/examples/bleclient_sprkplus.go
similarity index 69%
rename from examples/sprkplus.go
rename to examples/bleclient_sprkplus.go
index 8ad732e89..d814c667c 100644
--- a/examples/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 (
@@ -20,13 +21,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() {
@@ -43,5 +44,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/sprkplus_collision.go b/examples/bleclient_sprkplus_collision.go
similarity index 66%
rename from examples/sprkplus_collision.go
rename to examples/bleclient_sprkplus_collision.go
index 4d58a5f89..44b09890b 100644
--- a/examples/sprkplus_collision.go
+++ b/examples/bleclient_sprkplus_collision.go
@@ -20,16 +20,16 @@ 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{}) {
+ _ = 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..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,7 +25,9 @@ func main() {
[]gobot.Device{led},
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.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..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 (
@@ -23,7 +24,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 +36,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..167c7974f 100644
--- a/examples/edison_button_led_api.go
+++ b/examples/edison_button_led_api.go
@@ -7,16 +7,17 @@
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() {
- master := gobot.NewMaster()
- api.NewAPI(master).Start()
+ manager := gobot.NewManager()
+ api.NewAPI(manager).Start()
e := edison.NewAdaptor()
@@ -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)
+ }
})
}
@@ -38,7 +43,9 @@ func main() {
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.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
deleted file mode 100644
index 427a26c3e..000000000
--- a/examples/edison_rgb_led.go
+++ /dev/null
@@ -1,37 +0,0 @@
-//go:build example
-// +build example
-
-//
-// Do not build by default.
-
-package main
-
-import (
- "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))
- led.SetRGB(r, g, b)
- })
- }
-
- robot := gobot.NewRobot("rgbBot",
- []gobot.Connection{e},
- []gobot.Device{led},
- work,
- )
-
- robot.Start()
-}
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..46a51cbfe 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"
@@ -16,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")
@@ -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)
+ }
})
}
@@ -35,7 +38,9 @@ func main() {
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.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..d0069f971 100644
--- a/examples/firmata_gpio_max7219.go
+++ b/examples/firmata_gpio_max7219.go
@@ -18,6 +18,7 @@
package main
import (
+ "fmt"
"os"
"time"
@@ -28,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
@@ -37,8 +38,12 @@ func main() {
work := func() {
gobot.Every(100*time.Millisecond, func() {
- max.ClearAll()
- max.One(module, digit, bits)
+ if err := maxim.ClearAll(); err != nil {
+ fmt.Println(err)
+ }
+ if err := maxim.One(module, digit, bits); err != nil {
+ fmt.Println(err)
+ }
bits = bits << 1
count++
@@ -60,9 +65,11 @@ func main() {
robot := gobot.NewRobot("Max7219Bot",
[]gobot.Connection{firmataAdaptor},
- []gobot.Device{max},
+ []gobot.Device{maxim},
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..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 (
@@ -30,17 +31,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 +58,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..0f403f1d4 100644
--- a/examples/firmata_rgb_led.go
+++ b/examples/firmata_rgb_led.go
@@ -11,9 +11,11 @@
go run examples/firmata_rgb_led.go /dev/ttyACM0
*/
+//nolint:gosec // ok here
package main
import (
+ "fmt"
"os"
"time"
@@ -31,7 +33,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 +45,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..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 (
@@ -31,7 +32,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 +44,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..1cd3dc4bc 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")
@@ -78,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"))
})
}
@@ -97,6 +107,8 @@ func main() {
work,
)
- master.AddRobot(robot)
- master.Start()
+ manager.AddRobot(robot)
+ if err := manager.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..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 (
@@ -25,7 +26,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 +38,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..0cb626783 100644
--- a/examples/hello_api.go
+++ b/examples/hello_api.go
@@ -16,25 +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)
})
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/hello_api_auth.go b/examples/hello_api_auth.go
index 04da9e86b..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,16 +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)
})
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/hello_api_custom.go b/examples/hello_api_custom.go
index 7fddff341..a1eff0b9a 100644
--- a/examples/hello_api_custom.go
+++ b/examples/hello_api_custom.go
@@ -15,23 +15,29 @@ 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) {
- 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))
+ 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)
+ }
})
// starts the API without the default C2PIO API and Robeaux web interface.
a.StartWithoutDefaults()
- master.AddRobot(gobot.NewRobot("hello"))
+ manager.AddRobot(gobot.NewRobot("hello"))
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/hello_api_video.go b/examples/hello_api_video.go
index 3d63fe046..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,9 @@ func main() {
// start capturing
go mjpegCapture()
- master.Start()
+ if err := manager.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..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
//
@@ -12,6 +13,7 @@ package main
// 2. if end pin configure, reboot Jetson nano.
// 3. run gobot
import (
+ "fmt"
"log"
"time"
@@ -29,7 +31,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 +54,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
deleted file mode 100644
index b94e9fc28..000000000
--- a/examples/joule_rgb_led.go
+++ /dev/null
@@ -1,37 +0,0 @@
-//go:build example
-// +build example
-
-//
-// Do not build by default.
-
-package main
-
-import (
- "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))
- led.SetRGB(r, g, b)
- })
- }
-
- robot := gobot.NewRobot("rgbBot",
- []gobot.Connection{e},
- []gobot.Device{led},
- work,
- )
-
- robot.Start()
-}
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 455faec8f..07f6ea5ec 100644
--- a/examples/leap_sphero.go
+++ b/examples/leap_sphero.go
@@ -10,19 +10,20 @@ import (
"math"
"gobot.io/x/gobot/v2"
+ "gobot.io/x/gobot/v2/drivers/serial/sphero"
"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)
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 {
@@ -40,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/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/minidrone_mambo_ps3.go b/examples/minidrone_mambo_ps3.go
deleted file mode 100644
index b7ccd9b3a..000000000
--- a/examples/minidrone_mambo_ps3.go
+++ /dev/null
@@ -1,176 +0,0 @@
-//go:build example
-// +build example
-
-//
-// Do not build by default.
-
-/*
- How to setup
- You must be using a PS3 or compatible controller, along with
- one of the Parrot Mambo drones to run this example.
-
- You run the Go program on your computer and communicate
- wirelessly with the Mambo.
-
- How to run
- Pass the Bluetooth name or address as first param:
-
- go run examples/minidrone_mambo_ps3.go "Mambo_1234"
-
- NOTE: sudo is required to use BLE in Linux
-*/
-
-package main
-
-import (
- "os"
- "sync/atomic"
- "time"
-
- "gobot.io/x/gobot/v2"
- "gobot.io/x/gobot/v2/platforms/ble"
- "gobot.io/x/gobot/v2/platforms/joystick"
- "gobot.io/x/gobot/v2/platforms/parrot/minidrone"
-)
-
-type pair struct {
- x float64
- y float64
-}
-
-var leftX, leftY, rightX, rightY atomic.Value
-
-const offset = 32767.0
-
-func main() {
- joystickAdaptor := joystick.NewAdaptor("0")
- stick := joystick.NewDriver(joystickAdaptor,
- "./platforms/joystick/configs/dualshock3.json",
- )
-
- droneAdaptor := ble.NewClientAdaptor(os.Args[1])
- drone := minidrone.NewDriver(droneAdaptor)
-
- work := func() {
- leftX.Store(float64(0.0))
- leftY.Store(float64(0.0))
- rightX.Store(float64(0.0))
- rightY.Store(float64(0.0))
-
- clawOpen := false
-
- stick.On(joystick.CirclePress, func(data interface{}) {
- if clawOpen {
- drone.ClawControl(0, minidrone.ClawClosed)
- clawOpen = false
- } else {
- drone.ClawControl(0, minidrone.ClawOpen)
- clawOpen = true
- }
- })
-
- stick.On(joystick.R2Press, func(data interface{}) {
- if clawOpen {
- drone.ClawControl(0, minidrone.ClawClosed)
- clawOpen = false
- } else {
- drone.ClawControl(0, minidrone.ClawOpen)
- clawOpen = true
- }
- })
-
- stick.On(joystick.TrianglePress, func(data interface{}) {
- drone.HullProtection(true)
- drone.TakeOff()
- })
-
- stick.On(joystick.XPress, func(data interface{}) {
- drone.Land()
- })
-
- stick.On(joystick.LeftX, func(data interface{}) {
- val := float64(data.(int16))
- leftX.Store(val)
- })
-
- stick.On(joystick.LeftY, func(data interface{}) {
- val := float64(data.(int16))
- leftY.Store(val)
- })
-
- stick.On(joystick.RightX, func(data interface{}) {
- val := float64(data.(int16))
- rightX.Store(val)
- })
-
- stick.On(joystick.RightY, func(data interface{}) {
- val := float64(data.(int16))
- rightY.Store(val)
- })
-
- gobot.Every(10*time.Millisecond, func() {
- rightStick := getRightStick()
-
- switch {
- case rightStick.y < -10:
- drone.Forward(minidrone.ValidatePitch(rightStick.y, offset))
- case rightStick.y > 10:
- drone.Backward(minidrone.ValidatePitch(rightStick.y, offset))
- default:
- drone.Forward(0)
- }
-
- switch {
- case rightStick.x > 10:
- drone.Right(minidrone.ValidatePitch(rightStick.x, offset))
- case rightStick.x < -10:
- drone.Left(minidrone.ValidatePitch(rightStick.x, offset))
- default:
- drone.Right(0)
- }
- })
-
- gobot.Every(10*time.Millisecond, func() {
- leftStick := getLeftStick()
- switch {
- case leftStick.y < -10:
- drone.Up(minidrone.ValidatePitch(leftStick.y, offset))
- case leftStick.y > 10:
- drone.Down(minidrone.ValidatePitch(leftStick.y, offset))
- default:
- drone.Up(0)
- }
-
- switch {
- case leftStick.x > 20:
- drone.Clockwise(minidrone.ValidatePitch(leftStick.x, offset))
- case leftStick.x < -20:
- drone.CounterClockwise(minidrone.ValidatePitch(leftStick.x, offset))
- default:
- drone.Clockwise(0)
- }
- })
- }
-
- robot := gobot.NewRobot("minidrone",
- []gobot.Connection{joystickAdaptor, droneAdaptor},
- []gobot.Device{stick, drone},
- work,
- )
-
- robot.Start()
-}
-
-func getLeftStick() pair {
- s := pair{x: 0, y: 0}
- s.x = leftX.Load().(float64)
- s.y = leftY.Load().(float64)
- return s
-}
-
-func getRightStick() pair {
- s := pair{x: 0, y: 0}
- s.x = rightX.Load().(float64)
- s.y = rightY.Load().(float64)
- return s
-}
diff --git a/examples/minidrone_ps3.go b/examples/minidrone_ps3.go
deleted file mode 100644
index 7afd96053..000000000
--- a/examples/minidrone_ps3.go
+++ /dev/null
@@ -1,167 +0,0 @@
-//go:build example
-// +build example
-
-//
-// Do not build by default.
-
-/*
- How to setup
- You must be using a PS3 or compatible controller, along with
- any of the Parrot Minidrone drones to run this example.
-
- You run the Go program on your computer and communicate
- wirelessly with the Parrot Minidrone.
-
- How to run
- Pass the Bluetooth name or address as first param:
-
- go run examples/minidrone_ps3.go "Travis_1234"
-
- NOTE: sudo is required to use BLE in Linux
-*/
-
-package main
-
-import (
- "os"
- "sync/atomic"
- "time"
-
- "gobot.io/x/gobot/v2"
- "gobot.io/x/gobot/v2/platforms/ble"
- "gobot.io/x/gobot/v2/platforms/joystick"
- "gobot.io/x/gobot/v2/platforms/parrot/minidrone"
-)
-
-type pair struct {
- x float64
- y float64
-}
-
-var leftX, leftY, rightX, rightY atomic.Value
-
-const offset = 32767.0
-
-func main() {
- joystickAdaptor := joystick.NewAdaptor("0")
- stick := joystick.NewDriver(joystickAdaptor, "dualshock3")
-
- droneAdaptor := ble.NewClientAdaptor(os.Args[1])
- drone := minidrone.NewDriver(droneAdaptor)
-
- work := func() {
- leftX.Store(float64(0.0))
- leftY.Store(float64(0.0))
- rightX.Store(float64(0.0))
- rightY.Store(float64(0.0))
-
- recording := false
-
- stick.On(joystick.CirclePress, func(data interface{}) {
- if recording {
- drone.StopRecording()
- } else {
- drone.StartRecording()
- }
- recording = !recording
- })
-
- stick.On(joystick.SquarePress, func(data interface{}) {
- drone.Stop()
- })
-
- stick.On(joystick.TrianglePress, func(data interface{}) {
- drone.HullProtection(true)
- drone.TakeOff()
- })
-
- stick.On(joystick.XPress, func(data interface{}) {
- drone.Land()
- })
-
- stick.On(joystick.LeftX, func(data interface{}) {
- val := float64(data.(int16))
- leftX.Store(val)
- })
-
- stick.On(joystick.LeftY, func(data interface{}) {
- val := float64(data.(int16))
- leftY.Store(val)
- })
-
- stick.On(joystick.RightX, func(data interface{}) {
- val := float64(data.(int16))
- rightX.Store(val)
- })
-
- stick.On(joystick.RightY, func(data interface{}) {
- val := float64(data.(int16))
- rightY.Store(val)
- })
-
- gobot.Every(10*time.Millisecond, func() {
- rightStick := getRightStick()
-
- switch {
- case rightStick.y < -10:
- drone.Forward(minidrone.ValidatePitch(rightStick.y, offset))
- case rightStick.y > 10:
- drone.Backward(minidrone.ValidatePitch(rightStick.y, offset))
- default:
- drone.Forward(0)
- }
-
- switch {
- case rightStick.x > 10:
- drone.Right(minidrone.ValidatePitch(rightStick.x, offset))
- case rightStick.x < -10:
- drone.Left(minidrone.ValidatePitch(rightStick.x, offset))
- default:
- drone.Right(0)
- }
- })
-
- gobot.Every(10*time.Millisecond, func() {
- leftStick := getLeftStick()
- switch {
- case leftStick.y < -10:
- drone.Up(minidrone.ValidatePitch(leftStick.y, offset))
- case leftStick.y > 10:
- drone.Down(minidrone.ValidatePitch(leftStick.y, offset))
- default:
- drone.Up(0)
- }
-
- switch {
- case leftStick.x > 20:
- drone.Clockwise(minidrone.ValidatePitch(leftStick.x, offset))
- case leftStick.x < -20:
- drone.CounterClockwise(minidrone.ValidatePitch(leftStick.x, offset))
- default:
- drone.Clockwise(0)
- }
- })
- }
-
- robot := gobot.NewRobot("minidrone",
- []gobot.Connection{joystickAdaptor, droneAdaptor},
- []gobot.Device{stick, drone},
- work,
- )
-
- robot.Start()
-}
-
-func getLeftStick() pair {
- s := pair{x: 0, y: 0}
- s.x = leftX.Load().(float64)
- s.y = leftY.Load().(float64)
- return s
-}
-
-func getRightStick() pair {
- s := pair{x: 0, y: 0}
- s.x = rightX.Load().(float64)
- s.y = rightY.Load().(float64)
- return s
-}
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/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..0dbc30b7b 100644
--- a/examples/particle_api.go
+++ b/examples/particle_api.go
@@ -14,6 +14,7 @@
package main
import (
+ "fmt"
"os"
"time"
@@ -24,15 +25,17 @@ 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")
work := func() {
gobot.Every(1*time.Second, func() {
- led.Toggle()
+ if err := led.Toggle(); err != nil {
+ fmt.Println(err)
+ }
})
}
@@ -42,7 +45,9 @@ func main() {
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.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..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()
@@ -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")
})
}
@@ -40,7 +40,9 @@ func main() {
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/pebble_accelerometer.go b/examples/pebble_accelerometer.go
index 5444312b3..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()
@@ -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))
})
}
@@ -35,7 +35,9 @@ func main() {
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/raspi_adafruit2327_servo.go b/examples/raspi_adafruit2327_servo.go
index 9a93aa985..846137c73 100644
--- a/examples/raspi_adafruit2327_servo.go
+++ b/examples/raspi_adafruit2327_servo.go
@@ -4,9 +4,11 @@
//
// Do not build by default.
+//nolint:gosec // ok here
package main
import (
+ "fmt"
"log"
"time"
@@ -38,7 +40,9 @@ func main() {
work := func() {
gobot.Every(5*time.Second, func() {
- adafruitServoMotorRunner(adaFruit)
+ if err := adafruitServoMotorRunner(adaFruit); err != nil {
+ fmt.Println(err)
+ }
})
}
@@ -48,7 +52,9 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
func adafruitServoMotorRunner(a *i2c.Adafruit2327Driver) error {
@@ -60,26 +66,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..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 (
@@ -69,7 +70,6 @@ func main() {
if err := stepper.MoveDeg(-360 * countRot); err != nil {
log.Println("move backward", err)
}
- return
}
robot := gobot.NewRobot("stepperBot",
@@ -78,5 +78,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/megapi_motor.go b/examples/serialport_megapi_motor.go
similarity index 59%
rename from examples/megapi_motor.go
rename to examples/serialport_megapi_motor.go
index ca61c3db3..54fbd3191 100644
--- a/examples/megapi_motor.go
+++ b/examples/serialport_megapi_motor.go
@@ -7,24 +7,28 @@
package main
import (
+ "fmt"
"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)
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
@@ -33,10 +37,12 @@ func main() {
}
robot := gobot.NewRobot("megaPiBot",
- []gobot.Connection{megaPiAdaptor},
+ []gobot.Connection{adaptor},
[]gobot.Device{motor},
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/neurosky.go b/examples/serialport_mindwave.go
similarity index 50%
rename from examples/neurosky.go
rename to examples/serialport_mindwave.go
index 37cb12a94..c27c685a5 100644
--- a/examples/neurosky.go
+++ b/examples/serialport_mindwave.go
@@ -10,34 +10,35 @@ 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{}) {
+ _ = 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{}) {
- eeg := data.(neurosky.EEGData)
+ _ = neuro.On(neuro.Event("eeg"), func(data interface{}) {
+ eeg := data.(neurosky.MindWaveEEGData)
fmt.Println("Delta", eeg.Delta)
fmt.Println("Theta", eeg.Theta)
fmt.Println("LoAlpha", eeg.LoAlpha)
@@ -56,5 +57,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/sphero.go b/examples/serialport_sphero.go
similarity index 58%
rename from examples/sphero.go
rename to examples/serialport_sphero.go
index f876f4a10..1947542f6 100644
--- a/examples/sphero.go
+++ b/examples/serialport_sphero.go
@@ -4,6 +4,7 @@
//
// Do not build by default.
+//nolint:gosec // ok here
package main
import (
@@ -11,21 +12,23 @@ import (
"time"
"gobot.io/x/gobot/v2"
- "gobot.io/x/gobot/v2/platforms/sphero"
+ "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 := sphero.NewAdaptor("/dev/rfcomm0")
+ adaptor := serialport.NewAdaptor("/dev/rfcomm0")
spheroDriver := sphero.NewSpheroDriver(adaptor)
work := func() {
- spheroDriver.SetDataStreaming(sphero.DefaultDataStreamingConfig())
+ spheroDriver.SetDataStreaming(spherocommon.DefaultDataStreamingConfig())
- spheroDriver.On(sphero.Collision, func(data interface{}) {
+ _ = spheroDriver.On(spherocommon.CollisionEvent, func(data interface{}) {
fmt.Printf("Collision! %+v\n", data)
})
- spheroDriver.On(sphero.SensorData, func(data interface{}) {
+ _ = spheroDriver.On(spherocommon.SensorDataEvent, func(data interface{}) {
fmt.Printf("Streaming Data! %+v\n", data)
})
@@ -47,5 +50,7 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/sphero_api.go b/examples/serialport_sphero_api.go
similarity index 70%
rename from examples/sphero_api.go
rename to examples/serialport_sphero_api.go
index 0c38abcef..c12cd9f43 100644
--- a/examples/sphero_api.go
+++ b/examples/serialport_sphero_api.go
@@ -9,19 +9,20 @@ 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/sphero"
+ "gobot.io/x/gobot/v2/platforms/serialport"
)
func main() {
- master := gobot.NewMaster()
- api.NewAPI(master).Start()
+ manager := gobot.NewManager()
+ api.NewAPI(manager).Start()
spheros := map[string]string{
"Sphero-BPO": "/dev/rfcomm0",
}
for name, port := range spheros {
- spheroAdaptor := sphero.NewAdaptor(port)
+ spheroAdaptor := serialport.NewAdaptor(port)
spheroDriver := sphero.NewSpheroDriver(spheroAdaptor)
work := func() {
@@ -38,8 +39,10 @@ func main() {
return nil
})
- master.AddRobot(robot)
+ manager.AddRobot(robot)
}
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/sphero_calibration.go b/examples/serialport_sphero_calibration.go
similarity index 74%
rename from examples/sphero_calibration.go
rename to examples/serialport_sphero_calibration.go
index d48d0542b..a4442fc2f 100644
--- a/examples/sphero_calibration.go
+++ b/examples/serialport_sphero_calibration.go
@@ -9,16 +9,17 @@ package main
import (
"gobot.io/x/gobot/v2"
"gobot.io/x/gobot/v2/api"
+ "gobot.io/x/gobot/v2/drivers/serial/sphero"
"gobot.io/x/gobot/v2/platforms/keyboard"
- "gobot.io/x/gobot/v2/platforms/sphero"
+ "gobot.io/x/gobot/v2/platforms/serialport"
)
func main() {
- master := gobot.NewMaster()
- a := api.NewAPI(master)
+ manager := gobot.NewManager()
+ a := api.NewAPI(manager)
a.Start()
- ballConn := sphero.NewAdaptor("/dev/rfcomm0")
+ ballConn := serialport.NewAdaptor("/dev/rfcomm0")
ball := sphero.NewSpheroDriver(ballConn)
keys := keyboard.NewDriver()
@@ -26,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 {
@@ -61,7 +62,9 @@ func main() {
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/sphero_conways.go b/examples/serialport_sphero_conways.go
similarity index 77%
rename from examples/sphero_conways.go
rename to examples/serialport_sphero_conways.go
index 23d97fc68..11de8517f 100644
--- a/examples/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 (
@@ -11,7 +12,10 @@ import (
"time"
"gobot.io/x/gobot/v2"
- "gobot.io/x/gobot/v2/platforms/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"
)
type conway struct {
@@ -22,7 +26,7 @@ type conway struct {
}
func main() {
- master := gobot.NewMaster()
+ manager := gobot.NewManager()
spheros := []string{
"/dev/rfcomm0",
@@ -31,10 +35,9 @@ func main() {
}
for _, port := range spheros {
- spheroAdaptor := sphero.NewAdaptor(port)
+ spheroAdaptor := serialport.NewAdaptor(port)
- cell := sphero.NewSpheroDriver(spheroAdaptor)
- cell.SetName("Sphero" + port)
+ cell := sphero.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero"+port))
work := func() {
conway := new(conway)
@@ -42,7 +45,7 @@ func main() {
conway.birth()
- cell.On(sphero.Collision, func(data interface{}) {
+ _ = cell.On(spherocommon.CollisionEvent, func(data interface{}) {
conway.contact()
})
@@ -65,10 +68,12 @@ func main() {
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
}
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
func (c *conway) resetContacts() {
diff --git a/examples/sphero_dpad.go b/examples/serialport_sphero_dpad.go
similarity index 71%
rename from examples/sphero_dpad.go
rename to examples/serialport_sphero_dpad.go
index f41c16c63..111b01150 100644
--- a/examples/sphero_dpad.go
+++ b/examples/serialport_sphero_dpad.go
@@ -11,15 +11,16 @@ 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/sphero"
+ "gobot.io/x/gobot/v2/platforms/serialport"
)
func main() {
- master := gobot.NewMaster()
- a := api.NewAPI(master)
+ manager := gobot.NewManager()
+ a := api.NewAPI(manager)
a.Start()
- conn := sphero.NewAdaptor("/dev/rfcomm0")
+ conn := serialport.NewAdaptor("/dev/rfcomm0")
ball := sphero.NewSpheroDriver(conn)
robot := gobot.NewRobot("sphero-dpad",
@@ -46,7 +47,9 @@ func main() {
return "ok"
})
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/sphero_master.go b/examples/serialport_sphero_master.go
similarity index 64%
rename from examples/sphero_master.go
rename to examples/serialport_sphero_master.go
index 19fe9b439..2679ab17d 100644
--- a/examples/sphero_master.go
+++ b/examples/serialport_sphero_master.go
@@ -4,24 +4,26 @@
//
// Do not build by default.
+//nolint:gosec // ok here
package main
import (
"time"
"gobot.io/x/gobot/v2"
- "gobot.io/x/gobot/v2/platforms/sphero"
+ "gobot.io/x/gobot/v2/drivers/serial/sphero"
+ "gobot.io/x/gobot/v2/platforms/serialport"
)
func main() {
- master := gobot.NewMaster()
+ manager := gobot.NewManager()
spheros := map[string]string{
"Sphero-BPO": "/dev/rfcomm0",
}
for name, port := range spheros {
- spheroAdaptor := sphero.NewAdaptor(port)
+ spheroAdaptor := serialport.NewAdaptor(port)
spheroDriver := sphero.NewSpheroDriver(spheroAdaptor)
work := func() {
@@ -34,13 +36,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)),
@@ -49,7 +51,9 @@ func main() {
},
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/sphero_multiple.go b/examples/serialport_sphero_multiple.go
similarity index 59%
rename from examples/sphero_multiple.go
rename to examples/serialport_sphero_multiple.go
index 5748d7718..6d8c70374 100644
--- a/examples/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 (
@@ -12,18 +13,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/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 := sphero.NewAdaptor(port)
- spheroDriver := sphero.NewSpheroDriver(spheroAdaptor)
- spheroDriver.SetName("Sphero" + port)
+ spheroAdaptor := serialport.NewAdaptor(port)
+ spheroDriver := sphero.NewSpheroDriver(spheroAdaptor, serial.WithName("Sphero"+port))
work := func() {
spheroDriver.Stop()
- spheroDriver.On(sphero.Collision, func(data interface{}) {
+ _ = spheroDriver.On(spherocommon.CollisionEvent, func(data interface{}) {
fmt.Println("Collision Detected!")
})
@@ -48,8 +51,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",
@@ -59,8 +62,10 @@ func main() {
}
for _, port := range spheros {
- master.AddRobot(NewSwarmBot(port))
+ manager.AddRobot(NewSwarmBot(port))
}
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/square.go b/examples/square.go
index bd0921b89..5c99fb3bd 100644
--- a/examples/square.go
+++ b/examples/square.go
@@ -7,6 +7,7 @@
package main
import (
+ "fmt"
"time"
"gobot.io/x/gobot/v2"
@@ -16,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()
@@ -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)
+ }
})
}
@@ -78,7 +103,9 @@ func main() {
return enabled
})
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
diff --git a/examples/square_fire.go b/examples/square_fire.go
index 69c9c0121..6fa2eb5fe 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"
@@ -16,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()
@@ -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)
+ }
})
}
@@ -78,7 +103,9 @@ func main() {
return enabled
})
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.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..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
@@ -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..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))
@@ -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/go.mod b/go.mod
index 8a5b93b70..e5283e041 100644
--- a/go.mod
+++ b/go.mod
@@ -1,26 +1,28 @@
module gobot.io/x/gobot/v2
-go 1.19
+go 1.22.0
+
+toolchain go1.22.7
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.31.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.19.0
- golang.org/x/sys v0.16.0
- periph.io/x/conn/v3 v3.7.0
+ github.com/stretchr/testify v1.9.0
+ 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.1
periph.io/x/host/v3 v3.8.2
tinygo.org/x/bluetooth v0.8.0
)
@@ -31,18 +33,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.4 // 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-20221213043340-85dc80edc4e1 // 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-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/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 5a87cda0a..d8bc81ebb 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.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
-github.com/klauspost/compress v1.17.4/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-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-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,14 +53,13 @@ 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=
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=
@@ -71,34 +70,35 @@ 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/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.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.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+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.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
-golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
+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 +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.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=
@@ -120,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/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/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/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/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/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/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/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/doc.go b/platforms/beaglebone/doc.go
index d868ed3f7..f4834243e 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,10 +36,12 @@ Example:
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
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/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/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/ble_client_adaptor.go b/platforms/ble/ble_client_adaptor.go
deleted file mode 100644
index 8273e1c94..000000000
--- a/platforms/ble/ble_client_adaptor.go
+++ /dev/null
@@ -1,228 +0,0 @@
-package ble
-
-import (
- "fmt"
- "log"
- "sync"
- "time"
-
- "tinygo.org/x/bluetooth"
-
- "gobot.io/x/gobot/v2"
-)
-
-var (
- currentAdapter *bluetooth.Adapter
- 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 {
- name string
- address string
- AdapterName string
-
- addr bluetooth.Address
- adpt *bluetooth.Adapter
- device *bluetooth.Device
- characteristics map[string]bluetooth.DeviceCharacteristic
-
- connected bool
- withoutResponses bool
-}
-
-// NewClientAdaptor returns a new ClientAdaptor given an address
-func NewClientAdaptor(address string) *ClientAdaptor {
- return &ClientAdaptor{
- name: gobot.DefaultName("BLEClient"),
- address: address,
- AdapterName: "default",
- connected: false,
- withoutResponses: false,
- characteristics: make(map[string]bluetooth.DeviceCharacteristic),
- }
-}
-
-// Name returns the name for the adaptor
-func (b *ClientAdaptor) Name() string { return b.name }
-
-// SetName sets the name for the adaptor
-func (b *ClientAdaptor) SetName(n string) { b.name = n }
-
-// Address returns the Bluetooth LE address for the adaptor
-func (b *ClientAdaptor) Address() string { return b.address }
-
-// WithoutResponses sets if the adaptor should expect responses after
-// writing characteristics for this device
-func (b *ClientAdaptor) WithoutResponses(use bool) { b.withoutResponses = use }
-
-// Connect initiates a connection to the BLE peripheral. Returns true on successful connection.
-func (b *ClientAdaptor) Connect() error {
- bleMutex.Lock()
- defer bleMutex.Unlock()
-
- var err error
- // enable adaptor
- b.adpt, err = getBLEAdapter(b.AdapterName)
- if err != nil {
- return fmt.Errorf("can't get adapter %s: %w", b.AdapterName, err)
- }
-
- // handle address
- b.addr.Set(b.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 {
- panic(err)
- }
- b.SetName(result.LocalName())
- ch <- result
- }
- })
-
- if err != nil {
- return err
- }
-
- // wait to connect to peripheral device
- result := <-ch
- b.device, err = b.adpt.Connect(result.Address, bluetooth.ConnectionParams{})
- if err != nil {
- return err
- }
-
- // get all services/characteristics
- srvcs, err := b.device.DiscoverServices(nil)
- if err != nil {
- return err
- }
- for _, srvc := range srvcs {
- chars, err := srvc.DiscoverCharacteristics(nil)
- if err != nil {
- log.Println(err)
- continue
- }
- for _, char := range chars {
- b.characteristics[char.UUID().String()] = char
- }
- }
-
- b.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 {
- return err
- }
- }
- return b.Connect()
-}
-
-// Disconnect terminates the connection to the BLE peripheral. Returns true on successful disconnect.
-func (b *ClientAdaptor) Disconnect() error {
- err := b.device.Disconnect()
- time.Sleep(500 * time.Millisecond)
- return err
-}
-
-// Finalize finalizes the BLEAdaptor
-func (b *ClientAdaptor) Finalize() error {
- return b.Disconnect()
-}
-
-// ReadCharacteristic returns bytes from the BLE device for the
-// requested characteristic uuid
-func (b *ClientAdaptor) ReadCharacteristic(cUUID string) ([]byte, error) {
- if !b.connected {
- return nil, fmt.Errorf("Cannot read from BLE device until connected")
- }
-
- cUUID = convertUUID(cUUID)
-
- if char, ok := b.characteristics[cUUID]; ok {
- buf := make([]byte, 255)
- n, err := char.Read(buf)
- if err != nil {
- return nil, err
- }
- return buf[:n], nil
- }
-
- return nil, fmt.Errorf("Unknown characteristic: %s", cUUID)
-}
-
-// 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 {
- return fmt.Errorf("Cannot write to BLE device until connected")
- }
-
- cUUID = convertUUID(cUUID)
-
- if char, ok := b.characteristics[cUUID]; ok {
- _, err := char.WriteWithoutResponse(data)
- if err != nil {
- return err
- }
- return nil
- }
-
- return fmt.Errorf("Unknown characteristic: %s", cUUID)
-}
-
-// 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 {
- return fmt.Errorf("Cannot subscribe to BLE device until connected")
- }
-
- cUUID = convertUUID(cUUID)
-
- if char, ok := b.characteristics[cUUID]; ok {
- fn := func(d []byte) {
- f(d, nil)
- }
- return char.EnableNotifications(fn)
- }
-
- 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
- }
-
- currentAdapter = bluetooth.DefaultAdapter
- err := currentAdapter.Enable()
- if err != nil {
- return nil, err
- }
-
- return currentAdapter, nil
-}
diff --git a/platforms/ble/ble_client_adaptor_test.go b/platforms/ble/ble_client_adaptor_test.go
deleted file mode 100644
index 0862405e8..000000000
--- a/platforms/ble/ble_client_adaptor_test.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package ble
-
-import (
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-
- "gobot.io/x/gobot/v2"
-)
-
-var _ gobot.Adaptor = (*ClientAdaptor)(nil)
-
-func TestBLEClientAdaptor(t *testing.T) {
- a := NewClientAdaptor("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")
- a.SetName("awesome")
- assert.Equal(t, "awesome", a.Name())
-}
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/uuid.go b/platforms/ble/uuid.go
deleted file mode 100644
index da0c47f6f..000000000
--- a/platforms/ble/uuid.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package ble
-
-import (
- "fmt"
- "strconv"
-
- "tinygo.org/x/bluetooth"
-)
-
-func convertUUID(cUUID string) string {
- switch len(cUUID) {
- case 4:
- // convert to full uuid from "22bb"
- uid, e := strconv.ParseUint("0x"+cUUID, 0, 16)
- if e != nil {
- return ""
- }
-
- uuid := bluetooth.New16BitUUID(uint16(uid))
- return uuid.String()
-
- 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])
- }
-
- return cUUID
-}
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 77%
rename from platforms/ble/README.md
rename to platforms/bleclient/README.md
index 5871bd6fe..8655f7526 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,16 +61,21 @@ 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() {
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)
})
}
@@ -84,6 +85,8 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
diff --git a/platforms/bleclient/ble_client_adaptor.go b/platforms/bleclient/ble_client_adaptor.go
new file mode 100644
index 000000000..c6e336f80
--- /dev/null
+++ b/platforms/bleclient/ble_client_adaptor.go
@@ -0,0 +1,259 @@
+package bleclient
+
+import (
+ "fmt"
+ "log"
+ "sync"
+ "time"
+
+ "tinygo.org/x/bluetooth"
+
+ "gobot.io/x/gobot/v2"
+)
+
+type configuration struct {
+ scanTimeout time.Duration
+ sleepAfterDisconnect time.Duration
+ debug bool
+}
+
+// Adaptor represents a Client Connection to a BLE Peripheral
+type Adaptor struct {
+ name string
+ identifier string
+ cfg *configuration
+
+ btAdpt *btAdapter
+ btDevice *btDevice
+ characteristics map[string]bluetoothExtCharacteristicer
+
+ connected bool
+ rssi int
+
+ btAdptCreator btAdptCreatorFunc
+ mutex *sync.Mutex
+}
+
+// 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)
+}
+
+// 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 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 (has no effect at the moment).
+func (a *Adaptor) WithoutResponses(bool) {}
+
+// Connect initiates a connection to the BLE peripheral.
+func (a *Adaptor) Connect() error {
+ a.mutex.Lock()
+ defer a.mutex.Unlock()
+
+ var err error
+
+ if a.cfg.debug {
+ fmt.Println("[Connect]: enable adaptor...")
+ }
+
+ // 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
+ }
+
+ 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
+ }
+
+ 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 _, 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 {
+ 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.
+func (a *Adaptor) Reconnect() error {
+ if a.connected {
+ if err := a.Disconnect(); err != nil {
+ return err
+ }
+ }
+ return a.Connect()
+}
+
+// Disconnect terminates the connection to the BLE peripheral.
+func (a *Adaptor) Disconnect() error {
+ 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
+}
+
+// Finalize finalizes the BLEAdaptor
+func (a *Adaptor) Finalize() error {
+ return a.Disconnect()
+}
+
+// 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")
+ }
+
+ cUUID, err := convertUUID(cUUID)
+ if err != nil {
+ return nil, err
+ }
+
+ if chara, ok := a.characteristics[cUUID]; ok {
+ return readFromCharacteristic(chara)
+ }
+
+ return nil, fmt.Errorf("unknown characteristic: %s", cUUID)
+}
+
+// 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")
+ }
+
+ cUUID, err := convertUUID(cUUID)
+ if err != nil {
+ return err
+ }
+
+ if chara, ok := a.characteristics[cUUID]; ok {
+ return writeToCharacteristicWithoutResponse(chara, data)
+ }
+
+ return fmt.Errorf("unknown characteristic: %s", cUUID)
+}
+
+// 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, err := convertUUID(cUUID)
+ if err != nil {
+ return err
+ }
+
+ if chara, ok := a.characteristics[cUUID]; ok {
+ return enableNotificationsForCharacteristic(chara, f)
+ }
+
+ 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
new file mode 100644
index 000000000..614c6a04c
--- /dev/null
+++ b/platforms/bleclient/ble_client_adaptor_test.go
@@ -0,0 +1,407 @@
+package bleclient
+
+import (
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "gobot.io/x/gobot/v2"
+)
+
+var (
+ _ gobot.Adaptor = (*Adaptor)(nil)
+ _ gobot.BLEConnector = (*Adaptor)(nil)
+)
+
+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 TestName(t *testing.T) {
+ a := NewAdaptor("D7:99:5A:26:EC:38")
+ 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/doc.go b/platforms/bleclient/doc.go
new file mode 100644
index 000000000..29449f8e5
--- /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/release/platforms/bleclient/README.md
+*/
+package bleclient // import "gobot.io/x/gobot/v2/platforms/bleclient"
diff --git a/platforms/bleclient/helpers_test.go b/platforms/bleclient/helpers_test.go
new file mode 100644
index 000000000..459d9b412
--- /dev/null
+++ b/platforms/bleclient/helpers_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
new file mode 100644
index 000000000..ddec347a5
--- /dev/null
+++ b/platforms/bleclient/uuid.go
@@ -0,0 +1,40 @@
+package bleclient
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "tinygo.org/x/bluetooth"
+)
+
+// 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:
+ 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)
+ }
+ return bluetooth.New16BitUUID(uint16(uid)).String(), nil
+ case 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 "", 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)
+ })
+ }
+}
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/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/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/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 95813e2bc..b53687033 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,10 +60,14 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
+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 7d715ab8c..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 (
@@ -37,10 +40,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
@@ -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 4a6477dfa..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.
@@ -26,7 +29,9 @@ Example:
work := func() {
gobot.Every(1*time.Second, func() {
- led.Toggle()
+ if err := led.Toggle(); err != nil {
+ fmt.Println(err)
+ }
})
}
@@ -36,10 +41,12 @@ Example:
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
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/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/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/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/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/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/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/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/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/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/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/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/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..f93f9152a 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,10 +35,12 @@ Example:
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
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/firmata/firmata_adaptor.go b/platforms/firmata/firmata_adaptor.go
index 24f64f9c5..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
}
@@ -116,23 +116,23 @@ 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
-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/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..69f3403ca 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)
+ }
}
```
@@ -74,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:
@@ -82,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/curie/imu_driver.go b/platforms/intel-iot/curie/imu_driver.go
index 15998c84d..340c37d6c 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
@@ -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/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/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/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/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/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/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/intel-iot/joule/joule_adaptor.go b/platforms/intel-iot/joule/joule_adaptor.go
index 5706ac233..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 {
@@ -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/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/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/jetson/jetson_adaptor.go b/platforms/jetson/jetson_adaptor.go
index 6ef35239a..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 {
@@ -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/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/bin/scanner.go b/platforms/joystick/bin/scanner.go
index 2940ed605..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/doc.go b/platforms/mavlink/doc.go
index b88fcf757..8fee54f6b 100644
--- a/platforms/mavlink/doc.go
+++ b/platforms/mavlink/doc.go
@@ -59,10 +59,12 @@ Example:
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
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/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 abc0a675e..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 (
@@ -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/megapi/README.md b/platforms/megapi/README.md
index f4200b919..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,11 +43,13 @@ func main() {
}
robot := gobot.NewRobot("megaPiBot",
- []gobot.Connection{megaPiAdaptor},
+ []gobot.Connection{adaptor},
[]gobot.Device{motor},
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
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/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/microbit/README.md b/platforms/microbit/README.md
index f4342e64c..ba0f30423 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,16 +42,18 @@ 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() {
- ubit.Blank()
+ if err := ubit.Blank(); err != nil {
+ fmt.Println(err)
+ }
gobot.After(1*time.Second, func() {
ubit.WriteText("Hello")
})
@@ -71,7 +68,9 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
@@ -89,23 +88,27 @@ 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")
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)
+ }
})
}
@@ -115,7 +118,9 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
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/accelerometer_driver_test.go b/platforms/microbit/accelerometer_driver_test.go
deleted file mode 100644
index 33ea547a5..000000000
--- a/platforms/microbit/accelerometer_driver_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-//nolint:forcetypeassert,dupl // ok here
-package microbit
-
-import (
- "strings"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- "gobot.io/x/gobot/v2"
-)
-
-var _ gobot.Driver = (*AccelerometerDriver)(nil)
-
-func initTestAccelerometerDriver() *AccelerometerDriver {
- d := NewAccelerometerDriver(NewBleTestAdaptor())
- return d
-}
-
-func TestAccelerometerDriver(t *testing.T) {
- d := initTestAccelerometerDriver()
- assert.True(t, strings.HasPrefix(d.Name(), "Microbit Accelerometer"))
- d.SetName("NewName")
- assert.Equal(t, "NewName", d.Name())
-}
-
-func TestAccelerometerDriverStartAndHalt(t *testing.T) {
- d := initTestAccelerometerDriver()
- require.NoError(t, d.Start())
- require.NoError(t, d.Halt())
-}
-
-func TestAccelerometerDriverReadData(t *testing.T) {
- sem := make(chan bool)
- a := NewBleTestAdaptor()
- d := NewAccelerometerDriver(a)
- _ = d.Start()
- _ = 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)
-
- select {
- case <-sem:
- case <-time.After(100 * time.Millisecond):
- t.Errorf("Microbit Event \"Accelerometer\" was not published")
- }
-}
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/button_driver_test.go b/platforms/microbit/button_driver_test.go
deleted file mode 100644
index be92c0ed7..000000000
--- a/platforms/microbit/button_driver_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package microbit
-
-import (
- "strings"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- "gobot.io/x/gobot/v2"
-)
-
-var _ gobot.Driver = (*ButtonDriver)(nil)
-
-func initTestButtonDriver() *ButtonDriver {
- d := NewButtonDriver(NewBleTestAdaptor())
- return d
-}
-
-func TestButtonDriver(t *testing.T) {
- d := initTestButtonDriver()
- assert.True(t, strings.HasPrefix(d.Name(), "Microbit Button"))
- d.SetName("NewName")
- assert.Equal(t, "NewName", d.Name())
-}
-
-func TestButtonDriverStartAndHalt(t *testing.T) {
- d := initTestButtonDriver()
- require.NoError(t, d.Start())
- require.NoError(t, d.Halt())
-}
-
-func TestButtonDriverReadData(t *testing.T) {
- sem := make(chan bool)
- a := NewBleTestAdaptor()
- d := NewButtonDriver(a)
- _ = d.Start()
- _ = d.On(ButtonB, func(data interface{}) {
- sem <- true
- })
-
- a.TestReceiveNotification([]byte{1}, nil)
-
- select {
- case <-sem:
- case <-time.After(100 * time.Millisecond):
- t.Errorf("Microbit Event \"ButtonB\" was not published")
- }
-}
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/helpers_test.go b/platforms/microbit/helpers_test.go
deleted file mode 100644
index acf446f2d..000000000
--- a/platforms/microbit/helpers_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package microbit
-
-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
-
- testSubscribe func([]byte, error)
- 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 {
- t.testSubscribe = f
- 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 (t *bleTestClientAdaptor) TestReceiveNotification(data []byte, err error) {
- t.mtx.Lock()
- defer t.mtx.Unlock()
- t.testSubscribe(data, err)
-}
-
-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) {},
- }
-}
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/led_driver_test.go b/platforms/microbit/led_driver_test.go
deleted file mode 100644
index a59039dfb..000000000
--- a/platforms/microbit/led_driver_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package microbit
-
-import (
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- "gobot.io/x/gobot/v2"
-)
-
-var _ gobot.Driver = (*LEDDriver)(nil)
-
-func initTestLEDDriver() *LEDDriver {
- d := NewLEDDriver(NewBleTestAdaptor())
- return d
-}
-
-func TestLEDDriver(t *testing.T) {
- d := initTestLEDDriver()
- 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())
-}
-
-func TestLEDDriverWriteMatrix(t *testing.T) {
- d := initTestLEDDriver()
- _ = d.Start()
- require.NoError(t, d.WriteMatrix([]byte{0x01, 0x02}))
-}
-
-func TestLEDDriverWriteText(t *testing.T) {
- d := initTestLEDDriver()
- _ = d.Start()
- require.NoError(t, d.WriteText("Hello"))
-}
-
-func TestLEDDriverCommands(t *testing.T) {
- d := initTestLEDDriver()
- _ = d.Start()
- 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.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/magnetometer_driver_test.go b/platforms/microbit/magnetometer_driver_test.go
deleted file mode 100644
index 5a7d31f1f..000000000
--- a/platforms/microbit/magnetometer_driver_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-//nolint:forcetypeassert,dupl // ok here
-package microbit
-
-import (
- "strings"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- "gobot.io/x/gobot/v2"
-)
-
-var _ gobot.Driver = (*MagnetometerDriver)(nil)
-
-func initTestMagnetometerDriver() *MagnetometerDriver {
- d := NewMagnetometerDriver(NewBleTestAdaptor())
- return d
-}
-
-func TestMagnetometerDriver(t *testing.T) {
- d := initTestMagnetometerDriver()
- assert.True(t, strings.HasPrefix(d.Name(), "Microbit Magnetometer"))
- d.SetName("NewName")
- assert.Equal(t, "NewName", d.Name())
-}
-
-func TestMagnetometerDriverStartAndHalt(t *testing.T) {
- d := initTestMagnetometerDriver()
- require.NoError(t, d.Start())
- require.NoError(t, d.Halt())
-}
-
-func TestMagnetometerDriverReadData(t *testing.T) {
- sem := make(chan bool)
- a := NewBleTestAdaptor()
- d := NewMagnetometerDriver(a)
- _ = d.Start()
- _ = 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
- })
-
- a.TestReceiveNotification([]byte{0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, nil)
-
- select {
- case <-sem:
- case <-time.After(100 * time.Millisecond):
- t.Errorf("Microbit Event \"Magnetometer\" was not published")
- }
-}
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/microbit/temperature_driver_test.go b/platforms/microbit/temperature_driver_test.go
deleted file mode 100644
index 3d4a81db9..000000000
--- a/platforms/microbit/temperature_driver_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package microbit
-
-import (
- "strings"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- "gobot.io/x/gobot/v2"
-)
-
-var _ gobot.Driver = (*TemperatureDriver)(nil)
-
-func initTestTemperatureDriver() *TemperatureDriver {
- d := NewTemperatureDriver(NewBleTestAdaptor())
- return d
-}
-
-func TestTemperatureDriver(t *testing.T) {
- d := initTestTemperatureDriver()
- assert.True(t, strings.HasPrefix(d.Name(), "Microbit Temperature"))
- d.SetName("NewName")
- assert.Equal(t, "NewName", d.Name())
-}
-
-func TestTemperatureDriverStartAndHalt(t *testing.T) {
- d := initTestTemperatureDriver()
- require.NoError(t, d.Start())
- require.NoError(t, d.Halt())
-}
-
-func TestTemperatureDriverReadData(t *testing.T) {
- sem := make(chan bool)
- a := NewBleTestAdaptor()
- d := NewTemperatureDriver(a)
- _ = d.Start()
- _ = d.On(Temperature, func(data interface{}) {
- assert.Equal(t, int8(0x22), data)
- sem <- true
- })
-
- a.TestReceiveNotification([]byte{0x22}, nil)
-
- select {
- case <-sem:
- case <-time.After(100 * time.Millisecond):
- t.Errorf("Microbit Event \"Temperature\" was not published")
- }
-}
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/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/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/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/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/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/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/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
diff --git a/platforms/neurosky/README.md b/platforms/neurosky/README.md
index 68ec33cc4..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,66 +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,
- )
-
- robot.Start()
-}
-```
+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 d4afbff6a..000000000
--- a/platforms/neurosky/doc.go
+++ /dev/null
@@ -1,68 +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,
- )
-
- robot.Start()
- }
-
-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/opencv/README.md b/platforms/opencv/README.md
index f45dad612..8f7f64c18 100644
--- a/platforms/opencv/README.md
+++ b/platforms/opencv/README.md
@@ -64,6 +64,10 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
+
+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 9a475bcc9..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 (
@@ -45,7 +48,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/opencv/doc.go b/platforms/opencv/doc.go
index ecd83ce15..339734a13 100644
--- a/platforms/opencv/doc.go
+++ b/platforms/opencv/doc.go
@@ -34,10 +34,12 @@ Example:
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
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/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/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/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..75c91cba3 100644
--- a/platforms/parrot/ardrone/doc.go
+++ b/platforms/parrot/ardrone/doc.go
@@ -35,10 +35,12 @@ Example:
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
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/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/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/parrot/bebop/client/client.go b/platforms/parrot/bebop/client/client.go
index 08451c1b4..81da02887 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,
@@ -238,7 +194,6 @@ func (b *Bebop) Discover() error {
data := make([]byte, 10240)
_, err = b.discoveryClient.Read(data)
-
if err != nil {
return err
}
@@ -258,7 +213,6 @@ func (b *Bebop) Connect() error {
}
b.c2dClient, err = net.DialUDP("udp", nil, c2daddr)
-
if err != nil {
return err
}
@@ -332,7 +286,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 +306,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 +326,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 +346,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 {
@@ -481,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)
}
@@ -516,7 +475,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 +487,15 @@ 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)}),
+ //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)),
)
}
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 +539,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 +610,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 +639,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 +664,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 +689,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 {
@@ -801,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)
}
@@ -826,5 +789,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/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/bebop/client/networkframegenerator.go b/platforms/parrot/bebop/client/networkframegenerator.go
new file mode 100644
index 000000000..44b189428
--- /dev/null
+++ b/platforms/parrot/bebop/client/networkframegenerator.go
@@ -0,0 +1,60 @@
+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]++ // automatically rollover to 0 when > 255 is fine
+
+ ret := &bytes.Buffer{}
+ ret.WriteByte(frameType)
+ ret.WriteByte(id)
+ 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)
+ }
+
+ ret.Write(size.Bytes())
+ ret.Write(cmd.Bytes())
+
+ return ret
+}
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/parrot/minidrone/README.md b/platforms/parrot/minidrone/README.md
index 279d458dc..b52c5c2e5 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{}) {
@@ -82,7 +82,9 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
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/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/adaptor_test.go b/platforms/particle/adaptor_test.go
index ee79d51ec..6ddbcfb14 100644
--- a/platforms/particle/adaptor_test.go
+++ b/platforms/particle/adaptor_test.go
@@ -29,7 +29,8 @@ 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)
+ //nolint:testifylint // TODO: fix later
+ require.Fail(t, "Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path)
}
_, _ = w.Write(dummyData)
})
@@ -48,7 +49,8 @@ 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)
+ //nolint:testifylint // TODO: fix later
+ require.Fail(t, "Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path)
}
_ = r.ParseForm()
@@ -78,7 +80,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 +89,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/particle/doc.go b/platforms/particle/doc.go
index 467b65dec..01064744c 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,10 +35,12 @@ Example:
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
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/README.md b/platforms/pebble/README.md
index 0fa25a4a5..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,9 +52,11 @@ func main() {
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
```
diff --git a/platforms/pebble/doc.go b/platforms/pebble/doc.go
index 686eb837a..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,12 +47,14 @@ your computer IP, robot name is 'pebble' and robot api port is 8080
work,
)
- master.AddRobot(robot)
+ manager.AddRobot(robot)
- master.Start()
+ if err := manager.Start(); err != nil {
+ panic(err)
+ }
}
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/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/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/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/raspi/raspi_adaptor.go b/platforms/raspi/raspi_adaptor.go
index 1d917b19a..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
@@ -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/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/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/rockpi/rockpi_adaptor.go b/platforms/rockpi/rockpi_adaptor.go
index cf159a716..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()
@@ -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/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..605cb5706
--- /dev/null
+++ b/platforms/serialport/README.md
@@ -0,0 +1,12 @@
+# 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/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/adaptor.go b/platforms/serialport/adaptor.go
new file mode 100644
index 000000000..8af566039
--- /dev/null
+++ b/platforms/serialport/adaptor.go
@@ -0,0 +1,128 @@
+package serialport
+
+import (
+ "fmt"
+ "io"
+
+ "go.bug.st/serial"
+
+ "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 {
+ port string
+ cfg *configuration
+
+ sp io.ReadWriteCloser
+ connectFunc func(string, int) (io.ReadWriteCloser, error)
+}
+
+// NewAdaptor returns a new adaptor given a port for the serial communication
+func NewAdaptor(port string, opts ...optionApplier) *Adaptor {
+ cfg := configuration{
+ name: gobot.DefaultName("Serial"),
+ baudRate: 115200,
+ }
+
+ a := Adaptor{
+ cfg: &cfg,
+ port: port,
+ 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
+}
+
+// WithName is used to replace the default name of the driver.
+func WithName(name string) optionApplier {
+ return nameOption(name)
+}
+
+// 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 {
+ if a.sp != nil {
+ 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
+ }
+
+ a.sp = sp
+ return nil
+}
+
+// Finalize finalizes the adaptor by disconnect
+func (a *Adaptor) Finalize() error {
+ return a.Disconnect()
+}
+
+// Disconnect terminates the connection to the port.
+func (a *Adaptor) Disconnect() error {
+ if a.sp != nil {
+ if err := a.sp.Close(); err != nil {
+ return err
+ }
+ a.sp = nil
+ }
+ return nil
+}
+
+// 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.sp != nil {
+ if err := a.Disconnect(); err != nil {
+ return err
+ }
+ }
+ return a.Connect()
+}
+
+// Port returns the adaptors port
+func (a *Adaptor) Port() string { return a.port }
+
+// IsConnected returns the connection state
+func (a *Adaptor) IsConnected() bool {
+ return a.sp != nil
+}
+
+// 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(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
new file mode 100644
index 000000000..972011415
--- /dev/null
+++ b/platforms/serialport/adaptor_test.go
@@ -0,0 +1,155 @@
+package serialport
+
+import (
+ "errors"
+ "io"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "gobot.io/x/gobot/v2"
+)
+
+var _ gobot.Adaptor = (*Adaptor)(nil)
+
+func initTestAdaptor() (*Adaptor, *nullReadWriteCloser) {
+ a := NewAdaptor("/dev/null")
+ rwc := newNullReadWriteCloser()
+
+ a.connectFunc = func(string, int) (io.ReadWriteCloser, error) {
+ return rwc, nil
+ }
+
+ if err := a.Connect(); err != nil {
+ panic(err)
+ }
+ return a, rwc
+}
+
+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 TestSerialRead(t *testing.T) {
+ tests := map[string]struct {
+ readDataBuffer []byte
+ simReadErr bool
+ wantCount int
+ wantErr string
+ }{
+ "read_ok": {
+ readDataBuffer: []byte{0, 0},
+ wantCount: 2,
+ },
+ "error_read": {
+ readDataBuffer: []byte{},
+ simReadErr: true,
+ wantErr: "read error",
+ },
+ }
+ 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)
+ })
+ }
+}
+
+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 TestConnect(t *testing.T) {
+ // arrange
+ a, _ := initTestAdaptor()
+ 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.sp = nil
+ 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.NotNil(t, a.sp)
+ // act & assert
+ require.NoError(t, a.Reconnect())
+ require.NotNil(t, a.sp)
+ // act & assert
+ require.NoError(t, a.Disconnect())
+ require.Nil(t, a.sp)
+ // act & assert
+ require.NoError(t, a.Reconnect())
+ require.NotNil(t, a.sp)
+}
+
+func TestFinalize(t *testing.T) {
+ // arrange
+ a, rwc := initTestAdaptor()
+ // act & assert
+ require.NoError(t, a.Finalize())
+ assert.False(t, a.IsConnected())
+ // re-arrange error
+ rwc.simulateCloseErr = true
+ require.NoError(t, a.Connect())
+ // act & assert
+ require.ErrorContains(t, a.Finalize(), "close error")
+}
diff --git a/platforms/serialport/doc.go b/platforms/serialport/doc.go
new file mode 100644
index 000000000..ed03a6260
--- /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/release/platforms/serialport/README.md
+*/
+package serialport // import "gobot.io/x/gobot/v2/platforms/serialport"
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/bb8/README.md b/platforms/sphero/bb8/README.md
index b097ae57b..fa1d77ea8 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() {
@@ -39,7 +39,10 @@ func main() {
work,
)
- robot.Start()
+ err := robot.Start()
+ if err != nil {
+ fmt.Println(err)
+ }
}
```
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..48cc3bb1d 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() {
@@ -39,7 +39,10 @@ func main() {
work,
)
- robot.Start()
+ err := robot.Start()
+ if err != nil {
+ fmt.Println(err)
+ }
}
```
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 76%
rename from platforms/sphero/README.md
rename to platforms/sphero/sphero/README.md
index 9132c6368..b7ff9c62e 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,11 +64,12 @@ 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")
+ adaptor := serialport.NewAdaptor("/dev/rfcomm0")
driver := sphero.NewSpheroDriver(adaptor)
work := func() {
@@ -82,6 +84,8 @@ func main() {
work,
)
- robot.Start()
+ if err := robot.Start(); err != nil {
+ panic(err)
+ }
}
```
diff --git a/platforms/sphero/sphero_adaptor.go b/platforms/sphero/sphero_adaptor.go
deleted file mode 100644
index d71f10666..000000000
--- a/platforms/sphero/sphero_adaptor.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package sphero
-
-import (
- "io"
-
- "go.bug.st/serial"
-
- "gobot.io/x/gobot/v2"
-)
-
-// Adaptor represents a Connection to a Sphero
-type Adaptor struct {
- name string
- port string
- sp io.ReadWriteCloser
- connected bool
- connect func(string) (io.ReadWriteCloser, error)
-}
-
-// NewAdaptor returns a new Sphero Adaptor given a port
-func NewAdaptor(port string) *Adaptor {
- return &Adaptor{
- name: gobot.DefaultName("Sphero"),
- port: port,
- connect: func(port string) (io.ReadWriteCloser, error) {
- return serial.Open(port, &serial.Mode{BaudRate: 115200})
- },
- }
-}
-
-// Name returns the Adaptor's name
-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.
-func (a *Adaptor) Connect() error {
- sp, err := a.connect(a.Port())
- if err != nil {
- return err
- }
-
- a.sp = sp
- a.connected = true
- 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()
-}
-
-// Disconnect terminates the connection to the Sphero. Returns true on successful disconnect.
-func (a *Adaptor) Disconnect() error {
- if a.connected {
- if err := a.sp.Close(); err != nil {
- return err
- }
- a.connected = false
- }
- return nil
-}
-
-// Finalize finalizes the Sphero Adaptor
-func (a *Adaptor) Finalize() error {
- return a.Disconnect()
-}
diff --git a/platforms/sphero/sphero_adaptor_test.go b/platforms/sphero/sphero_adaptor_test.go
deleted file mode 100644
index a364e14c0..000000000
--- a/platforms/sphero/sphero_adaptor_test.go
+++ /dev/null
@@ -1,106 +0,0 @@
-package sphero
-
-import (
- "errors"
- "io"
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- "gobot.io/x/gobot/v2"
-)
-
-var _ gobot.Adaptor = (*Adaptor)(nil)
-
-type nullReadWriteCloser struct {
- testAdaptorRead func(p []byte) (int, error)
- testAdaptorWrite func(b []byte) (int, error)
- testAdaptorClose func() error
-}
-
-func (n *nullReadWriteCloser) Write(p []byte) (int, error) {
- return n.testAdaptorWrite(p)
-}
-
-func (n *nullReadWriteCloser) Read(b []byte) (int, error) {
- return n.testAdaptorRead(b)
-}
-
-func (n *nullReadWriteCloser) Close() error {
- return n.testAdaptorClose()
-}
-
-func NewNullReadWriteCloser() *nullReadWriteCloser {
- return &nullReadWriteCloser{
- testAdaptorRead: func(p []byte) (int, error) {
- return len(p), nil
- },
- testAdaptorWrite: func(b []byte) (int, error) {
- return len(b), nil
- },
- testAdaptorClose: func() error {
- return nil
- },
- }
-}
-
-func initTestSpheroAdaptor() (*Adaptor, *nullReadWriteCloser) {
- a := NewAdaptor("/dev/null")
- rwc := NewNullReadWriteCloser()
-
- a.connect = func(string) (io.ReadWriteCloser, error) {
- return rwc, nil
- }
- return a, rwc
-}
-
-func TestSpheroAdaptorName(t *testing.T) {
- a, _ := initTestSpheroAdaptor()
- assert.True(t, strings.HasPrefix(a.Name(), "Sphero"))
- 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.Equal(t, "/dev/null", a.Port())
-}
-
-func TestSpheroAdaptorReconnect(t *testing.T) {
- a, _ := initTestSpheroAdaptor()
- _ = a.Connect()
- assert.True(t, a.connected)
- _ = a.Reconnect()
- assert.True(t, a.connected)
- _ = a.Disconnect()
- assert.False(t, a.connected)
- _ = a.Reconnect()
- assert.True(t, a.connected)
-}
-
-func TestSpheroAdaptorFinalize(t *testing.T) {
- a, rwc := initTestSpheroAdaptor()
- _ = a.Connect()
- require.NoError(t, a.Finalize())
-
- rwc.testAdaptorClose = func() error {
- return errors.New("close error")
- }
-
- a.connected = true
- require.ErrorContains(t, a.Finalize(), "close error")
-}
-
-func TestSpheroAdaptorConnect(t *testing.T) {
- a, _ := initTestSpheroAdaptor()
- 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/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..c6ab58a7c 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() {
@@ -39,7 +39,10 @@ func main() {
work,
)
- robot.Start()
+ err := robot.Start()
+ if err != nil {
+ fmt.Println(err)
+ }
}
```
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,
- }
-}
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/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/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/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
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
+ }
}
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/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 8c8e9f077..f941424ba 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
@@ -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 b7b473885..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 (
@@ -34,7 +35,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/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/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() {
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
}
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)
}
}