1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-26 13:48:49 +08:00
hybridgroup.gobot/platforms/joystick/joystick_driver.go

184 lines
4.3 KiB
Go
Raw Normal View History

2014-04-27 18:02:39 -07:00
package joystick
import (
"encoding/json"
2014-07-22 13:55:19 -07:00
"errors"
"fmt"
"io/ioutil"
2014-11-19 15:45:59 -08:00
"time"
2014-07-09 18:32:27 -07:00
"github.com/hybridgroup/go-sdl2/sdl"
"github.com/hybridgroup/gobot"
)
var _ gobot.Driver = (*JoystickDriver)(nil)
type JoystickDriver struct {
name string
interval time.Duration
connection gobot.Connection
2014-11-19 15:45:59 -08:00
configPath string
config joystickConfig
poll func() sdl.Event
2014-12-23 01:20:44 -08:00
halt chan bool
gobot.Eventer
}
// pair is a JSON representation of name and id
type pair struct {
Name string `json:"name"`
2014-06-10 15:16:11 -07:00
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"`
2014-06-10 15:16:11 -07:00
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"`
}
// NewJoystickDriver creates a joyscript driver by name.
//
// It adds the following events:
// (button)_press - triggered when (button) is pressed
// (button)_release - triggered when (button) is released
func NewJoystickDriver(a *JoystickAdaptor, name string, config string, v ...time.Duration) *JoystickDriver {
2014-04-27 18:02:39 -07:00
d := &JoystickDriver{
name: name,
connection: a,
Eventer: gobot.NewEventer(),
2014-11-19 15:45:59 -08:00
configPath: config,
2014-07-22 13:55:19 -07:00
poll: func() sdl.Event {
return sdl.PollEvent()
},
interval: 10 * time.Millisecond,
2014-12-23 01:20:44 -08:00
halt: make(chan bool, 0),
}
if len(v) > 0 {
d.interval = v[0]
2014-04-27 18:02:39 -07:00
}
2014-11-19 15:45:59 -08:00
d.AddEvent("error")
return d
}
func (j *JoystickDriver) Name() string { return j.name }
func (j *JoystickDriver) Connection() gobot.Connection { return j.connection }
// adaptor returns joystick adaptor
func (j *JoystickDriver) adaptor() *JoystickAdaptor {
return j.Connection().(*JoystickAdaptor)
}
// Start initiallizes event polling with defined interval
func (j *JoystickDriver) Start() (errs []error) {
2014-11-19 15:45:59 -08:00
file, err := ioutil.ReadFile(j.configPath)
if err != nil {
return []error{err}
2014-11-19 15:45:59 -08:00
}
var jsontype joystickConfig
json.Unmarshal(file, &jsontype)
j.config = jsontype
for _, value := range j.config.Buttons {
j.AddEvent(fmt.Sprintf("%s_press", value.Name))
j.AddEvent(fmt.Sprintf("%s_release", value.Name))
}
for _, value := range j.config.Axis {
j.AddEvent(value.Name)
}
for _, value := range j.config.Hats {
j.AddEvent(value.Name)
}
go func() {
for {
event := j.poll()
if event != nil {
if err = j.handleEvent(event); err != nil {
gobot.Publish(j.Event("error"), err)
}
}
2014-12-23 01:20:44 -08:00
select {
case <-time.After(j.interval):
case <-j.halt:
return
}
2014-07-22 13:55:19 -07:00
}
2014-11-19 15:45:59 -08:00
}()
return
2014-07-22 13:55:19 -07:00
}
// Halt stops joystick driver
2014-12-23 01:20:44 -08:00
func (j *JoystickDriver) Halt() (errs []error) {
j.halt <- true
return
}
// HandleEvent publishes an specific event according to data received
2014-07-22 13:55:19 -07:00
func (j *JoystickDriver) 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 == "" {
2014-11-19 15:45:59 -08:00
return errors.New(fmt.Sprintf("Unknown Axis: %v", data.Axis))
2014-07-22 13:55:19 -07:00
} else {
gobot.Publish(j.Event(axis), data.Value)
}
}
case *sdl.JoyButtonEvent:
if data.Which == j.adaptor().joystick.InstanceID() {
button := j.findName(data.Button, j.config.Buttons)
if button == "" {
2014-11-19 15:45:59 -08:00
return errors.New(fmt.Sprintf("Unknown Button: %v", data.Button))
2014-07-22 13:55:19 -07:00
} else {
if data.State == 1 {
gobot.Publish(j.Event(fmt.Sprintf("%s_press", button)), nil)
} else {
gobot.Publish(j.Event(fmt.Sprintf("%s_release", button)), nil)
}
}
}
2014-07-22 13:55:19 -07:00
case *sdl.JoyHatEvent:
if data.Which == j.adaptor().joystick.InstanceID() {
hat := j.findHatName(data.Value, data.Hat, j.config.Hats)
if hat == "" {
2014-11-19 15:45:59 -08:00
return errors.New(fmt.Sprintf("Unknown Hat: %v %v", data.Hat, data.Value))
2014-07-22 13:55:19 -07:00
} else {
gobot.Publish(j.Event(hat), true)
}
}
}
return nil
}
2014-07-22 13:55:19 -07:00
2014-04-27 18:02:39 -07:00
func (j *JoystickDriver) findName(id uint8, list []pair) string {
for _, value := range list {
2014-06-10 15:16:11 -07:00
if int(id) == value.ID {
return value.Name
}
}
return ""
}
// findHatName returns name from hat found by id in provided list
2014-04-27 18:02:39 -07:00
func (j *JoystickDriver) findHatName(id uint8, hat uint8, list []hat) string {
for _, lHat := range list {
if int(id) == lHat.ID && int(hat) == lHat.Hat {
return lHat.Name
}
}
return ""
}