1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-29 13:49:14 +08:00

go lint and documentation tweaks for the gobot package

This commit is contained in:
Adrian Zankich 2014-12-31 05:15:52 -08:00
parent f19fd7dfa6
commit 8ea3ae2c8b
11 changed files with 103 additions and 74 deletions

View File

@ -1,11 +1,16 @@
package gobot package gobot
// Adaptor is the interface that describes an adaptor in gobot
type Adaptor interface { type Adaptor interface {
Finalize() []error // Name returns the label for the Adaptor
Connect() []error
Name() string Name() string
// Connect initiates the Adaptor
Connect() []error
// Finalize terminates the Adaptor
Finalize() []error
} }
// Porter is the interface that describes an adaptor's port
type Porter interface { type Porter interface {
Port() string Port() string
} }

View File

@ -4,30 +4,33 @@ type commander struct {
commands map[string]func(map[string]interface{}) interface{} commands map[string]func(map[string]interface{}) interface{}
} }
// Commander is the interface which describes the behaviour for a Driver or Adaptor
// which exposes API commands.
type Commander interface { type Commander interface {
// Command returns a command given a name. Returns nil if the command is not found.
Command(string) (command func(map[string]interface{}) interface{}) Command(string) (command func(map[string]interface{}) interface{})
// Commands returns a map of commands.
Commands() (commands map[string]func(map[string]interface{}) interface{}) Commands() (commands map[string]func(map[string]interface{}) interface{})
// AddCommand adds a command given a name.
AddCommand(name string, command func(map[string]interface{}) interface{}) AddCommand(name string, command func(map[string]interface{}) interface{})
} }
// NewCommander returns a new Commander.
func NewCommander() Commander { func NewCommander() Commander {
return &commander{ return &commander{
commands: make(map[string]func(map[string]interface{}) interface{}), commands: make(map[string]func(map[string]interface{}) interface{}),
} }
} }
// Command retrieves a command by name
func (c *commander) Command(name string) (command func(map[string]interface{}) interface{}) { func (c *commander) Command(name string) (command func(map[string]interface{}) interface{}) {
command, _ = c.commands[name] command, _ = c.commands[name]
return return
} }
// Commands returns a map of driver commands
func (c *commander) Commands() map[string]func(map[string]interface{}) interface{} { func (c *commander) Commands() map[string]func(map[string]interface{}) interface{} {
return c.commands return c.commands
} }
// AddCommand links specified command name to `f`
func (c *commander) AddCommand(name string, command func(map[string]interface{}) interface{}) { func (c *commander) AddCommand(name string, command func(map[string]interface{}) interface{}) {
c.commands[name] = command c.commands[name] = command
} }

View File

