diff --git a/driver.go b/driver.go index 252019b72..aa09eef1b 100644 --- a/driver.go +++ b/driver.go @@ -3,11 +3,11 @@ package gobot import "time" type Driver struct { - Interval time.Duration `json:"interval"` - Pin string `json:"pin"` - Name string `json:"name"` - Commands []string `json:"commands"` - Events map[string]chan interface{} `json:"-"` + Interval time.Duration `json:"interval"` + Pin string `json:"pin"` + Name string `json:"name"` + Commands []string `json:"commands"` + Events map[string]*Event `json:"-"` } type DriverInterface interface { diff --git a/event.go b/event.go new file mode 100644 index 000000000..cbb950e1f --- /dev/null +++ b/event.go @@ -0,0 +1,34 @@ +package gobot + +type Event struct { + Chan chan interface{} + Callbacks []func(interface{}) +} + +func NewEvent() *Event { + e := &Event{ + Chan: make(chan interface{}, 1), + Callbacks: []func(interface{}){}, + } + go func() { + for { + e.Read() + } + }() + return e +} + +func (e *Event) Write(data interface{}) { + select { + case e.Chan <- data: + default: + } +} + +func (e *Event) Read() { + for s := range e.Chan { + for _, f := range e.Callbacks { + go f(s) + } + } +} diff --git a/examples/firmata_button.go b/examples/firmata_button.go index a84be05ad..fed74e379 100644 --- a/examples/firmata_button.go +++ b/examples/firmata_button.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "github.com/hybridgroup/gobot" "github.com/hybridgroup/gobot/platforms/firmata" "github.com/hybridgroup/gobot/platforms/gpio" @@ -21,6 +22,14 @@ func main() { gobot.On(button.Events["release"], func(data interface{}) { led.Off() }) + + gobot.On(button.Events["push"], func(data interface{}) { + fmt.Println("IVE BEEN PUSHED") + }) + + gobot.On(button.Events["release"], func(data interface{}) { + fmt.Println("IVE BEEN RELEASED") + }) } gbot.Robots = append(gbot.Robots, diff --git a/platforms/ardrone/ardrone_driver.go b/platforms/ardrone/ardrone_driver.go index 151873601..2573b546c 100644 --- a/platforms/ardrone/ardrone_driver.go +++ b/platforms/ardrone/ardrone_driver.go @@ -17,8 +17,8 @@ func NewArdroneDriver(adaptor DroneInterface, name string) *ArdroneDriver { return &ArdroneDriver{ Driver: gobot.Driver{ Name: name, - Events: map[string]chan interface{}{ - "Flying": make(chan interface{}, 1), + Events: map[string]*gobot.Event{ + "Flying": gobot.NewEvent(), }, }, Adaptor: adaptor, diff --git a/platforms/gpio/button_driver.go b/platforms/gpio/button_driver.go index 75474e91c..2c113bc3a 100644 --- a/platforms/gpio/button_driver.go +++ b/platforms/gpio/button_driver.go @@ -15,9 +15,9 @@ func NewButtonDriver(a DigitalReader, name string, pin string) *ButtonDriver { Driver: gobot.Driver{ Name: name, Pin: pin, - Events: map[string]chan interface{}{ - "push": make(chan interface{}), - "release": make(chan interface{}), + Events: map[string]*gobot.Event{ + "push": gobot.NewEvent(), + "release": gobot.NewEvent(), }, }, Active: false, diff --git a/platforms/gpio/makey_button_driver.go b/platforms/gpio/makey_button_driver.go index c4313bed4..ec6399e34 100644 --- a/platforms/gpio/makey_button_driver.go +++ b/platforms/gpio/makey_button_driver.go @@ -16,9 +16,9 @@ func NewMakeyButtonDriver(a DigitalReader, name string, pin string) *MakeyButton Driver: gobot.Driver{ Name: name, Pin: pin, - Events: map[string]chan interface{}{ - "push": make(chan interface{}), - "release": make(chan interface{}), + Events: map[string]*gobot.Event{ + "push": gobot.NewEvent(), + "release": gobot.NewEvent(), }, }, Active: false, diff --git a/platforms/i2c/wiichuck_driver.go b/platforms/i2c/wiichuck_driver.go index bf8f69028..69c3baab1 100644 --- a/platforms/i2c/wiichuck_driver.go +++ b/platforms/i2c/wiichuck_driver.go @@ -16,10 +16,10 @@ func NewWiichuckDriver(a I2cInterface, name string) *WiichuckDriver { return &WiichuckDriver{ Driver: gobot.Driver{ Name: name, - Events: map[string]chan interface{}{ - "z_button": make(chan interface{}), - "c_button": make(chan interface{}), - "joystick": make(chan interface{}), + Events: map[string]*gobot.Event{ + "z_button": gobot.NewEvent(), + "c_button": gobot.NewEvent(), + "joystick": gobot.NewEvent(), }, }, joystick: map[string]float64{ diff --git a/platforms/joystick/joystick_driver.go b/platforms/joystick/joystick_driver.go index 77acd5ecc..b992e07d4 100644 --- a/platforms/joystick/joystick_driver.go +++ b/platforms/joystick/joystick_driver.go @@ -37,7 +37,7 @@ type joystickConfig struct { func NewJoystickDriver(a *JoystickAdaptor, name string, config string) *JoystickDriver { d := &JoystickDriver{ Driver: gobot.Driver{ - Events: make(map[string]chan interface{}), + Events: make(map[string]*gobot.Event), }, Adaptor: a, } @@ -50,14 +50,14 @@ func NewJoystickDriver(a *JoystickAdaptor, name string, config string) *Joystick json.Unmarshal(file, &jsontype) d.config = jsontype for _, value := range d.config.Buttons { - d.Events[fmt.Sprintf("%s_press", value.Name)] = make(chan interface{}, 0) - d.Events[fmt.Sprintf("%s_release", value.Name)] = make(chan interface{}, 0) + d.Events[fmt.Sprintf("%s_press", value.Name)] = gobot.NewEvent() + d.Events[fmt.Sprintf("%s_release", value.Name)] = gobot.NewEvent() } for _, value := range d.config.Axis { - d.Events[value.Name] = make(chan interface{}, 0) + d.Events[value.Name] = gobot.NewEvent() } for _, value := range d.config.Hats { - d.Events[value.Name] = make(chan interface{}, 0) + d.Events[value.Name] = gobot.NewEvent() } return d } diff --git a/platforms/leap/leap_motion_driver.go b/platforms/leap/leap_motion_driver.go index 08c016247..780771f56 100644 --- a/platforms/leap/leap_motion_driver.go +++ b/platforms/leap/leap_motion_driver.go @@ -15,8 +15,8 @@ func NewLeapMotionDriver(a *LeapMotionAdaptor, name string) *LeapMotionDriver { return &LeapMotionDriver{ Driver: gobot.Driver{ Name: name, - Events: map[string]chan interface{}{ - "Message": make(chan interface{}), + Events: map[string]*gobot.Event{ + "Message": gobot.NewEvent(), }, }, Adaptor: a, diff --git a/platforms/neurosky/neurosky_driver.go b/platforms/neurosky/neurosky_driver.go index 0123fe4df..a3a4751cc 100644 --- a/platforms/neurosky/neurosky_driver.go +++ b/platforms/neurosky/neurosky_driver.go @@ -34,14 +34,14 @@ func NewNeuroskyDriver(a *NeuroskyAdaptor, name string) *NeuroskyDriver { return &NeuroskyDriver{ Driver: gobot.Driver{ Name: name, - Events: map[string]chan interface{}{ - "Extended": make(chan interface{}), - "Signal": make(chan interface{}), - "Attention": make(chan interface{}), - "Meditation": make(chan interface{}), - "Blink": make(chan interface{}), - "Wave": make(chan interface{}), - "EEG": make(chan interface{}), + Events: map[string]*gobot.Event{ + "Extended": gobot.NewEvent(), + "Signal": gobot.NewEvent(), + "Attention": gobot.NewEvent(), + "Meditation": gobot.NewEvent(), + "Blink": gobot.NewEvent(), + "Wave": gobot.NewEvent(), + "EEG": gobot.NewEvent(), }, }, Adaptor: a, diff --git a/platforms/opencv/camera_driver.go b/platforms/opencv/camera_driver.go index 2644faae3..ea2fe0c5d 100644 --- a/platforms/opencv/camera_driver.go +++ b/platforms/opencv/camera_driver.go @@ -16,8 +16,8 @@ func NewCameraDriver(name string, source interface{}) *CameraDriver { Driver: gobot.Driver{ Name: name, Commands: []string{}, - Events: map[string]chan interface{}{ - "Frame": make(chan interface{}, 0), + Events: map[string]*gobot.Event{ + "Frame": gobot.NewEvent(), }, }, Source: source, diff --git a/platforms/pebble/pebble_driver.go b/platforms/pebble/pebble_driver.go index a800614ae..b0a3eca73 100644 --- a/platforms/pebble/pebble_driver.go +++ b/platforms/pebble/pebble_driver.go @@ -17,10 +17,10 @@ func NewPebbleDriver(adaptor *PebbleAdaptor, name string) *PebbleDriver { return &PebbleDriver{ Driver: gobot.Driver{ Name: name, - Events: map[string]chan interface{}{ - "button": make(chan interface{}), - "accel": make(chan interface{}), - "tap": make(chan interface{}), + Events: map[string]*gobot.Event{ + "button": gobot.NewEvent(), + "accel": gobot.NewEvent(), + "tap": gobot.NewEvent(), }, Commands: []string{ "PublishEventC", diff --git a/platforms/sphero/sphero_driver.go b/platforms/sphero/sphero_driver.go index c617725c6..fa69d4862 100644 --- a/platforms/sphero/sphero_driver.go +++ b/platforms/sphero/sphero_driver.go @@ -25,8 +25,10 @@ type SpheroDriver struct { func NewSpheroDriver(a *SpheroAdaptor, name string) *SpheroDriver { return &SpheroDriver{ Driver: gobot.Driver{ - Name: name, - Events: make(map[string]chan interface{}), + Name: name, + Events: map[string]*gobot.Event{ + "Collision": gobot.NewEvent(), + }, Commands: []string{ "SetRGBC", "RollC", @@ -137,7 +139,6 @@ func (s *SpheroDriver) Stop() { } func (s *SpheroDriver) configureCollisionDetection() { - s.Events["Collision"] = make(chan interface{}) s.packetChannel <- s.craftPacket([]uint8{0x01, 0x40, 0x40, 0x50, 0x50, 0x60}, 0x12) } diff --git a/utils.go b/utils.go index c07581c9d..7428ac4a2 100644 --- a/utils.go +++ b/utils.go @@ -27,19 +27,12 @@ func After(t time.Duration, f func()) { time.AfterFunc(t, f) } -func Publish(c chan interface{}, val interface{}) { - select { - case c <- val: - default: - } +func Publish(e *Event, val interface{}) { + e.Write(val) } -func On(c chan interface{}, f func(s interface{})) { - go func() { - for s := range c { - f(s) - } - }() +func On(e *Event, f func(s interface{})) { + e.Callbacks = append(e.Callbacks, f) } func Rand(max int) int { diff --git a/utils_test.go b/utils_test.go index 95d9b5fba..8cba3349d 100644 --- a/utils_test.go +++ b/utils_test.go @@ -30,19 +30,20 @@ var _ = Describe("Utils", func() { Expect(i).To(Equal(1)) }) It("should Publish message to channel without blocking", func() { - c := make(chan interface{}, 1) - Publish(c, 1) - Publish(c, 2) - i := <-c + e := &Event{Chan: make(chan interface{}, 1)} + Publish(e, 1) + Publish(e, 2) + i := <-e.Chan Expect(i.(int)).To(Equal(1)) }) It("should execution function on event", func() { - c := make(chan interface{}) var i int - On(c, func(data interface{}) { + e := NewEvent() + On(e, func(data interface{}) { i = data.(int) }) - c <- 10 + Publish(e, 10) + time.Sleep(1 * time.Millisecond) Expect(i).To(Equal(10)) }) It("should scale the value between 0...1", func() {