From 603fe264f5bc6a37660b90d129d5e25c9d756657 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 9 Sep 2023 11:07:54 +0200 Subject: [PATCH 01/13] platforms/joystick: remove sdl based joystick and replace with @0xcafed00d package Signed-off-by: deadprogram --- go.mod | 1 + go.sum | 2 + platforms/joystick/LICENSE | 2 +- platforms/joystick/README.md | 52 +----- platforms/joystick/configs/dualshock3.json | 12 +- platforms/joystick/doc.go | 2 +- platforms/joystick/joystick_adaptor.go | 26 +-- platforms/joystick/joystick_adaptor_test.go | 8 +- platforms/joystick/joystick_driver.go | 103 +++++------ platforms/joystick/joystick_driver_test.go | 189 ++++++++++---------- platforms/joystick/joystick_dualshock3.go | 8 + platforms/joystick/test_helper.go | 8 +- 12 files changed, 196 insertions(+), 217 deletions(-) diff --git a/go.mod b/go.mod index 044643eea..b68ef9ba1 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module gobot.io/x/gobot/v2 go 1.18 require ( + github.com/0xcafed00d/joystick v1.0.1 github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 github.com/eclipse/paho.mqtt.golang v1.4.2 diff --git a/go.sum b/go.sum index f590e4b61..933d96db1 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/0xcafed00d/joystick v1.0.1 h1:r4p2cRp4MHJWu1gArhGtumbkPxmr3tcOUTFqybEhplM= +github.com/0xcafed00d/joystick v1.0.1/go.mod h1:gzszjNgzP6jtCAeSdC9OqPVO5rO7TJuaw4P7eAjNzx8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/bgould/http v0.0.0-20190627042742-d268792bdee7/go.mod h1:BTqvVegvwifopl4KTEDth6Zezs9eR+lCWhvGKvkxJHE= github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f h1:gOO/tNZMjjvTKZWpY7YnXC72ULNLErRtp94LountVE8= diff --git a/platforms/joystick/LICENSE b/platforms/joystick/LICENSE index 257d22e97..f90ffa280 100644 --- a/platforms/joystick/LICENSE +++ b/platforms/joystick/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2018 The Hybrid Group +Copyright (c) 2014-2023 The Hybrid Group Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/platforms/joystick/README.md b/platforms/joystick/README.md index 5e4b9d2cc..d365f264e 100644 --- a/platforms/joystick/README.md +++ b/platforms/joystick/README.md @@ -1,6 +1,6 @@ # Joystick -You can use Gobot with any USB joystick or game controller that is compatible with [Simple DirectMedia Layer](http://www.libsdl.org/). +You can use Gobot with many USB joysticks and game controllers. Current configurations included: @@ -14,41 +14,24 @@ Current configurations included: ## How to Install -This package requires `sdl2` to be installed on your system +Any platform specific info here... ### macOS -To install `sdl2` on macOS using Homebrew: - -```sh -brew install sdl2 -``` - -To use an XBox360 controller on macOS, you will most likely need to install additional software such as [https://github.com/360Controller/360Controller](https://github.com/360Controller/360Controller). ### Linux (Ubuntu and Raspbian) -Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) -You must be running a Linux kernel that is v4.14+ in order for the various controller mappings to work as expected. +### Windows -Then you must install the latest SDL2 v2.0.8 or greater: - -```sh -wget https://www.libsdl.org/release/SDL2-2.0.8.tar.gz -tar -zxvf SDL2-2.0.8.tar.gz -cd SDL2-2.0.8/ -./configure && make && sudo make install -``` ## How to Use -Controller configurations are stored in Gobot it, but you can also use external file in JSON format. Take a look at the -`configs` directory for examples. +Controller configurations are stored in Gobot, but you can also use external file in JSON format. Take a look at the `configs` directory for examples. ## How to Connect -Plug your USB joystick or game controller into your USB port. If your device is supported by SDL, you are now ready. +Plug your USB joystick or game controller into your USB port. If your device is supported by your operating system, it might prompt you to install some system drivers. For the Dualshock4, you must pair the device with your computers Bluetooth interface first, before running your Gobot program. @@ -67,7 +50,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, "dualshock3", ) @@ -151,25 +134,4 @@ func main() { ## How to Add A New Joystick -In the `bin` directory for this package is a CLI utility program that scans for SDL joystick events, and displays the ID -and value: - -```sh -$ go run ./platforms/joystick/bin/scanner.go -Joystick 0 connected -[6625 ms] Axis: 1 value:-22686 -[6641 ms] Axis: 1 value:-32768 -[6836 ms] Axis: 1 value:-18317 -[6852 ms] Axis: 1 value:0 -[8663 ms] Axis: 3 value:-32768 -[8873 ms] Axis: 3 value:0 -[10183 ms] Axis: 0 value:-24703 -[10183 ms] Axis: 0 value:-32768 -[10313 ms] Axis: 1 value:-3193 -[10329 ms] Axis: 1 value:0 -[10345 ms] Axis: 0 value:0 -``` - -You can use the output from this program to create a JSON file for the various buttons and axes on your joystick/gamepad. -You could also create a file similar to `joystick_dualshock3.go` and submit a pull request with the new configuration so -others can use it as well. +You can create a file similar to `joystick_dualshock3.go` and submit a pull request with the new configuration so others can use it as well. diff --git a/platforms/joystick/configs/dualshock3.json b/platforms/joystick/configs/dualshock3.json index f74f5b963..24195932e 100644 --- a/platforms/joystick/configs/dualshock3.json +++ b/platforms/joystick/configs/dualshock3.json @@ -11,12 +11,20 @@ "id": 1 }, { - "name": "right_x", + "name": "l2", "id": 2 }, { - "name": "right_y", + "name": "right_x", "id": 3 + }, + { + "name": "right_y", + "id": 4 + }, + { + "name": "r2", + "id": 5 } ], "buttons": [ diff --git a/platforms/joystick/doc.go b/platforms/joystick/doc.go index c0f7c8f60..a89979569 100644 --- a/platforms/joystick/doc.go +++ b/platforms/joystick/doc.go @@ -19,7 +19,7 @@ Example: ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) joystick := joystick.NewDriver(joystickAdaptor, "./platforms/joystick/configs/dualshock3.json", ) diff --git a/platforms/joystick/joystick_adaptor.go b/platforms/joystick/joystick_adaptor.go index 2d5f93789..743588d05 100644 --- a/platforms/joystick/joystick_adaptor.go +++ b/platforms/joystick/joystick_adaptor.go @@ -1,38 +1,40 @@ package joystick import ( - "errors" + "fmt" "gobot.io/x/gobot/v2" - "github.com/veandco/go-sdl2/sdl" + js "github.com/0xcafed00d/joystick" ) type joystick interface { Close() - InstanceID() sdl.JoystickID + ID() int } // Adaptor represents a connection to a joystick type Adaptor struct { name string - joystick joystick + id int + joystick js.Joystick connect func(*Adaptor) error } // NewAdaptor returns a new Joystick Adaptor. -func NewAdaptor() *Adaptor { +// Pass in the ID of the joystick you wish to connect to. +func NewAdaptor(id int) *Adaptor { return &Adaptor{ name: gobot.DefaultName("Joystick"), connect: func(j *Adaptor) error { - if err := sdl.Init(sdl.INIT_JOYSTICK); err != nil { - return err + joy, err := js.Open(id) + if err != nil { + return fmt.Errorf("No joystick available: %v", err) } - if sdl.NumJoysticks() > 0 { - j.joystick = sdl.JoystickOpen(0) - return nil - } - return errors.New("No joystick available") + + j.id = id + j.joystick = joy + return nil }, } } diff --git a/platforms/joystick/joystick_adaptor_test.go b/platforms/joystick/joystick_adaptor_test.go index 4f11ca06a..2c07b5dfc 100644 --- a/platforms/joystick/joystick_adaptor_test.go +++ b/platforms/joystick/joystick_adaptor_test.go @@ -1,7 +1,6 @@ package joystick import ( - "errors" "strings" "testing" @@ -12,7 +11,7 @@ import ( var _ gobot.Adaptor = (*Adaptor)(nil) func initTestAdaptor() *Adaptor { - a := NewAdaptor() + a := NewAdaptor(6) a.connect = func(j *Adaptor) (err error) { j.joystick = &testJoystick{} return nil @@ -31,8 +30,9 @@ func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() gobottest.Assert(t, a.Connect(), nil) - a = NewAdaptor() - gobottest.Assert(t, a.Connect(), errors.New("No joystick available")) + a = NewAdaptor(6) + err := a.Connect() + gobottest.Assert(t, strings.HasPrefix(err.Error(), "No joystick available"), true) } func TestAdaptorFinalize(t *testing.T) { diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index 09634c234..1db3fcc78 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -6,8 +6,8 @@ import ( "os" "time" - "github.com/veandco/go-sdl2/sdl" "gobot.io/x/gobot/v2" + js "github.com/0xcafed00d/joystick" ) const ( @@ -46,7 +46,9 @@ type Driver struct { connection gobot.Connection configPath string config joystickConfig - poll func() sdl.Event + buttonState map[int]bool + axisState map[int]int + halt chan bool gobot.Eventer } @@ -86,9 +88,9 @@ func NewDriver(a *Adaptor, config string, v ...time.Duration) *Driver { connection: a, Eventer: gobot.NewEventer(), configPath: config, - poll: func() sdl.Event { - return sdl.PollEvent() - }, + buttonState: make(map[int]bool), + axisState: make(map[int]int), + interval: 10 * time.Millisecond, halt: make(chan bool), } @@ -159,18 +161,17 @@ func (j *Driver) Start() (err error) { for _, value := range j.config.Axis { j.AddEvent(value.Name) } - for _, value := range j.config.Hats { - j.AddEvent(fmt.Sprintf("%s_press", value.Name)) - j.AddEvent(fmt.Sprintf("%s_release", value.Name)) - } go func() { for { - for event := j.poll(); event != nil; event = j.poll() { - if errs := j.handleEvent(event); errs != nil { - j.Publish(j.Event("error"), errs) - } + state, err := j.adaptor().joystick.Read() + if err != nil { + j.Publish(j.Event("error"), err) + break } + j.handleButtons(state) + j.handleAxes(state) + select { case <-time.After(j.interval): case <-j.halt: @@ -189,46 +190,48 @@ func (j *Driver) Halt() (err error) { var previousHat = "" -// HandleEvent publishes an specific event according to data received -func (j *Driver) handleEvent(event sdl.Event) error { - switch data := event.(type) { - case *sdl.JoyAxisEvent: - if data.Which == j.adaptor().joystick.InstanceID() { - axis := j.findName(data.Axis, j.config.Axis) - if axis == "" { - return fmt.Errorf("Unknown Axis: %v", data.Axis) +func (j *Driver) handleButtons(state js.State) error { + for button := 0; button < j.adaptor().joystick.ButtonCount(); button++ { + switch { + case state.Buttons&(1< Date: Sat, 9 Sep 2023 11:09:05 +0200 Subject: [PATCH 02/13] examples: modify consumers of joystick.NewAdaptor() to pass joystick ID as is now required Signed-off-by: deadprogram --- examples/ardrone_ps3.go | 2 +- examples/bebop_ps3.go | 2 +- examples/bebop_ps3_video.go | 2 +- examples/joystick_ps3.go | 26 +++++++++++++++++++- examples/joystick_ps4.go | 2 +- examples/joystick_ps5.go | 2 +- examples/joystick_xbox360.go | 2 +- examples/joystick_xbox360_rock_band_drums.go | 2 +- examples/joystick_xboxone.go | 2 +- examples/minidrone_mambo_ps3.go | 2 +- examples/minidrone_ps3.go | 2 +- examples/tello_facetracker.go | 2 +- examples/tello_ps3.go | 2 +- 13 files changed, 37 insertions(+), 13 deletions(-) diff --git a/examples/ardrone_ps3.go b/examples/ardrone_ps3.go index d7aad83e0..c21b84352 100644 --- a/examples/ardrone_ps3.go +++ b/examples/ardrone_ps3.go @@ -25,7 +25,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, "dualshock3") ardroneAdaptor := ardrone.NewAdaptor() diff --git a/examples/bebop_ps3.go b/examples/bebop_ps3.go index 93b514348..7b33ffa91 100644 --- a/examples/bebop_ps3.go +++ b/examples/bebop_ps3.go @@ -25,7 +25,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, "dualshock3") bebopAdaptor := bebop.NewAdaptor() diff --git a/examples/bebop_ps3_video.go b/examples/bebop_ps3_video.go index 74b38b672..7e57e7169 100644 --- a/examples/bebop_ps3_video.go +++ b/examples/bebop_ps3_video.go @@ -83,7 +83,7 @@ func ffmpeg() (stdin io.WriteCloser, stderr io.ReadCloser, err error) { } func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, "dualshock3") bebopAdaptor := bebop.NewAdaptor() diff --git a/examples/joystick_ps3.go b/examples/joystick_ps3.go index 2cdb55bc4..762f79b2b 100644 --- a/examples/joystick_ps3.go +++ b/examples/joystick_ps3.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, joystick.Dualshock3) work := func() { @@ -64,15 +64,27 @@ func main() { stick.On(joystick.RightPress, func(data interface{}) { fmt.Println("right_press") }) + stick.On(joystick.RightRelease, func(data interface{}) { + fmt.Println("right_release") + }) stick.On(joystick.LeftPress, func(data interface{}) { fmt.Println("left_press") }) + stick.On(joystick.LeftRelease, func(data interface{}) { + fmt.Println("left_release") + }) stick.On(joystick.UpPress, func(data interface{}) { fmt.Println("up_press") }) + stick.On(joystick.UpRelease, func(data interface{}) { + fmt.Println("up_release") + }) stick.On(joystick.DownPress, func(data interface{}) { fmt.Println("down_press") }) + stick.On(joystick.DownRelease, func(data interface{}) { + fmt.Println("down_release") + }) // joysticks stick.On(joystick.LeftX, func(data interface{}) { @@ -92,15 +104,27 @@ func main() { stick.On(joystick.R1Press, func(data interface{}) { fmt.Println("R1Press", data) }) + stick.On(joystick.R1Release, func(data interface{}) { + fmt.Println("R1Release", data) + }) stick.On(joystick.R2Press, func(data interface{}) { fmt.Println("R2Press", data) }) + stick.On(joystick.R2Release, func(data interface{}) { + fmt.Println("R2Release", data) + }) stick.On(joystick.L1Press, func(data interface{}) { fmt.Println("L1Press", data) }) + stick.On(joystick.L1Release, func(data interface{}) { + fmt.Println("L1Release", data) + }) stick.On(joystick.L2Press, func(data interface{}) { fmt.Println("L2Press", data) }) + stick.On(joystick.L2Release, func(data interface{}) { + fmt.Println("L2Release", data) + }) } robot := gobot.NewRobot("joystickBot", diff --git a/examples/joystick_ps4.go b/examples/joystick_ps4.go index 046c7bd0a..91b1c3a99 100644 --- a/examples/joystick_ps4.go +++ b/examples/joystick_ps4.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, joystick.Dualshock4) work := func() { diff --git a/examples/joystick_ps5.go b/examples/joystick_ps5.go index fe8d1063b..0de5af6ee 100644 --- a/examples/joystick_ps5.go +++ b/examples/joystick_ps5.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, joystick.Dualsense) work := func() { diff --git a/examples/joystick_xbox360.go b/examples/joystick_xbox360.go index 655cb3889..dd8dee5b9 100644 --- a/examples/joystick_xbox360.go +++ b/examples/joystick_xbox360.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, joystick.Xbox360) work := func() { diff --git a/examples/joystick_xbox360_rock_band_drums.go b/examples/joystick_xbox360_rock_band_drums.go index a83c6993b..b892eb0ae 100644 --- a/examples/joystick_xbox360_rock_band_drums.go +++ b/examples/joystick_xbox360_rock_band_drums.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, joystick.Xbox360RockBandDrums) work := func() { diff --git a/examples/joystick_xboxone.go b/examples/joystick_xboxone.go index d29737c90..df079993b 100644 --- a/examples/joystick_xboxone.go +++ b/examples/joystick_xboxone.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) joystick := joystick.NewDriver(joystickAdaptor, joystick.XboxOne) work := func() { diff --git a/examples/minidrone_mambo_ps3.go b/examples/minidrone_mambo_ps3.go index d38e4af6a..2dd581c32 100644 --- a/examples/minidrone_mambo_ps3.go +++ b/examples/minidrone_mambo_ps3.go @@ -43,7 +43,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, "./platforms/joystick/configs/dualshock3.json", ) diff --git a/examples/minidrone_ps3.go b/examples/minidrone_ps3.go index a09959ec9..8717b723c 100644 --- a/examples/minidrone_ps3.go +++ b/examples/minidrone_ps3.go @@ -43,7 +43,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, "dualshock3") droneAdaptor := ble.NewClientAdaptor(os.Args[1]) diff --git a/examples/tello_facetracker.go b/examples/tello_facetracker.go index 1a65dfd65..676e9445f 100644 --- a/examples/tello_facetracker.go +++ b/examples/tello_facetracker.go @@ -74,7 +74,7 @@ var ( flightData *tello.FlightData // joystick - joyAdaptor = joystick.NewAdaptor() + joyAdaptor = joystick.NewAdaptor(0) stick = joystick.NewDriver(joyAdaptor, "dualshock4") leftX, leftY, rightX, rightY atomic.Value ) diff --git a/examples/tello_ps3.go b/examples/tello_ps3.go index 5d4f998d0..e1d9a71cc 100644 --- a/examples/tello_ps3.go +++ b/examples/tello_ps3.go @@ -37,7 +37,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor() + joystickAdaptor := joystick.NewAdaptor(0) stick := joystick.NewDriver(joystickAdaptor, "dualshock3") drone := tello.NewDriver("8888") From 2891173830f7b414ea8192eac0fb824a9bcf6bf6 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 9 Sep 2023 13:44:17 +0200 Subject: [PATCH 03/13] platform/joystick: add bin/scanner to handle OS differences Signed-off-by: deadprogram --- go.mod | 2 + go.sum | 4 + platforms/joystick/bin/scanner.go | 135 +++++++++++++++++++----------- 3 files changed, 94 insertions(+), 47 deletions(-) diff --git a/go.mod b/go.mod index b68ef9ba1..46ac9521c 100644 --- a/go.mod +++ b/go.mod @@ -35,10 +35,12 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/klauspost/compress v1.16.7 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 // indirect github.com/nats-io/nats-server/v2 v2.7.4 // indirect github.com/nats-io/nkeys v0.4.4 // indirect github.com/nats-io/nuid v1.0.1 // indirect + github.com/nsf/termbox-go v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/saltosystems/winrt-go v0.0.0-20230613063811-c792451fa808 // indirect github.com/sirupsen/logrus v1.9.3 // indirect diff --git a/go.sum b/go.sum index 933d96db1..ab35de053 100644 --- a/go.sum +++ b/go.sum @@ -54,6 +54,8 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/muka/go-bluetooth v0.0.0-20220830075246-0746e3a1ea53/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 h1:BuVRHr4HHJbk1DHyWkArJ7E8J/VA8ncCr/VLnQFazBo= @@ -69,6 +71,8 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY= +github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk= github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= diff --git a/platforms/joystick/bin/scanner.go b/platforms/joystick/bin/scanner.go index 66eff923d..8eb726e2a 100644 --- a/platforms/joystick/bin/scanner.go +++ b/platforms/joystick/bin/scanner.go @@ -8,65 +8,106 @@ // Based on original code from Jacky Boen // https://github.com/veandco/go-sdl2/blob/master/examples/events/events.go +// Simple program that displays the state of the specified joystick +// +// go run joysticktest.go 2 +// displays state of joystick id 2 package main import ( "fmt" + "github.com/nsf/termbox-go" + "github.com/0xcafed00d/joystick" "os" - - "github.com/veandco/go-sdl2/sdl" + "strconv" + "time" ) -var joysticks [16]*sdl.Joystick - -func run() int { - var event sdl.Event - var running bool - - sdl.Init(sdl.INIT_JOYSTICK) - defer sdl.Quit() - - sdl.JoystickEventState(sdl.ENABLE) - - running = true - for running { - for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() { - switch t := event.(type) { - case *sdl.QuitEvent: - running = false - case *sdl.JoyAxisEvent: - fmt.Printf("[%d ms] Axis: %d\tvalue:%d\n", - t.Timestamp, t.Axis, t.Value) - case *sdl.JoyBallEvent: - fmt.Printf("[%d ms] Ball:%d\txrel:%d\tyrel:%d\n", - t.Timestamp, t.Ball, t.XRel, t.YRel) - case *sdl.JoyButtonEvent: - fmt.Printf("[%d ms] Button:%d\tstate:%d\n", - t.Timestamp, t.Button, t.State) - case *sdl.JoyHatEvent: - fmt.Printf("[%d ms] Hat:%d\tvalue:%d\n", - t.Timestamp, t.Hat, t.Value) - case *sdl.JoyDeviceAddedEvent: - joysticks[int(t.Which)] = sdl.JoystickOpen(int(t.Which)) - if joysticks[int(t.Which)] != nil { - fmt.Printf("Joystick %d connected\n", t.Which) - } - case *sdl.JoyDeviceRemovedEvent: - if joystick := joysticks[int(t.Which)]; joystick != nil { - joystick.Close() - } - fmt.Printf("Joystick %d disconnected\n", t.Which) - default: - fmt.Printf("Unknown event\n") - } +func printAt(x, y int, s string) { + for _, r := range s { + termbox.SetCell(x, y, r, termbox.ColorDefault, termbox.ColorDefault) + x++ + } +} + +func readJoystick(js joystick.Joystick) { + jinfo, err := js.Read() + + if err != nil { + printAt(1, 5, "Error: "+err.Error()) + return + } + + printAt(1, 5, "Buttons:") + for button := 0; button < js.ButtonCount(); button++ { + if jinfo.Buttons&(1< 1 { + i, err := strconv.Atoi(os.Args[1]) + if err != nil { + fmt.Println(err) + return + } + jsid = i + } + + js, jserr := joystick.Open(jsid) + + if jserr != nil { + fmt.Println(jserr) + return + } + + err := termbox.Init() + if err != nil { + panic(err) + } + defer termbox.Close() + + eventQueue := make(chan termbox.Event) + go func() { + for { + eventQueue <- termbox.PollEvent() + } + }() + + ticker := time.NewTicker(time.Millisecond * 40) + + for doQuit := false; !doQuit; { + select { + case ev := <-eventQueue: + if ev.Type == termbox.EventKey { + if ev.Ch == 'q' { + doQuit = true + } + } + if ev.Type == termbox.EventResize { + termbox.Flush() + } + + case <-ticker.C: + printAt(1, 0, "-- Press 'q' to Exit --") + printAt(1, 1, fmt.Sprintf("Joystick Name: %s", js.Name())) + printAt(1, 2, fmt.Sprintf(" Axis Count: %d", js.AxisCount())) + printAt(1, 3, fmt.Sprintf(" Button Count: %d", js.ButtonCount())) + readJoystick(js) + termbox.Flush() + } + } } From b3b92796bb24586b322f0a0b535a3fe809dcd205 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 9 Sep 2023 13:55:56 +0200 Subject: [PATCH 04/13] platforms/joystick: handle OS differences for dualshock3 and remove hat since it is not handled in the current joystick package Signed-off-by: deadprogram --- platforms/joystick/joystick_driver.go | 10 -- platforms/joystick/joystick_driver_test.go | 3 - platforms/joystick/joystick_dualsense.go | 1 - .../joystick/joystick_dualshock3_darwin.go | 86 +++++++++++++++++ ...shock3.go => joystick_dualshock3_linux.go} | 1 - .../joystick/joystick_dualshock3_windows.go | 94 +++++++++++++++++++ platforms/joystick/joystick_dualshock4.go | 27 ------ .../joystick/joystick_nintendo_joycon.go | 1 - platforms/joystick/joystick_shield.go | 27 ------ .../joystick/joystick_tflight_hotas_x.go | 7 -- platforms/joystick/joystick_xbox360.go | 47 ---------- .../joystick_xbox360_rock_band_drums.go | 1 - platforms/joystick/joystick_xboxone.go | 27 ------ 13 files changed, 180 insertions(+), 152 deletions(-) create mode 100644 platforms/joystick/joystick_dualshock3_darwin.go rename platforms/joystick/{joystick_dualshock3.go => joystick_dualshock3_linux.go} (98%) create mode 100644 platforms/joystick/joystick_dualshock3_windows.go diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index 1db3fcc78..da0e96728 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -59,20 +59,12 @@ type pair struct { ID int `json:"id"` } -// hat is a JSON representation of hat, name and id -type hat struct { - Hat int `json:"hat"` - Name string `json:"name"` - ID int `json:"id"` -} - // joystickConfig is a JSON representation of configuration values type joystickConfig struct { Name string `json:"name"` GUID string `json:"guid"` Axis []pair `json:"axis"` Buttons []pair `json:"buttons"` - Hats []hat `json:"Hats"` } // NewDriver returns a new Driver with a polling interval of @@ -188,8 +180,6 @@ func (j *Driver) Halt() (err error) { return } -var previousHat = "" - func (j *Driver) handleButtons(state js.State) error { for button := 0; button < j.adaptor().joystick.ButtonCount(); button++ { switch { diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index 7fd6647e2..a98d10163 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -19,9 +19,6 @@ func initTestDriver(config string) *Driver { } _ = a.Connect() d := NewDriver(a, config) - // d.poll = func() sdl.Event { - // return nil - // } return d } diff --git a/platforms/joystick/joystick_dualsense.go b/platforms/joystick/joystick_dualsense.go index ea17486f1..9827aed47 100644 --- a/platforms/joystick/joystick_dualsense.go +++ b/platforms/joystick/joystick_dualsense.go @@ -91,5 +91,4 @@ var dualsenseConfig = joystickConfig{ ID: 15, }, }, - Hats: []hat{}, } diff --git a/platforms/joystick/joystick_dualshock3_darwin.go b/platforms/joystick/joystick_dualshock3_darwin.go new file mode 100644 index 000000000..09dd31afd --- /dev/null +++ b/platforms/joystick/joystick_dualshock3_darwin.go @@ -0,0 +1,86 @@ +package joystick + +var dualshock3Config = joystickConfig{ + Name: "Dualshock3 Controller", + GUID: "1111", + Axis: []pair{ + { + Name: "left_x", + ID: 0, + }, + { + Name: "left_y", + ID: 1, + }, + { + Name: "right_x", + ID: 2, + }, + { + Name: "right_y", + ID: 3, + }, + }, + Buttons: []pair{ + { + Name: "square", + ID: 15, + }, + { + Name: "triangle", + ID: 12, + }, + { + Name: "circle", + ID: 13, + }, + { + Name: "x", + ID: 14, + }, + { + Name: "up", + ID: 4, + }, + { + Name: "down", + ID: 6, + }, + { + Name: "left", + ID: 17, + }, + { + Name: "right", + ID: 5, + }, + { + Name: "l1", + ID: 10, + }, + { + Name: "l2", + ID: 8, + }, + { + Name: "r1", + ID: 11, + }, + { + Name: "r2", + ID: 9, + }, + { + Name: "start", + ID: 3, + }, + { + Name: "select", + ID: 0, + }, + { + Name: "home", + ID: 16, + }, + }, +} diff --git a/platforms/joystick/joystick_dualshock3.go b/platforms/joystick/joystick_dualshock3_linux.go similarity index 98% rename from platforms/joystick/joystick_dualshock3.go rename to platforms/joystick/joystick_dualshock3_linux.go index a3bde6a19..19578f8ec 100644 --- a/platforms/joystick/joystick_dualshock3.go +++ b/platforms/joystick/joystick_dualshock3_linux.go @@ -91,5 +91,4 @@ var dualshock3Config = joystickConfig{ ID: 10, }, }, - Hats: []hat{}, } diff --git a/platforms/joystick/joystick_dualshock3_windows.go b/platforms/joystick/joystick_dualshock3_windows.go new file mode 100644 index 000000000..19578f8ec --- /dev/null +++ b/platforms/joystick/joystick_dualshock3_windows.go @@ -0,0 +1,94 @@ +package joystick + +var dualshock3Config = joystickConfig{ + Name: "Dualshock3 Controller", + GUID: "1111", + Axis: []pair{ + { + Name: "left_x", + ID: 0, + }, + { + Name: "left_y", + ID: 1, + }, + { + Name: "l2", + ID: 2, + }, + { + Name: "right_x", + ID: 3, + }, + { + Name: "right_y", + ID: 4, + }, + { + Name: "r2", + ID: 5, + }, + }, + Buttons: []pair{ + { + Name: "square", + ID: 3, + }, + { + Name: "triangle", + ID: 2, + }, + { + Name: "circle", + ID: 1, + }, + { + Name: "x", + ID: 0, + }, + { + Name: "up", + ID: 13, + }, + { + Name: "down", + ID: 14, + }, + { + Name: "left", + ID: 15, + }, + { + Name: "right", + ID: 16, + }, + { + Name: "l1", + ID: 4, + }, + { + Name: "l2", + ID: 6, + }, + { + Name: "r1", + ID: 5, + }, + { + Name: "r2", + ID: 7, + }, + { + Name: "start", + ID: 9, + }, + { + Name: "select", + ID: 8, + }, + { + Name: "home", + ID: 10, + }, + }, +} diff --git a/platforms/joystick/joystick_dualshock4.go b/platforms/joystick/joystick_dualshock4.go index cb1bdb5d6..77d4dcc80 100644 --- a/platforms/joystick/joystick_dualshock4.go +++ b/platforms/joystick/joystick_dualshock4.go @@ -75,31 +75,4 @@ var dualshock4Config = joystickConfig{ ID: 10, }, }, - Hats: []hat{ - { - Hat: 0, - Name: "down", - ID: 4, - }, - { - Hat: 0, - Name: "up", - ID: 1, - }, - { - Hat: 0, - Name: "left", - ID: 8, - }, - { - Hat: 0, - Name: "right", - ID: 2, - }, - { - Hat: 0, - Name: "released", - ID: 0, - }, - }, } diff --git a/platforms/joystick/joystick_nintendo_joycon.go b/platforms/joystick/joystick_nintendo_joycon.go index 4226ab1df..501bc8114 100644 --- a/platforms/joystick/joystick_nintendo_joycon.go +++ b/platforms/joystick/joystick_nintendo_joycon.go @@ -111,5 +111,4 @@ var joyconPairConfig = joystickConfig{ ID: 6, }, }, - Hats: []hat{}, } diff --git a/platforms/joystick/joystick_shield.go b/platforms/joystick/joystick_shield.go index dd6a70e00..8f3f2989b 100644 --- a/platforms/joystick/joystick_shield.go +++ b/platforms/joystick/joystick_shield.go @@ -75,31 +75,4 @@ var shieldConfig = joystickConfig{ ID: 9, }, }, - Hats: []hat{ - { - Hat: 0, - Name: "down", - ID: 4, - }, - { - Hat: 0, - Name: "up", - ID: 1, - }, - { - Hat: 0, - Name: "left", - ID: 8, - }, - { - Hat: 0, - Name: "right", - ID: 2, - }, - { - Hat: 0, - Name: "released", - ID: 0, - }, - }, } diff --git a/platforms/joystick/joystick_tflight_hotas_x.go b/platforms/joystick/joystick_tflight_hotas_x.go index 280346dd6..8cdb1bab8 100644 --- a/platforms/joystick/joystick_tflight_hotas_x.go +++ b/platforms/joystick/joystick_tflight_hotas_x.go @@ -24,11 +24,4 @@ var tflightHotasXConfig = joystickConfig{ {Name: "select", ID: 10}, {Name: "start", ID: 11}, }, - Hats: []hat{ - {Hat: 0, Name: "down", ID: 4}, - {Hat: 0, Name: "up", ID: 1}, - {Hat: 0, Name: "left", ID: 8}, - {Hat: 0, Name: "right", ID: 2}, - {Hat: 0, Name: "released", ID: 0}, - }, } diff --git a/platforms/joystick/joystick_xbox360.go b/platforms/joystick/joystick_xbox360.go index 6658b7097..02fa88666 100644 --- a/platforms/joystick/joystick_xbox360.go +++ b/platforms/joystick/joystick_xbox360.go @@ -75,51 +75,4 @@ var xbox360Config = joystickConfig{ ID: 9, }, }, - Hats: []hat{ - { - Hat: 0, - Name: "down", - ID: 4, - }, - { - Hat: 0, - Name: "up", - ID: 1, - }, - { - Hat: 0, - Name: "left", - ID: 8, - }, - { - Hat: 0, - Name: "upLeft", - ID: 9, - }, - { - Hat: 0, - Name: "downLeft", - ID: 12, - }, - { - Hat: 0, - Name: "right", - ID: 2, - }, - { - Hat: 0, - Name: "upRight", - ID: 3, - }, - { - Hat: 0, - Name: "downRight", - ID: 6, - }, - { - Hat: 0, - Name: "released", - ID: 0, - }, - }, } diff --git a/platforms/joystick/joystick_xbox360_rock_band_drums.go b/platforms/joystick/joystick_xbox360_rock_band_drums.go index c6c02a738..eaa9d3054 100644 --- a/platforms/joystick/joystick_xbox360_rock_band_drums.go +++ b/platforms/joystick/joystick_xbox360_rock_band_drums.go @@ -54,5 +54,4 @@ var xbox360RockBandDrumsConfig = joystickConfig{ ID: 14, }, }, - Hats: []hat{}, } diff --git a/platforms/joystick/joystick_xboxone.go b/platforms/joystick/joystick_xboxone.go index 76d085e36..e3cf49958 100644 --- a/platforms/joystick/joystick_xboxone.go +++ b/platforms/joystick/joystick_xboxone.go @@ -75,31 +75,4 @@ var xboxOneConfig = joystickConfig{ ID: 8, }, }, - Hats: []hat{ - { - Hat: 0, - Name: "down", - ID: 4, - }, - { - Hat: 0, - Name: "up", - ID: 1, - }, - { - Hat: 0, - Name: "left", - ID: 8, - }, - { - Hat: 0, - Name: "right", - ID: 2, - }, - { - Hat: 0, - Name: "released", - ID: 0, - }, - }, } From 2afb3e6b91a1a157dd072461e1b310360332bfe8 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sun, 10 Sep 2023 10:11:25 +0200 Subject: [PATCH 05/13] platforms/joystick: remove unused interface and go fmt cleanup Signed-off-by: deadprogram --- platforms/joystick/doc.go | 8 ++---- platforms/joystick/joystick_adaptor.go | 7 +---- platforms/joystick/joystick_driver.go | 38 ++++++++++++++++---------- platforms/joystick/test_helper.go | 10 +++---- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/platforms/joystick/doc.go b/platforms/joystick/doc.go index a89979569..810a0034a 100644 --- a/platforms/joystick/doc.go +++ b/platforms/joystick/doc.go @@ -3,9 +3,7 @@ Package joystick provides the Gobot adaptor and drivers for game controllers tha Installing: - This package requires `sdl2` to be installed on your system - - Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) + Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/release/README.md) Example: @@ -20,9 +18,7 @@ Example: func main() { joystickAdaptor := joystick.NewAdaptor(0) - joystick := joystick.NewDriver(joystickAdaptor, - "./platforms/joystick/configs/dualshock3.json", - ) + joystick := joystick.NewDriver(joystickAdaptor, "dualshock3") work := func() { joystick.On(joystick.Event("square_press"), func(data interface{}) { diff --git a/platforms/joystick/joystick_adaptor.go b/platforms/joystick/joystick_adaptor.go index 743588d05..0015f1012 100644 --- a/platforms/joystick/joystick_adaptor.go +++ b/platforms/joystick/joystick_adaptor.go @@ -8,15 +8,10 @@ import ( js "github.com/0xcafed00d/joystick" ) -type joystick interface { - Close() - ID() int -} - // Adaptor represents a connection to a joystick type Adaptor struct { name string - id int + id int joystick js.Joystick connect func(*Adaptor) error } diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index da0e96728..224d37f9d 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -6,8 +6,8 @@ import ( "os" "time" - "gobot.io/x/gobot/v2" js "github.com/0xcafed00d/joystick" + "gobot.io/x/gobot/v2" ) const ( @@ -41,15 +41,15 @@ const ( // Driver represents a joystick type Driver struct { - name string - interval time.Duration - connection gobot.Connection - configPath string - config joystickConfig + name string + interval time.Duration + connection gobot.Connection + configPath string + config joystickConfig buttonState map[int]bool - axisState map[int]int + axisState map[int]int - halt chan bool + halt chan bool gobot.Eventer } @@ -76,12 +76,12 @@ type joystickConfig struct { // time.Duration: Interval at which the Driver is polled for new information func NewDriver(a *Adaptor, config string, v ...time.Duration) *Driver { d := &Driver{ - name: gobot.DefaultName("Joystick"), - connection: a, - Eventer: gobot.NewEventer(), - configPath: config, + name: gobot.DefaultName("Joystick"), + connection: a, + Eventer: gobot.NewEventer(), + configPath: config, buttonState: make(map[int]bool), - axisState: make(map[int]int), + axisState: make(map[int]int), interval: 10 * time.Millisecond, halt: make(chan bool), @@ -161,8 +161,16 @@ func (j *Driver) Start() (err error) { j.Publish(j.Event("error"), err) break } - j.handleButtons(state) - j.handleAxes(state) + + // might just be missing a button definition, so keep going + if err := j.handleButtons(state); err != nil { + j.Publish(j.Event("error"), err) + } + + // might just be missing an axis definition, so keep going + if err := j.handleAxes(state); err != nil { + j.Publish(j.Event("error"), err) + } select { case <-time.After(j.interval): diff --git a/platforms/joystick/test_helper.go b/platforms/joystick/test_helper.go index f0ad6fdc7..4fa17da13 100644 --- a/platforms/joystick/test_helper.go +++ b/platforms/joystick/test_helper.go @@ -4,9 +4,9 @@ import js "github.com/0xcafed00d/joystick" type testJoystick struct{} -func (t *testJoystick) Close() {} -func (t *testJoystick) ID() int { return 0 } -func (t *testJoystick) ButtonCount() int { return 0 } -func (t *testJoystick) AxisCount() int { return 0 } -func (t *testJoystick) Name() string { return "test-joy" } +func (t *testJoystick) Close() {} +func (t *testJoystick) ID() int { return 0 } +func (t *testJoystick) ButtonCount() int { return 0 } +func (t *testJoystick) AxisCount() int { return 0 } +func (t *testJoystick) Name() string { return "test-joy" } func (t *testJoystick) Read() (js.State, error) { return js.State{}, nil } From c8f7010b7a21196965567d37ef0831d8714cbf01 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sun, 10 Sep 2023 19:30:51 +0200 Subject: [PATCH 06/13] platforms/joystick: add test coverage for axes and buttons Signed-off-by: deadprogram --- platforms/joystick/joystick_driver.go | 66 +++++---- platforms/joystick/joystick_driver_test.go | 156 ++++++++------------- platforms/joystick/test_helper.go | 9 +- 3 files changed, 107 insertions(+), 124 deletions(-) diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index 224d37f9d..04df57aeb 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -120,6 +120,41 @@ func (j *Driver) adaptor() *Adaptor { // [button]_release // [axis] func (j *Driver) Start() (err error) { + if err := j.initConfig(); err != nil { + return err + } + + j.initEvents() + + go func() { + for { + state, err := j.adaptor().joystick.Read() + if err != nil { + j.Publish(j.Event("error"), err) + break + } + + // might just be missing a button definition, so keep going + if err := j.handleButtons(state); err != nil { + j.Publish(j.Event("error"), err) + } + + // might just be missing an axis definition, so keep going + if err := j.handleAxes(state); err != nil { + j.Publish(j.Event("error"), err) + } + + select { + case <-time.After(j.interval): + case <-j.halt: + return + } + } + }() + return +} + +func (j *Driver) initConfig() error { switch j.configPath { case Dualshock3: j.config = dualshock3Config @@ -146,6 +181,10 @@ func (j *Driver) Start() (err error) { } } + return nil +} + +func (j *Driver) initEvents() { for _, value := range j.config.Buttons { j.AddEvent(fmt.Sprintf("%s_press", value.Name)) j.AddEvent(fmt.Sprintf("%s_release", value.Name)) @@ -153,33 +192,6 @@ func (j *Driver) Start() (err error) { for _, value := range j.config.Axis { j.AddEvent(value.Name) } - - go func() { - for { - state, err := j.adaptor().joystick.Read() - if err != nil { - j.Publish(j.Event("error"), err) - break - } - - // might just be missing a button definition, so keep going - if err := j.handleButtons(state); err != nil { - j.Publish(j.Event("error"), err) - } - - // might just be missing an axis definition, so keep going - if err := j.handleAxes(state); err != nil { - j.Publish(j.Event("error"), err) - } - - select { - case <-time.After(j.interval): - case <-j.halt: - return - } - } - }() - return } // Halt stops joystick driver diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index a98d10163..b442d2ca4 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -7,136 +7,104 @@ import ( "gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2/gobottest" + + js "github.com/0xcafed00d/joystick" ) var _ gobot.Driver = (*Driver)(nil) -func initTestDriver(config string) *Driver { +func initTestDriver(config string) (*Driver, *testJoystick) { a := NewAdaptor(6) + tj := &testJoystick{} a.connect = func(j *Adaptor) (err error) { - j.joystick = &testJoystick{} + j.joystick = tj return nil } _ = a.Connect() d := NewDriver(a, config) - return d + return d, tj } func TestJoystickDriverName(t *testing.T) { - d := initTestDriver("./configs/xbox360_power_a_mini_proex.json") + d, _ := initTestDriver("./configs/dualshock3.json") gobottest.Assert(t, strings.HasPrefix(d.Name(), "Joystick"), true) d.SetName("NewName") gobottest.Assert(t, d.Name(), "NewName") } func TestDriverStart(t *testing.T) { - d := initTestDriver("./configs/xbox360_power_a_mini_proex.json") + d, _ := initTestDriver("./configs/dualshock3.json") d.interval = 1 * time.Millisecond gobottest.Assert(t, d.Start(), nil) time.Sleep(2 * time.Millisecond) } func TestDriverHalt(t *testing.T) { - d := initTestDriver("./configs/xbox360_power_a_mini_proex.json") + d, _ := initTestDriver("./configs/dualshock3.json") go func() { <-d.halt }() gobottest.Assert(t, d.Halt(), nil) } -// func TestDriverHandleEvent(t *testing.T) { -// sem := make(chan bool) -// d := initTestDriver("./configs/xbox360_power_a_mini_proex.json") -// _ = d.Start() - -// // left x stick -// _ = d.On(d.Event("left_x"), func(data interface{}) { -// gobottest.Assert(t, int16(100), data.(int16)) -// sem <- true -// }) -// _ = d.handleEvent(&sdl.JoyAxisEvent{ -// Which: 0, -// Axis: 0, -// Value: 100, -// }) -// select { -// case <-sem: -// case <-time.After(10 * time.Second): -// t.Errorf("Button Event \"left_x\" was not published") -// } - -// // x button press -// _ = d.On(d.Event("x_press"), func(data interface{}) { -// sem <- true -// }) -// _ = d.handleEvent(&sdl.JoyButtonEvent{ -// Which: 0, -// Button: 2, -// State: 1, -// }) -// select { -// case <-sem: -// case <-time.After(10 * time.Second): -// t.Errorf("Button Event \"x_press\" was not published") -// } - -// // x button release -// _ = d.On(d.Event("x_release"), func(data interface{}) { -// sem <- true -// }) -// _ = d.handleEvent(&sdl.JoyButtonEvent{ -// Which: 0, -// Button: 2, -// State: 0, -// }) -// select { -// case <-sem: -// case <-time.After(10 * time.Second): -// t.Errorf("Button Event \"x_release\" was not published") -// } - -// // down button press -// _ = d.On(d.Event("down_press"), func(data interface{}) { -// sem <- true -// }) -// _ = d.handleEvent(&sdl.JoyHatEvent{ -// Which: 0, -// Hat: 0, -// Value: 4, -// }) -// select { -// case <-sem: -// case <-time.After(10 * time.Second): -// t.Errorf("Hat Event \"down\" was not published") -// } - -// err := d.handleEvent(&sdl.JoyHatEvent{ -// Which: 0, -// Hat: 99, -// Value: 4, -// }) - -// gobottest.Assert(t, err.Error(), "Unknown Hat: 99 4") +func TestDriverHandleEvent(t *testing.T) { + sem := make(chan bool) + d, tj := initTestDriver("./configs/dualshock3.json") + tj.axisCount = 6 + tj.buttonCount = 17 -// err = d.handleEvent(&sdl.JoyAxisEvent{ -// Which: 0, -// Axis: 99, -// Value: 100, -// }) - -// gobottest.Assert(t, err.Error(), "Unknown Axis: 99") + if err := d.initConfig(); err != nil { + t.Errorf("initConfig() error: %v", err) + } + + d.initEvents() + + // left x stick + _ = d.On(d.Event("left_x"), func(data interface{}) { + gobottest.Assert(t, int(255), data.(int)) + sem <- true + }) + _ = d.handleAxes(js.State{ + AxisData: []int{255, 0, 0, 0, 0, 0}, + Buttons: 0, + }) + select { + case <-sem: + case <-time.After(1 * time.Second): + t.Errorf("Button Event \"left_x\" was not published") + } -// err = d.handleEvent(&sdl.JoyButtonEvent{ -// Which: 0, -// Button: 99, -// State: 0, -// }) + // x button press + _ = d.On(d.Event("x_press"), func(data interface{}) { + sem <- true + }) + _ = d.handleButtons(js.State{ + AxisData: []int{255, 0, 0, 0, 0, 0}, + Buttons: 1 << 14, + }) + select { + case <-sem: + case <-time.After(1 * time.Second): + t.Errorf("Button Event \"x_press\" was not published") + } -// gobottest.Assert(t, err.Error(), "Unknown Button: 99") -// } + // x button release + _ = d.On(d.Event("x_release"), func(data interface{}) { + sem <- true + }) + _ = d.handleButtons(js.State{ + AxisData: []int{255, 0, 0, 0, 0, 0}, + Buttons: 0, + }) + select { + case <-sem: + case <-time.After(1 * time.Second): + t.Errorf("Button Event \"x_release\" was not published") + } +} func TestDriverInvalidConfig(t *testing.T) { - d := initTestDriver("./configs/doesnotexist") + d, _ := initTestDriver("./configs/doesnotexist") err := d.Start() gobottest.Assert(t, strings.Contains(err.Error(), "open ./configs/doesnotexist: no such file or directory"), true) } diff --git a/platforms/joystick/test_helper.go b/platforms/joystick/test_helper.go index 4fa17da13..b38738258 100644 --- a/platforms/joystick/test_helper.go +++ b/platforms/joystick/test_helper.go @@ -2,11 +2,14 @@ package joystick import js "github.com/0xcafed00d/joystick" -type testJoystick struct{} +type testJoystick struct { + axisCount int + buttonCount int +} func (t *testJoystick) Close() {} func (t *testJoystick) ID() int { return 0 } -func (t *testJoystick) ButtonCount() int { return 0 } -func (t *testJoystick) AxisCount() int { return 0 } +func (t *testJoystick) ButtonCount() int { return t.buttonCount } +func (t *testJoystick) AxisCount() int { return t.axisCount } func (t *testJoystick) Name() string { return "test-joy" } func (t *testJoystick) Read() (js.State, error) { return js.State{}, nil } From 2a352ed2504536c7e479ffc5ef9be5f74608a65a Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 12 Sep 2023 10:59:13 +0200 Subject: [PATCH 07/13] build: run some additional tests on Windows Signed-off-by: deadprogram --- appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index a2abb7d93..1bc2f7642 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,6 +16,10 @@ build_script: - go test -v -cpu=2 . - go test -v -cpu=2 ./drivers/aio/... - go test -v -cpu=2 ./drivers/i2c/... + - go test -v -cpu=2 ./platforms/dji/... - go test -v -cpu=2 ./platforms/firmata/... - go test -v -cpu=2 ./platforms/ble/... + - go test -v -cpu=2 ./platforms/joystick/... + - go test -v -cpu=2 ./platforms/parrot/... + - go test -v -cpu=2 ./platforms/sphero/... - cd .. From 7ed78ccb4ba7062e9ad1dfd03cb228316c4efca6 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 12 Sep 2023 12:09:56 +0200 Subject: [PATCH 08/13] platforms/joystick: wrap loadfile error to more easily handle OS differences Signed-off-by: deadprogram --- platforms/joystick/joystick_driver.go | 2 +- platforms/joystick/joystick_driver_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index 04df57aeb..2a6849006 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -177,7 +177,7 @@ func (j *Driver) initConfig() error { default: err := j.loadFile() if err != nil { - return err + return fmt.Errorf("loadfile error: %w", err) } } diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index b442d2ca4..c5599add5 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -56,7 +56,7 @@ func TestDriverHandleEvent(t *testing.T) { if err := d.initConfig(); err != nil { t.Errorf("initConfig() error: %v", err) } - + d.initEvents() // left x stick @@ -106,5 +106,5 @@ func TestDriverHandleEvent(t *testing.T) { func TestDriverInvalidConfig(t *testing.T) { d, _ := initTestDriver("./configs/doesnotexist") err := d.Start() - gobottest.Assert(t, strings.Contains(err.Error(), "open ./configs/doesnotexist: no such file or directory"), true) + gobottest.Assert(t, strings.Contains(err.Error(), "loadfile error"), true) } From 5647b8084cad2e2e91eb6d41cce0e63504b505bf Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 13 Sep 2023 13:51:39 +0200 Subject: [PATCH 09/13] platforms/joystick: mappings for Windows PS3 Signed-off-by: deadprogram --- .../joystick/joystick_dualshock3_windows.go | 42 ++++++++----------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/platforms/joystick/joystick_dualshock3_windows.go b/platforms/joystick/joystick_dualshock3_windows.go index 19578f8ec..09dd31afd 100644 --- a/platforms/joystick/joystick_dualshock3_windows.go +++ b/platforms/joystick/joystick_dualshock3_windows.go @@ -12,83 +12,75 @@ var dualshock3Config = joystickConfig{ Name: "left_y", ID: 1, }, - { - Name: "l2", - ID: 2, - }, { Name: "right_x", - ID: 3, + ID: 2, }, { Name: "right_y", - ID: 4, - }, - { - Name: "r2", - ID: 5, + ID: 3, }, }, Buttons: []pair{ { Name: "square", - ID: 3, + ID: 15, }, { Name: "triangle", - ID: 2, + ID: 12, }, { Name: "circle", - ID: 1, + ID: 13, }, { Name: "x", - ID: 0, + ID: 14, }, { Name: "up", - ID: 13, + ID: 4, }, { Name: "down", - ID: 14, + ID: 6, }, { Name: "left", - ID: 15, + ID: 17, }, { Name: "right", - ID: 16, + ID: 5, }, { Name: "l1", - ID: 4, + ID: 10, }, { Name: "l2", - ID: 6, + ID: 8, }, { Name: "r1", - ID: 5, + ID: 11, }, { Name: "r2", - ID: 7, + ID: 9, }, { Name: "start", - ID: 9, + ID: 3, }, { Name: "select", - ID: 8, + ID: 0, }, { Name: "home", - ID: 10, + ID: 16, }, }, } From 9db41afde4af71ca116700cb8ea9f8b425f103ca Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 13 Sep 2023 14:10:44 +0200 Subject: [PATCH 10/13] build: add joystick tests Signed-off-by: deadprogram --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2727f9153..e09013af6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,10 +38,10 @@ jobs: name: Debug version command: go version - run: - # digispark needs libusb, joystick needs sdl2, opencv needs opencv - name: Platform tests (except digispark, joystick, opencv) + # digispark needs libusb, opencv needs opencv + name: Platform tests (except digispark and opencv) command: | - go test -v $(go list ./platforms/... | grep -v platforms/digispark | grep -v platforms/joystick | grep -v platforms/opencv) + go test -v $(go list ./platforms/... | grep -v platforms/digispark | grep -v platforms/opencv) "check_examples": docker: @@ -52,11 +52,11 @@ jobs: name: Debug version command: go version - run: - # digispark needs libusb, joystick needs sdl2, opencv needs opencv - name: Check examples (except digispark, joystick, opencv) + # digispark needs libusb, opencv needs opencv + name: Check examples (except digispark, opencv) command: | ALL=$(grep -l -r --include "*.go" 'build example' ./) - SOME=$(grep -L 'digispark' $(grep -L 'joystick' $(grep -L 'gocv' ${ALL}))) + SOME=$(grep -L 'digispark' $(grep -L 'gocv' ${ALL})) for e in ${SOME} ; do go vet "${e}" ; done workflows: From 0cf0f03ba57bec32f47d9c0531c857b19ba06dc4 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 16 Sep 2023 15:55:43 +0200 Subject: [PATCH 11/13] platforms/joystick: testing and docs improvements based on PR feedback. Signed-off-by: deadprogram --- Makefile | 6 +- examples/ardrone_ps3.go | 2 +- examples/bebop_ps3.go | 2 +- examples/bebop_ps3_video.go | 2 +- examples/joystick_ps3.go | 2 +- examples/joystick_ps4.go | 2 +- examples/joystick_ps5.go | 2 +- examples/joystick_xbox360.go | 2 +- examples/joystick_xbox360_rock_band_drums.go | 2 +- examples/joystick_xboxone.go | 2 +- examples/minidrone_mambo_ps3.go | 2 +- examples/minidrone_ps3.go | 2 +- examples/tello_facetracker.go | 2 +- examples/tello_ps3.go | 2 +- platforms/joystick/README.md | 2 +- platforms/joystick/bin/scanner.go | 5 +- platforms/joystick/doc.go | 4 +- platforms/joystick/joystick_adaptor.go | 12 ++- platforms/joystick/joystick_adaptor_test.go | 17 ++-- platforms/joystick/joystick_driver.go | 33 +++++--- platforms/joystick/joystick_driver_test.go | 87 ++++++++++++++++---- 21 files changed, 129 insertions(+), 63 deletions(-) diff --git a/Makefile b/Makefile index 4d7c4b56d..7454c03ba 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,8 @@ ALL_EXAMPLES := $(shell grep -l -r --include "*.go" 'build example' ./) # prevent examples with gocv (opencv) dependencies EXAMPLES_NO_GOCV := $(shell grep -L 'gocv' $(ALL_EXAMPLES)) -# prevent examples with joystick (sdl2) dependencies -EXAMPLES_NO_JOYSTICK := $(shell grep -L 'joystick' $(ALL_EXAMPLES)) -# prevent examples with joystick (sdl2) and gocv (opencv) dependencies -EXAMPLES_NO_GOCV_JOYSTICK := $(shell grep -L 'joystick' $$(grep -L 'gocv' $(EXAMPLES_NO_GOCV))) # used examples -EXAMPLES := $(EXAMPLES_NO_GOCV_JOYSTICK) +EXAMPLES := $(EXAMPLES_NO_GOCV) .PHONY: test test_race test_cover robeaux version_check fmt_check fmt_fix examples examples_check $(EXAMPLES) diff --git a/examples/ardrone_ps3.go b/examples/ardrone_ps3.go index c21b84352..37dd20131 100644 --- a/examples/ardrone_ps3.go +++ b/examples/ardrone_ps3.go @@ -25,7 +25,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") ardroneAdaptor := ardrone.NewAdaptor() diff --git a/examples/bebop_ps3.go b/examples/bebop_ps3.go index 7b33ffa91..743b7b0f2 100644 --- a/examples/bebop_ps3.go +++ b/examples/bebop_ps3.go @@ -25,7 +25,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") bebopAdaptor := bebop.NewAdaptor() diff --git a/examples/bebop_ps3_video.go b/examples/bebop_ps3_video.go index 7e57e7169..007e782e3 100644 --- a/examples/bebop_ps3_video.go +++ b/examples/bebop_ps3_video.go @@ -83,7 +83,7 @@ func ffmpeg() (stdin io.WriteCloser, stderr io.ReadCloser, err error) { } func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") bebopAdaptor := bebop.NewAdaptor() diff --git a/examples/joystick_ps3.go b/examples/joystick_ps3.go index 762f79b2b..1d2f3a2ce 100644 --- a/examples/joystick_ps3.go +++ b/examples/joystick_ps3.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Dualshock3) work := func() { diff --git a/examples/joystick_ps4.go b/examples/joystick_ps4.go index 91b1c3a99..c824090d4 100644 --- a/examples/joystick_ps4.go +++ b/examples/joystick_ps4.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Dualshock4) work := func() { diff --git a/examples/joystick_ps5.go b/examples/joystick_ps5.go index 0de5af6ee..d5cbf631b 100644 --- a/examples/joystick_ps5.go +++ b/examples/joystick_ps5.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Dualsense) work := func() { diff --git a/examples/joystick_xbox360.go b/examples/joystick_xbox360.go index dd8dee5b9..dff41efb3 100644 --- a/examples/joystick_xbox360.go +++ b/examples/joystick_xbox360.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Xbox360) work := func() { diff --git a/examples/joystick_xbox360_rock_band_drums.go b/examples/joystick_xbox360_rock_band_drums.go index b892eb0ae..05c6bf0a2 100644 --- a/examples/joystick_xbox360_rock_band_drums.go +++ b/examples/joystick_xbox360_rock_band_drums.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, joystick.Xbox360RockBandDrums) work := func() { diff --git a/examples/joystick_xboxone.go b/examples/joystick_xboxone.go index df079993b..a680529e6 100644 --- a/examples/joystick_xboxone.go +++ b/examples/joystick_xboxone.go @@ -14,7 +14,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") joystick := joystick.NewDriver(joystickAdaptor, joystick.XboxOne) work := func() { diff --git a/examples/minidrone_mambo_ps3.go b/examples/minidrone_mambo_ps3.go index 2dd581c32..b7ccd9b3a 100644 --- a/examples/minidrone_mambo_ps3.go +++ b/examples/minidrone_mambo_ps3.go @@ -43,7 +43,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "./platforms/joystick/configs/dualshock3.json", ) diff --git a/examples/minidrone_ps3.go b/examples/minidrone_ps3.go index 8717b723c..7afd96053 100644 --- a/examples/minidrone_ps3.go +++ b/examples/minidrone_ps3.go @@ -43,7 +43,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") droneAdaptor := ble.NewClientAdaptor(os.Args[1]) diff --git a/examples/tello_facetracker.go b/examples/tello_facetracker.go index 676e9445f..38cc2bcc6 100644 --- a/examples/tello_facetracker.go +++ b/examples/tello_facetracker.go @@ -74,7 +74,7 @@ var ( flightData *tello.FlightData // joystick - joyAdaptor = joystick.NewAdaptor(0) + joyAdaptor = joystick.NewAdaptor("0") stick = joystick.NewDriver(joyAdaptor, "dualshock4") leftX, leftY, rightX, rightY atomic.Value ) diff --git a/examples/tello_ps3.go b/examples/tello_ps3.go index e1d9a71cc..fb0e2a7f1 100644 --- a/examples/tello_ps3.go +++ b/examples/tello_ps3.go @@ -37,7 +37,7 @@ var leftX, leftY, rightX, rightY atomic.Value const offset = 32767.0 func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3") drone := tello.NewDriver("8888") diff --git a/platforms/joystick/README.md b/platforms/joystick/README.md index d365f264e..9f8f06740 100644 --- a/platforms/joystick/README.md +++ b/platforms/joystick/README.md @@ -50,7 +50,7 @@ import ( ) func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") stick := joystick.NewDriver(joystickAdaptor, "dualshock3", ) diff --git a/platforms/joystick/bin/scanner.go b/platforms/joystick/bin/scanner.go index 8eb726e2a..ec74112c9 100644 --- a/platforms/joystick/bin/scanner.go +++ b/platforms/joystick/bin/scanner.go @@ -5,9 +5,8 @@ // Do not build by default. // // Joystick scanner -// Based on original code from Jacky Boen -// https://github.com/veandco/go-sdl2/blob/master/examples/events/events.go - +// Based on original code from +// https://github.com/0xcafed00d/joystick/blob/master/joysticktest/joysticktest.go // Simple program that displays the state of the specified joystick // // go run joysticktest.go 2 diff --git a/platforms/joystick/doc.go b/platforms/joystick/doc.go index 810a0034a..3b5fcd64e 100644 --- a/platforms/joystick/doc.go +++ b/platforms/joystick/doc.go @@ -1,5 +1,5 @@ /* -Package joystick provides the Gobot adaptor and drivers for game controllers that are compatible with SDL. +Package joystick provides the Gobot adaptor and drivers for game controllers and joysticks. Installing: @@ -17,7 +17,7 @@ Example: ) func main() { - joystickAdaptor := joystick.NewAdaptor(0) + joystickAdaptor := joystick.NewAdaptor("0") joystick := joystick.NewDriver(joystickAdaptor, "dualshock3") work := func() { diff --git a/platforms/joystick/joystick_adaptor.go b/platforms/joystick/joystick_adaptor.go index 0015f1012..fba07f6bd 100644 --- a/platforms/joystick/joystick_adaptor.go +++ b/platforms/joystick/joystick_adaptor.go @@ -2,6 +2,7 @@ package joystick import ( "fmt" + "strconv" "gobot.io/x/gobot/v2" @@ -11,18 +12,23 @@ import ( // Adaptor represents a connection to a joystick type Adaptor struct { name string - id int + id string joystick js.Joystick connect func(*Adaptor) error } // NewAdaptor returns a new Joystick Adaptor. // Pass in the ID of the joystick you wish to connect to. -func NewAdaptor(id int) *Adaptor { +func NewAdaptor(id string) *Adaptor { return &Adaptor{ name: gobot.DefaultName("Joystick"), connect: func(j *Adaptor) error { - joy, err := js.Open(id) + i, err := strconv.Atoi(id) + if err != nil { + return fmt.Errorf("Invalid joystick ID: %v", err) + } + + joy, err := js.Open(i) if err != nil { return fmt.Errorf("No joystick available: %v", err) } diff --git a/platforms/joystick/joystick_adaptor_test.go b/platforms/joystick/joystick_adaptor_test.go index 2c07b5dfc..3a96a2031 100644 --- a/platforms/joystick/joystick_adaptor_test.go +++ b/platforms/joystick/joystick_adaptor_test.go @@ -4,14 +4,15 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "gobot.io/x/gobot/v2" - "gobot.io/x/gobot/v2/gobottest" ) var _ gobot.Adaptor = (*Adaptor)(nil) func initTestAdaptor() *Adaptor { - a := NewAdaptor(6) + a := NewAdaptor("6") a.connect = func(j *Adaptor) (err error) { j.joystick = &testJoystick{} return nil @@ -21,22 +22,22 @@ func initTestAdaptor() *Adaptor { func TestJoystickAdaptorName(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, strings.HasPrefix(a.Name(), "Joystick"), true) + assert.True(t, strings.HasPrefix(a.Name(), "Joystick")) a.SetName("NewName") - gobottest.Assert(t, a.Name(), "NewName") + assert.Equal(t, a.Name(), "NewName") } func TestAdaptorConnect(t *testing.T) { a := initTestAdaptor() - gobottest.Assert(t, a.Connect(), nil) + assert.Nil(t, a.Connect()) - a = NewAdaptor(6) + a = NewAdaptor("6") err := a.Connect() - gobottest.Assert(t, strings.HasPrefix(err.Error(), "No joystick available"), true) + assert.True(t, strings.HasPrefix(err.Error(), "No joystick available")) } func TestAdaptorFinalize(t *testing.T) { a := initTestAdaptor() _ = a.Connect() - gobottest.Assert(t, a.Finalize(), nil) + assert.Nil(t, a.Finalize()) } diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index 2a6849006..c313f362d 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -119,7 +119,7 @@ func (j *Driver) adaptor() *Adaptor { // [button]_press // [button]_release // [axis] -func (j *Driver) Start() (err error) { +func (j *Driver) Start() error { if err := j.initConfig(); err != nil { return err } @@ -151,7 +151,8 @@ func (j *Driver) Start() (err error) { } } }() - return + + return nil } func (j *Driver) initConfig() error { @@ -202,23 +203,19 @@ func (j *Driver) Halt() (err error) { func (j *Driver) handleButtons(state js.State) error { for button := 0; button < j.adaptor().joystick.ButtonCount(); button++ { - switch { - case state.Buttons&(1< Date: Sat, 16 Sep 2023 16:04:52 +0200 Subject: [PATCH 12/13] modules: remove sdl Signed-off-by: deadprogram --- go.mod | 3 +-- go.sum | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 46ac9521c..4338b5512 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,9 @@ require ( github.com/hybridgroup/go-ardrone v0.0.0-20140402002621-b9750d8d7b78 github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e github.com/nats-io/nats.go v1.27.1 + github.com/nsf/termbox-go v1.1.1 github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f github.com/stretchr/testify v1.8.4 - github.com/veandco/go-sdl2 v0.4.35 github.com/warthog618/gpiod v0.8.1 go.bug.st/serial v1.5.0 gocv.io/x/gocv v0.33.0 @@ -40,7 +40,6 @@ require ( github.com/nats-io/nats-server/v2 v2.7.4 // indirect github.com/nats-io/nkeys v0.4.4 // indirect github.com/nats-io/nuid v1.0.1 // indirect - github.com/nsf/termbox-go v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/saltosystems/winrt-go v0.0.0-20230613063811-c792451fa808 // indirect github.com/sirupsen/logrus v1.9.3 // indirect diff --git a/go.sum b/go.sum index ab35de053..e77271270 100644 --- a/go.sum +++ b/go.sum @@ -106,8 +106,6 @@ github.com/tdakkota/win32metadata v0.1.0/go.mod h1:77e6YvX0LIVW+O81fhWLnXAxxcyu/ github.com/tinygo-org/cbgo v0.0.4 h1:3D76CRYbH03Rudi8sEgs/YO0x3JIMdyq8jlQtk/44fU= github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk= github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= -github.com/veandco/go-sdl2 v0.4.35 h1:NohzsfageDWGtCd9nf7Pc3sokMK/MOK+UA2QMJARWzQ= -github.com/veandco/go-sdl2 v0.4.35/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY= github.com/warthog618/gpiod v0.8.1 h1:+8iHpHd3fljAd6l4AT8jPbMDQNKdvBIpW/hmLgAcHiM= github.com/warthog618/gpiod v0.8.1/go.mod h1:A7v1hGR2eTsnkN+e9RoAPYgJG9bLJWtwyIIK+pgqC7s= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= From a774e4ce62dc57fa9224605cc7fff2c0294714c4 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 16 Sep 2023 19:55:47 +0200 Subject: [PATCH 13/13] platforms/joystick: add mappings for dualshock4 Signed-off-by: deadprogram --- platforms/joystick/joystick_driver_test.go | 60 +++++++++++- ...hock4.go => joystick_dualshock4_darwin.go} | 28 ++++-- .../joystick/joystick_dualshock4_linux.go | 94 +++++++++++++++++++ .../joystick/joystick_dualshock4_windows.go | 94 +++++++++++++++++++ 4 files changed, 266 insertions(+), 10 deletions(-) rename platforms/joystick/{joystick_dualshock4.go => joystick_dualshock4_darwin.go} (84%) create mode 100644 platforms/joystick/joystick_dualshock4_linux.go create mode 100644 platforms/joystick/joystick_dualshock4_windows.go diff --git a/platforms/joystick/joystick_driver_test.go b/platforms/joystick/joystick_driver_test.go index c6949d0c0..334120584 100644 --- a/platforms/joystick/joystick_driver_test.go +++ b/platforms/joystick/joystick_driver_test.go @@ -48,7 +48,7 @@ func TestDriverHalt(t *testing.T) { assert.Nil(t, d.Halt()) } -func TestDriverHandleEvent(t *testing.T) { +func TestDriverHandleEventDS3(t *testing.T) { sem := make(chan bool) d, tj := initTestDriver("dualshock3") tj.axisCount = 6 @@ -104,7 +104,7 @@ func TestDriverHandleEvent(t *testing.T) { } } -func TestDriverHandleEventJSON(t *testing.T) { +func TestDriverHandleEventJSONDS3(t *testing.T) { sem := make(chan bool) d, tj := initTestDriver("./configs/dualshock3.json") tj.axisCount = 6 @@ -160,6 +160,62 @@ func TestDriverHandleEventJSON(t *testing.T) { } } +func TestDriverHandleEventDS4(t *testing.T) { + sem := make(chan bool) + d, tj := initTestDriver("dualshock4") + tj.axisCount = 6 + tj.buttonCount = 17 + + if err := d.initConfig(); err != nil { + t.Errorf("initConfig() error: %v", err) + } + + d.initEvents() + + // left x stick + _ = d.On(d.Event("left_x"), func(data interface{}) { + assert.Equal(t, int(255), data.(int)) + sem <- true + }) + _ = d.handleAxes(js.State{ + AxisData: []int{255, 0, 0, 0, 0, 0}, + Buttons: 0, + }) + select { + case <-sem: + case <-time.After(1 * time.Second): + t.Errorf("Button Event \"left_x\" was not published") + } + + // square button press + _ = d.On(d.Event("square_press"), func(data interface{}) { + sem <- true + }) + _ = d.handleButtons(js.State{ + AxisData: []int{255, 0, 0, 0, 0, 0}, + Buttons: 1 << d.findID("square", d.config.Buttons), + }) + select { + case <-sem: + case <-time.After(1 * time.Second): + t.Errorf("Button Event \"square_press\" was not published") + } + + // square button release + _ = d.On(d.Event("square_release"), func(data interface{}) { + sem <- true + }) + _ = d.handleButtons(js.State{ + AxisData: []int{255, 0, 0, 0, 0, 0}, + Buttons: 0, + }) + select { + case <-sem: + case <-time.After(1 * time.Second): + t.Errorf("Button Event \"square_release\" was not published") + } +} + func TestDriverInvalidConfig(t *testing.T) { d, _ := initTestDriver("./configs/doesnotexist") err := d.Start() diff --git a/platforms/joystick/joystick_dualshock4.go b/platforms/joystick/joystick_dualshock4_darwin.go similarity index 84% rename from platforms/joystick/joystick_dualshock4.go rename to platforms/joystick/joystick_dualshock4_darwin.go index 77d4dcc80..6e60c0710 100644 --- a/platforms/joystick/joystick_dualshock4.go +++ b/platforms/joystick/joystick_dualshock4_darwin.go @@ -14,15 +14,15 @@ var dualshock4Config = joystickConfig{ }, { Name: "right_x", - ID: 3, + ID: 2, }, { Name: "right_y", - ID: 4, + ID: 3, }, { Name: "l2", - ID: 2, + ID: 4, }, { Name: "r2", @@ -32,19 +32,19 @@ var dualshock4Config = joystickConfig{ Buttons: []pair{ { Name: "square", - ID: 3, + ID: 0, }, { Name: "triangle", - ID: 2, + ID: 3, }, { Name: "circle", - ID: 1, + ID: 2, }, { Name: "x", - ID: 0, + ID: 1, }, { Name: "l1", @@ -64,7 +64,7 @@ var dualshock4Config = joystickConfig{ }, { Name: "share", - ID: 8, + ID: 13, }, { Name: "options", @@ -72,7 +72,19 @@ var dualshock4Config = joystickConfig{ }, { Name: "home", + ID: 12, + }, + { + Name: "left_joystick", ID: 10, }, + { + Name: "right_joystick", + ID: 11, + }, + { + Name: "panel", + ID: 13, + }, }, } diff --git a/platforms/joystick/joystick_dualshock4_linux.go b/platforms/joystick/joystick_dualshock4_linux.go new file mode 100644 index 000000000..bb8f7a4e1 --- /dev/null +++ b/platforms/joystick/joystick_dualshock4_linux.go @@ -0,0 +1,94 @@ +package joystick + +var dualshock4Config = joystickConfig{ + Name: "Dualshock4 Controller", + GUID: "2222", + Axis: []pair{ + { + Name: "left_x", + ID: 0, + }, + { + Name: "left_y", + ID: 1, + }, + { + Name: "right_x", + ID: 3, + }, + { + Name: "right_y", + ID: 4, + }, + { + Name: "l2", + ID: 2, + }, + { + Name: "r2", + ID: 5, + }, + { + Name: "right_left", + ID: 6, + }, + { + Name: "up_down", + ID: 7, + }, + }, + Buttons: []pair{ + { + Name: "square", + ID: 3, + }, + { + Name: "triangle", + ID: 2, + }, + { + Name: "circle", + ID: 1, + }, + { + Name: "x", + ID: 0, + }, + { + Name: "l1", + ID: 4, + }, + { + Name: "l2", + ID: 6, + }, + { + Name: "r1", + ID: 5, + }, + { + Name: "r2", + ID: 7, + }, + { + Name: "share", + ID: 8, + }, + { + Name: "options", + ID: 9, + }, + { + Name: "home", + ID: 10, + }, + { + Name: "left_joystick", + ID: 11, + }, + { + Name: "right_joystick", + ID: 12, + }, + }, +} diff --git a/platforms/joystick/joystick_dualshock4_windows.go b/platforms/joystick/joystick_dualshock4_windows.go new file mode 100644 index 000000000..d05f77533 --- /dev/null +++ b/platforms/joystick/joystick_dualshock4_windows.go @@ -0,0 +1,94 @@ +package joystick + +var dualshock4Config = joystickConfig{ + Name: "Dualshock4 Controller", + GUID: "2222", + Axis: []pair{ + { + Name: "left_x", + ID: 0, + }, + { + Name: "left_y", + ID: 1, + }, + { + Name: "right_x", + ID: 2, + }, + { + Name: "right_y", + ID: 3, + }, + { + Name: "l2", + ID: 5, + }, + { + Name: "r2", + ID: 4, + }, + { + Name: "right_left", + ID: 6, + }, + { + Name: "up_down", + ID: 7, + }, + }, + Buttons: []pair{ + { + Name: "square", + ID: 0, + }, + { + Name: "triangle", + ID: 3, + }, + { + Name: "circle", + ID: 2, + }, + { + Name: "x", + ID: 1, + }, + { + Name: "l1", + ID: 4, + }, + { + Name: "l2", + ID: 6, + }, + { + Name: "r1", + ID: 5, + }, + { + Name: "r2", + ID: 7, + }, + { + Name: "share", + ID: 8, + }, + { + Name: "options", + ID: 9, + }, + { + Name: "home", + ID: 12, + }, + { + Name: "left_joystick", + ID: 10, + }, + { + Name: "right_joystick", + ID: 11, + }, + }, +}