@ -1,19 +1,18 @@
package gobot package gobot
import ( import (
"errors"
"fmt" "fmt"
"log" "log"
"reflect" "reflect"
) )
// JSONConnection holds a JSON representation of a connection. // JSONConnection is a JSON representation of a Connection.
type JSONConnection struct { type JSONConnection struct {
Name string `json:"name"` Name string `json:"name"`
Adaptor string `json:"adaptor"` Adaptor string `json:"adaptor"`
} }
// ToJSON returns a json representation of an adaptor // NewJSONConnection returns a JSONConnection given a Connection.
func NewJSONConnection(connection Connection) *JSONConnection { func NewJSONConnection(connection Connection) *JSONConnection {
return &JSONConnection{ return &JSONConnection{
Name: connection.Name(), Name: connection.Name(),
@ -21,24 +20,26 @@ func NewJSONConnection(connection Connection) *JSONConnection {
} }
} }
// A Connection is an instance of an Adaptor
type Connection Adaptor type Connection Adaptor
type connections []Connection // Connections represents a collection of Connection
type Connections []Connection
// Len returns connections length // Len returns connections length
func (c *connections) Len() int { func (c *Connections) Len() int {
return len(*c) return len(*c)
} }
// Each calls function for each connection // Each enumerates through the Connections and calls specified callback function.
func (c *connections) Each(f func(Connection)) { func (c *Connections) Each(f func(Connection)) {
for _, connection := range *c { for _, connection := range *c {
f(connection) f(connection)
} }
} }
// Start initializes all the connections. // Start calls Connect on each Connection in c
func (c *connections) Start() (errs []error) { func (c *Connections) Start() (errs []error) {
log.Println("Starting connections...") log.Println("Starting connections...")
for _, connection := range *c { for _, connection := range *c {
info := "Starting connection " + connection.Name() info := "Starting connection " + connection.Name()
@ -51,7 +52,7 @@ func (c *connections) Start() (errs []error) {
if errs = connection.Connect(); len(errs) > 0 { if errs = connection.Connect(); len(errs) > 0 {
for i, err := range errs { for i, err := range errs {
errs[i] = errors.New(fmt.Sprintf("Connection %q: %v", connection.Name(), err)) errs[i] = fmt.Errorf("Connection %q: %v", connection.Name(), err)
} }
return return
} }
@ -59,12 +60,12 @@ func (c *connections) Start() (errs []error) {
return return
} }
// Finalize finishes all the connections. // Finalize calls Finalize on each Connection in c
func (c *connections) Finalize() (errs []error) { func (c *Connections) Finalize() (errs []error) {
for _, connection := range *c { for _, connection := range *c {
if cerrs := connection.Finalize(); cerrs != nil { if cerrs := connection.Finalize(); cerrs != nil {
for i, err := range cerrs { for i, err := range cerrs {
cerrs[i] = errors.New(fmt.Sprintf("Connection %q: %v", connection.Name(), err)) cerrs[i] = fmt.Errorf("Connection %q: %v", connection.Name(), err)
} }
errs = append(errs, cerrs...) errs = append(errs, cerrs...)
} }

View File

@ -1,13 +1,12 @@
package gobot package gobot
import ( import (
"errors"
"fmt" "fmt"
"log" "log"
"reflect" "reflect"
) )
// JSONDevice is a JSON representation of a Gobot Device. // JSONDevice is a JSON representation of a Device.
type JSONDevice struct { type JSONDevice struct {
Name string `json:"name"` Name string `json:"name"`
Driver string `json:"driver"` Driver string `json:"driver"`
@ -15,6 +14,7 @@ type JSONDevice struct {
Commands []string `json:"commands"` Commands []string `json:"commands"`
} }
// NewJSONDevice returns a JSONDevice given a Device.
func NewJSONDevice(device Device) *JSONDevice { func NewJSONDevice(device Device) *JSONDevice {
jsonDevice := &JSONDevice{ jsonDevice := &JSONDevice{
Name: device.Name(), Name: device.Name(),
@ -33,24 +33,26 @@ func NewJSONDevice(device Device) *JSONDevice {
return jsonDevice return jsonDevice
} }
// A Device is an instnace of a Driver
type Device Driver type Device Driver
type devices []Device // Devices represents a collection of Device
type Devices []Device
// Len returns devices length // Len returns devices length
func (d *devices) Len() int { func (d *Devices) Len() int {
return len(*d) return len(*d)
} }
// Each calls `f` function each device // Each enumerates through the Devices and calls specified callback function.
func (d *devices) Each(f func(Device)) { func (d *Devices) Each(f func(Device)) {
for _, device := range *d { for _, device := range *d {
f(device) f(device)
} }
} }
// Start starts all the devices. // Start calls Start on each Device in d
func (d *devices) Start() (errs []error) { func (d *Devices) Start() (errs []error) {
log.Println("Starting devices...") log.Println("Starting devices...")
for _, device := range *d { for _, device := range *d {
info := "Starting device " + device.Name() info := "Starting device " + device.Name()
@ -62,7 +64,7 @@ func (d *devices) Start() (errs []error) {
log.Println(info + "...") log.Println(info + "...")
if errs = device.Start(); len(errs) > 0 { if errs = device.Start(); len(errs) > 0 {
for i, err := range errs { for i, err := range errs {
errs[i] = errors.New(fmt.Sprintf("Device %q: %v", device.Name(), err)) errs[i] = fmt.Errorf("Device %q: %v", device.Name(), err)
} }
return return
} }
@ -70,12 +72,12 @@ func (d *devices) Start() (errs []error) {
return return
} }
// Halt stop all the devices. // Halt calls Halt on each Device in d
func (d *devices) Halt() (errs []error) { func (d *Devices) Halt() (errs []error) {
for _, device := range *d { for _, device := range *d {
if derrs := device.Halt(); len(derrs) > 0 { if derrs := device.Halt(); len(derrs) > 0 {
for i, err := range derrs { for i, err := range derrs {
derrs[i] = errors.New(fmt.Sprintf("Device %q: %v", device.Name(), err)) derrs[i] = fmt.Errorf("Device %q: %v", device.Name(), err)
} }
errs = append(errs, derrs...) errs = append(errs, derrs...)
} }

View File

@ -1,12 +1,18 @@
package gobot package gobot
// Driver is the interface that describes a driver in gobot
type Driver interface { type Driver interface {
Start() []error // Name returns the label for the Driver
Halt() []error
Name() string Name() string
// Start initiates the Driver
Start() []error
// Halt terminates the Driver
Halt() []error
// Connection returns the Connection assiciated with the Driver
Connection() Connection Connection() Connection
} }
// Pinner is the interface that describes a driver's pin
type Pinner interface { type Pinner interface {
Pin() string Pin() string
} }

View File

@ -5,12 +5,13 @@ type callback struct {
once bool once bool
} }
// Event executes the list of Callbacks when Chan is written to.
type Event struct { type Event struct {
Chan chan interface{} Chan chan interface{}
Callbacks []callback Callbacks []callback
} }
// NewEvent returns a new event which is then ready for publishing and subscribing. // NewEvent returns a new Event which is now listening for data.
func NewEvent() *Event { func NewEvent() *Event {
e := &Event{ e := &Event{
Chan: make(chan interface{}, 1), Chan: make(chan interface{}, 1),
@ -24,7 +25,8 @@ func NewEvent() *Event {
return e return e
} }
// Write writes data to the Event // Write writes data to the Event, it will not block and will not buffer if there
// are no active subscribers to the Event.
func (e *Event) Write(data interface{}) { func (e *Event) Write(data interface{}) {
select { select {
case e.Chan <- data: case e.Chan <- data:
@ -32,7 +34,7 @@ func (e *Event) Write(data interface{}) {
} }
} }
// Read publishes to all subscribers of e if there is any new data // Read executes all Callbacks when new data is available.
func (e *Event) Read() { func (e *Event) Read() {
for s := range e.Chan { for s := range e.Chan {
tmp := []callback{} tmp := []callback{}

View File

@ -4,30 +4,33 @@ type eventer struct {
events map[string]*Event events map[string]*Event
} }
// Eventer is the interface which describes behaviour for a Driver or Adaptor
// which uses events.
type Eventer interface { type Eventer interface {
// Events returns the Event map.
Events() (events map[string]*Event) Events() (events map[string]*Event)
// Event returns an Event by name. Returns nil if the Event is not found.
Event(name string) (event *Event) Event(name string) (event *Event)
// AddEvent adds a new Event given a name.
AddEvent(name string) AddEvent(name string)
} }
// NewEventer returns a new Eventer.
func NewEventer() Eventer { func NewEventer() Eventer {
return &eventer{ return &eventer{
events: make(map[string]*Event), events: make(map[string]*Event),
} }
} }
// Events returns driver events map
func (e *eventer) Events() map[string]*Event { func (e *eventer) Events() map[string]*Event {
return e.events return e.events
} }
// Event returns an event by name if exists
func (e *eventer) Event(name string) (event *Event) { func (e *eventer) Event(name string) (event *Event) {
event, _ = e.events[name] event, _ = e.events[name]
return return
} }
// AddEvents adds a new event by name
func (e *eventer) AddEvent(name string) { func (e *eventer) AddEvent(name string) {
e.events[name] = NewEvent() e.events[name] = NewEvent()
} }

View File

@ -6,13 +6,13 @@ import (
"os/signal" "os/signal"
) )
// JSONGobot holds a JSON representation of a Gobot. // JSONGobot is a JSON representation of a Gobot.
type JSONGobot struct { type JSONGobot struct {
Robots []*JSONRobot `json:"robots"` Robots []*JSONRobot `json:"robots"`
Commands []string `json:"commands"` Commands []string `json:"commands"`
} }
// ToJSON returns a JSON representation of this Gobot. // NewJSONGobot returns a JSONGobt given a Gobot.
func NewJSONGobot(gobot *Gobot) *JSONGobot { func NewJSONGobot(gobot *Gobot) *JSONGobot {
jsonGobot := &JSONGobot{ jsonGobot := &JSONGobot{
Robots: []*JSONRobot{}, Robots: []*JSONRobot{},
@ -29,9 +29,10 @@ func NewJSONGobot(gobot *Gobot) *JSONGobot {
return jsonGobot return jsonGobot
} }
// Gobot is a container composed of one or more robots // Gobot is the main type of your Gobot application and contains a collection of
// Robots, API commands and Events.
type Gobot struct { type Gobot struct {
robots *robots robots *Robots
trap func(chan os.Signal) trap func(chan os.Signal)
Commander Commander
Eventer Eventer
@ -40,7 +41,7 @@ type Gobot struct {
// NewGobot returns a new Gobot // NewGobot returns a new Gobot
func NewGobot() *Gobot { func NewGobot() *Gobot {
return &Gobot{ return &Gobot{
robots: &robots{}, robots: &Robots{},
trap: func(c chan os.Signal) { trap: func(c chan os.Signal) {
signal.Notify(c, os.Interrupt) signal.Notify(c, os.Interrupt)
}, },
@ -88,8 +89,8 @@ func (g *Gobot) Start() (errs []error) {
return errs return errs
} }
// Robots returns all robots associated with this Gobot instance. // Robots returns all robots associated with this Gobot.
func (g *Gobot) Robots() *robots { func (g *Gobot) Robots() *Robots {
return g.robots return g.robots
} }
@ -100,7 +101,7 @@ func (g *Gobot) AddRobot(r *Robot) *Robot {
return r return r
} }
// Robot returns a robot given name. Returns nil on no robot. // Robot returns a robot given name. Returns nil if the Robot does not exist.
func (g *Gobot) Robot(name string) *Robot { func (g *Gobot) Robot(name string) *Robot {
for _, robot := range *g.Robots() { for _, robot := range *g.Robots() {
if robot.Name == name { if robot.Name == name {

View File

@ -1,12 +1,11 @@
package gobot package gobot
import ( import (
"errors"
"fmt" "fmt"
"log" "log"
) )
// JSONRobot a JSON representation of a robot. // JSONRobot a JSON representation of a Robot.
type JSONRobot struct { type JSONRobot struct {
Name string `json:"name"` Name string `json:"name"`
Commands []string `json:"commands"` Commands []string `json:"commands"`
@ -14,7 +13,7 @@ type JSONRobot struct {
Devices []*JSONDevice `json:"devices"` Devices []*JSONDevice `json:"devices"`
} }
// NewJSONRobot returns a JSON representation of the robot. // NewJSONRobot returns a JSONRobot given a Robot.
func NewJSONRobot(robot *Robot) *JSONRobot { func NewJSONRobot(robot *Robot) *JSONRobot {
jsonRobot := &JSONRobot{ jsonRobot := &JSONRobot{
Name: robot.Name, Name: robot.Name,
@ -41,26 +40,26 @@ func NewJSONRobot(robot *Robot) *JSONRobot {
type Robot struct { type Robot struct {
Name string Name string
Work func() Work func()
connections *connections connections *Connections
devices *devices devices *Devices
Commander Commander
Eventer Eventer
} }
type robots []*Robot // Robots is a collection of Robot
type Robots []*Robot
// Len counts the robots associated with this instance. // Len returns the amount of Robots in the collection.
func (r *robots) Len() int { func (r *Robots) Len() int {
return len(*r) return len(*r)
} }
// Start initialises the event loop. All robots that were added will // Start calls the Start method of each Robot in the collection
// be automtically started as a result of this call. func (r *Robots) Start() (errs []error) {
func (r *robots) Start() (errs []error) {
for _, robot := range *r { for _, robot := range *r {
if errs = robot.Start(); len(errs) > 0 { if errs = robot.Start(); len(errs) > 0 {
for i, err := range errs { for i, err := range errs {
errs[i] = errors.New(fmt.Sprintf("Robot %q: %v", robot.Name, err)) errs[i] = fmt.Errorf("Robot %q: %v", robot.Name, err)
} }
return return
} }
@ -68,8 +67,8 @@ func (r *robots) Start() (errs []error) {
return return
} }
// Each enumerates thru the robots and calls specified function // Each enumerates through the Robots and calls specified callback function.
func (r *robots) Each(f func(*Robot)) { func (r *Robots) Each(f func(*Robot)) {
for _, robot := range *r { for _, robot := range *r {
f(robot) f(robot)
} }
@ -80,6 +79,7 @@ func (r *robots) Each(f func(*Robot)) {
// []Connection: Connections which are automatically started and stopped with the robot // []Connection: Connections which are automatically started and stopped with the robot
// []Device: Devices which are automatically started and stopped with the robot // []Device: Devices which are automatically started and stopped with the robot
// func(): The work routine the robot will execute once all devices and connections have been initialized and started // func(): The work routine the robot will execute once all devices and connections have been initialized and started
// A name will be automaically generated if no name is supplied.
func NewRobot(name string, v ...interface{}) *Robot { func NewRobot(name string, v ...interface{}) *Robot {
if name == "" { if name == "" {
name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1))) name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1)))
@ -87,8 +87,8 @@ func NewRobot(name string, v ...interface{}) *Robot {
r := &Robot{ r := &Robot{
Name: name, Name: name,
connections: &connections{}, connections: &Connections{},
devices: &devices{}, devices: &Devices{},
Work: nil, Work: nil,
Eventer: NewEventer(), Eventer: NewEventer(),
Commander: NewCommander(), Commander: NewCommander(),
@ -118,9 +118,7 @@ func NewRobot(name string, v ...interface{}) *Robot {
return r return r
} }
// Start a robot instance and runs it's work function if any. You should not // Start a Robot's Connections, Devices, and work.
// need to manually start a robot if already part of a Gobot application as the
// robot will be automatically started for you.
func (r *Robot) Start() (errs []error) { func (r *Robot) Start() (errs []error) {
log.Println("Starting Robot", r.Name, "...") log.Println("Starting Robot", r.Name, "...")
if cerrs := r.Connections().Start(); len(cerrs) > 0 { if cerrs := r.Connections().Start(); len(cerrs) > 0 {
@ -138,19 +136,19 @@ func (r *Robot) Start() (errs []error) {
return return
} }
// Devices returns all devices associated with this robot. // Devices returns all devices associated with this Robot.
func (r *Robot) Devices() *devices { func (r *Robot) Devices() *Devices {
return r.devices return r.devices
} }
// AddDevice adds a new device to the robots collection of devices. Returns the // AddDevice adds a new Device to the robots collection of devices. Returns the
// added device. // added device.
func (r *Robot) AddDevice(d Device) Device { func (r *Robot) AddDevice(d Device) Device {
*r.devices = append(*r.Devices(), d) *r.devices = append(*r.Devices(), d)
return d return d
} }
// Device returns a device given a name. Returns nil on no device. // Device returns a device given a name. Returns nil if the Device does not exist.
func (r *Robot) Device(name string) Device { func (r *Robot) Device(name string) Device {
if r == nil { if r == nil {
return nil return nil
@ -164,7 +162,7 @@ func (r *Robot) Device(name string) Device {
} }
// Connections returns all connections associated with this robot. // Connections returns all connections associated with this robot.
func (r *Robot) Connections() *connections { func (r *Robot) Connections() *Connections {
return r.connections return r.connections
} }
@ -175,7 +173,8 @@ func (r *Robot) AddConnection(c Connection) Connection {
return c return c
} }
// Connection returns a connection given a name. Returns nil on no connection. // Connection returns a connection given a name. Returns nil if the Connection
// does not exist.
func (r *Robot) Connection(name string) Connection { func (r *Robot) Connection(name string) Connection {
if r == nil { if r == nil {
return nil return nil

View File

@ -15,6 +15,7 @@ import (
) )
var ( var (
// ErrUnknownEvent is the error resulting if the specified Event does not exist
ErrUnknownEvent = errors.New("Event does not exist") ErrUnknownEvent = errors.New("Event does not exist")
) )
@ -37,6 +38,7 @@ func logFailure(t *testing.T, message string) {
errFunc(t, fmt.Sprintf("%v:%v: %v", s[len(s)-1], line, message)) errFunc(t, fmt.Sprintf("%v:%v: %v", s[len(s)-1], line, message))
} }
// Assert checks if a and b are equal, emis a t.Errorf if they are not equal.
func Assert(t *testing.T, a interface{}, b interface{}) { func Assert(t *testing.T, a interface{}, b interface{}) {
if !reflect.DeepEqual(a, b) { if !reflect.DeepEqual(a, b) {
logFailure(t, fmt.Sprintf("%v - \"%v\", should equal, %v - \"%v\"", logFailure(t, fmt.Sprintf("%v - \"%v\", should equal, %v - \"%v\"",
@ -44,6 +46,7 @@ func Assert(t *testing.T, a interface{}, b interface{}) {
} }
} }
// Refute checks if a and b are equal, emis a t.Errorf if they are equal.
func Refute(t *testing.T, a interface{}, b interface{}) { func Refute(t *testing.T, a interface{}, b interface{}) {
if reflect.DeepEqual(a, b) { if reflect.DeepEqual(a, b) {
logFailure(t, fmt.Sprintf("%v - \"%v\", should not equal, %v - \"%v\"", logFailure(t, fmt.Sprintf("%v - \"%v\", should not equal, %v - \"%v\"",
@ -69,7 +72,8 @@ func After(t time.Duration, f func()) {
time.AfterFunc(t, f) time.AfterFunc(t, f)
} }
// Publish emits val to all subscribers of e. // Publish emits val to all subscribers of e. Returns ErrUnknownEvent if Event
// does not exist.
func Publish(e *Event, val interface{}) (err error) { func Publish(e *Event, val interface{}) (err error) {
if err = eventError(e); err == nil { if err = eventError(e); err == nil {
e.Write(val) e.Write(val)
@ -77,7 +81,8 @@ func Publish(e *Event, val interface{}) (err error) {
return return
} }
// On executes f when e is Published to. // On executes f when e is Published to. Returns ErrUnknownEvent if Event
// does not exist.
func On(e *Event, f func(s interface{})) (err error) { func On(e *Event, f func(s interface{})) (err error) {
if err = eventError(e); err == nil { if err = eventError(e); err == nil {
e.Callbacks = append(e.Callbacks, callback{f, false}) e.Callbacks = append(e.Callbacks, callback{f, false})
@ -85,7 +90,8 @@ func On(e *Event, f func(s interface{})) (err error) {
return return
} }
// Once is similar to On except that it only executes f one time. // Once is similar to On except that it only executes f one time. Returns
//ErrUnknownEvent if Event does not exist.
func Once(e *Event, f func(s interface{})) (err error) { func Once(e *Event, f func(s interface{})) (err error) {
if err = eventError(e); err == nil { if err = eventError(e); err == nil {
e.Callbacks = append(e.Callbacks, callback{f, true}) e.Callbacks = append(e.Callbacks, callback{f, true})

View File

@ -2,6 +2,7 @@ package gobot
const version = "0.8.1" const version = "0.8.1"
// Version returns the current Gobot version
func Version() string { func Version() string {
return version return version
} }