From 11ff06b0ace921e35010ed1e307acca1cd7396f6 Mon Sep 17 00:00:00 2001 From: derailed Date: Fri, 18 Jul 2014 14:18:01 -0600 Subject: [PATCH] First pass at adding some documentation --- .gitignore | 1 + Makefile | 6 +- connection.go | 2 +- doc.go | 99 +++++++++++++++++++++- gobot.go | 21 +++++ platforms/beaglebone/beaglebone_adaptor.go | 8 +- robot.go | 23 +++++ 7 files changed, 151 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index cb5f91c7..69b84ad8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.swp profile.cov count.out +*.swp diff --git a/Makefile b/Makefile index 39f92f57..51905f9d 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ PACKAGES := gobot gobot/api $(shell ls ./platforms | sed -e 's/^/gobot\/platforms\//') -.PHONY: test cover robeaux +.PHONY: test cover robeaux test: for package in $(PACKAGES) ; do \ go test github.com/hybridgroup/$$package ; \ done ; \ - + cover: echo "mode: count" > profile.cov ; \ for package in $(PACKAGES) ; do \ @@ -32,4 +32,4 @@ endif cd .. ; \ rm -rf robeaux-tmp/ ; \ go fmt ./robeaux/robeaux.go ; \ - + diff --git a/connection.go b/connection.go index 49d4df3c..c95e2304 100644 --- a/connection.go +++ b/connection.go @@ -42,7 +42,7 @@ func (c *connections) Start() error { return err } -// Filanize() finalizes all the connections. +// Finalize() finalizes all the connections. func (c *connections) Finalize() { for _, connection := range *c { connection.Finalize() diff --git a/doc.go b/doc.go index b715b615..8ec4189e 100644 --- a/doc.go +++ b/doc.go @@ -1,9 +1,104 @@ -package gobot +// Copyright 2014 The Gobot Authors, HybridGroup. All rights reserved. /* +Package gobot is the main point of entry in your Gobot application. A Gobot +is typically composed of one or more robots that makes up a project. -overall doc for my package +Commands are a way to expose your robots functionality with the external world. +A Gobot can be configured to expose a restful HTTP interface using the api +package. You can define custom commands on your Gobot and interact with your +application as a web service. +Basic Setup + package main + import ( + "fmt" + "time" + + "github.com/hybridgroup/gobot" + ) + + func main() { + gbot := gobot.NewGobot() + + robot := gobot.NewRobot("Eve", func() { + gobot.Every(500*time.Millisecond, func() { + fmt.Println("Greeting Human") + }) + }) + + gbot.AddRobot(robot) + + gbot.Start() + } + +Web Enabled? You bet! + + package main + + import ( + "fmt" + + "github.com/hybridgroup/gobot" + "github.com/hybridgroup/gobot/api" + ) + + func main() { + gbot := gobot.NewGobot() + + // Starts the API server on default port 3000 + api.NewAPI(gbot).Start() + + // Accessible via http://localhost:3000/api/commands/say_hello + gbot.AddCommand("say_hello", func(params map[string]interface{}) interface{} { + return "Master says hello!" + }) + + hello := gbot.AddRobot(gobot.NewRobot("Eve")) + + // Accessible via http://localhost:3000/robots/Eve/commands/say_hello + hello.AddCommand("say_hello", func(params map[string]interface{}) interface{} { + return fmt.Sprintf("%v says hello!", hello.Name) + }) + + gbot.Start() + } + +Blinking teh LED (Hello Eve!) + + package main + + import ( + "time" + + "github.com/hybridgroup/gobot" + "github.com/hybridgroup/gobot/platforms/firmata" + "github.com/hybridgroup/gobot/platforms/gpio" + ) + + func main() { + gbot := gobot.NewGobot() + + firmataAdaptor := firmata.NewFirmataAdaptor("arduino", "/dev/ttyACM0") + led := gpio.NewLedDriver(firmataAdaptor, "led", "13") + + work := func() { + gobot.Every(1*time.Second, func() { + led.Toggle() + }) + } + + robot := gobot.NewRobot("Eve", + []gobot.Connection{firmataAdaptor}, + []gobot.Device{led}, + work, + ) + + gbot.AddRobot(robot) + + gbot.Start() + } */ +package gobot diff --git a/gobot.go b/gobot.go index 1774ab84..7d246332 100644 --- a/gobot.go +++ b/gobot.go @@ -6,17 +6,20 @@ import ( "os/signal" ) +// JSONGobot holds a JSON representation of a Gobot. type JSONGobot struct { Robots []*JSONRobot `json:"robots"` Commands []string `json:"commands"` } +// Gobot is a container composed of one or more robots type Gobot struct { robots *robots commands map[string]func(map[string]interface{}) interface{} trap func(chan os.Signal) } +// NewGobot instantiates a new Gobot func NewGobot() *Gobot { return &Gobot{ robots: &robots{}, @@ -27,18 +30,32 @@ func NewGobot() *Gobot { } } +/* +AddCommand creates a new command and adds it to the Gobot. This command +will be available via HTTP using '/commands/name' + +Example: + gbot.AddCommand( 'rollover', func( params map[string]interface{}) interface{} { + fmt.Println( "Rolling over - Stand by...") + }) + + With the api package setup, you can now get your Gobot to rollover using: http://localhost:3000/commands/rollover +*/ func (g *Gobot) AddCommand(name string, f func(map[string]interface{}) interface{}) { g.commands[name] = f } +// Commands lists all available commands on this Gobot instance. func (g *Gobot) Commands() map[string]func(map[string]interface{}) interface{} { return g.commands } +// Command fetch the associated command using the given command name func (g *Gobot) Command(name string) func(map[string]interface{}) interface{} { return g.commands[name] } +// Start runs the main Gobot event loop func (g *Gobot) Start() { g.robots.Start() @@ -54,15 +71,18 @@ func (g *Gobot) Start() { }) } +// Robots fetch all robots associated with this Gobot instance. func (g *Gobot) Robots() *robots { return g.robots } +// AddRobot adds a new robot to our Gobot instance. func (g *Gobot) AddRobot(r *Robot) *Robot { *g.robots = append(*g.robots, r) return r } +// Robot find a robot with a given name. func (g *Gobot) Robot(name string) *Robot { for _, robot := range *g.Robots() { if robot.Name == name { @@ -72,6 +92,7 @@ func (g *Gobot) Robot(name string) *Robot { return nil } +// ToJSON retrieves a JSON representation of this Gobot. func (g *Gobot) ToJSON() *JSONGobot { jsonGobot := &JSONGobot{ Robots: []*JSONRobot{}, diff --git a/platforms/beaglebone/beaglebone_adaptor.go b/platforms/beaglebone/beaglebone_adaptor.go index f21d45a5..615725d9 100644 --- a/platforms/beaglebone/beaglebone_adaptor.go +++ b/platforms/beaglebone/beaglebone_adaptor.go @@ -10,9 +10,11 @@ import ( "strings" ) -const Slots = "/sys/devices/bone_capemgr.*" -const Ocp = "/sys/devices/ocp.*" -const I2CLocation = "/dev/i2c-1" +const ( + Slots = "/sys/devices/bone_capemgr.*" + Ocp = "/sys/devices/ocp.*" + I2CLocation = "/dev/i2c-1" +) var pins = map[string]int{ "P8_3": 38, diff --git a/robot.go b/robot.go index 12288804..b1b27761 100644 --- a/robot.go +++ b/robot.go @@ -5,6 +5,7 @@ import ( "log" ) +// JSONRobot a JSON representation of a robot. type JSONRobot struct { Name string `json:"name"` Commands []string `json:"commands"` @@ -12,6 +13,9 @@ type JSONRobot struct { Devices []*JSONDevice `json:"devices"` } +// Robot software representation of a physical board. A robot is a named +// entitity that manages multiple IO devices using a set of adaptors. Additionally +// a user can specificy custom commands to control a robot remotely. type Robot struct { Name string commands map[string]func(map[string]interface{}) interface{} @@ -22,22 +26,28 @@ type Robot struct { type robots []*Robot +// Len counts the robots associated with this instance. func (r *robots) Len() int { return len(*r) } +// Start initialises the event loop. All robots that were added will +// be automtically started as a result of this call. func (r *robots) Start() { for _, robot := range *r { robot.Start() } } +// Each enumerates thru the robts and calls specified function func (r *robots) Each(f func(*Robot)) { for _, robot := range *r { f(robot) } } +// NewRobot constructs a new named robot. Though a robot's name will be generated, +// we recommend that user take care of naming a robot for later access. func NewRobot(name string, v ...interface{}) *Robot { if name == "" { name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1))) @@ -77,18 +87,24 @@ func NewRobot(name string, v ...interface{}) *Robot { return r } +// AddCommand setup a new command that we be made available via the REST api. func (r *Robot) AddCommand(name string, f func(map[string]interface{}) interface{}) { r.commands[name] = f } +// Commands lists out all available commands on this robot. func (r *Robot) Commands() map[string]func(map[string]interface{}) interface{} { return r.commands } +// Command fetch a named command on this robot. func (r *Robot) Command(name string) func(map[string]interface{}) interface{} { return r.commands[name] } +// Start a robot instance and runs it's work function if any. You should not +// 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() { log.Println("Starting Robot", r.Name, "...") if err := r.Connections().Start(); err != nil { @@ -103,15 +119,18 @@ func (r *Robot) Start() { } } +// Devices retrieves all devices associated with this robot. func (r *Robot) Devices() *devices { return r.devices } +// AddDevice adds a new device on this robot. func (r *Robot) AddDevice(d Device) Device { *r.devices = append(*r.Devices(), d) return d } +// Device finds a device by name. func (r *Robot) Device(name string) Device { if r == nil { return nil @@ -124,15 +143,18 @@ func (r *Robot) Device(name string) Device { return nil } +// Connections retrieves all connections on this robot. func (r *Robot) Connections() *connections { return r.connections } +// AddConnection add a new connection on this robot. func (r *Robot) AddConnection(c Connection) Connection { *r.connections = append(*r.Connections(), c) return c } +// Connection finds a connection by name. func (r *Robot) Connection(name string) Connection { if r == nil { return nil @@ -145,6 +167,7 @@ func (r *Robot) Connection(name string) Connection { return nil } +// ToJSON returns a JSON representation of the master robot. func (r *Robot) ToJSON() *JSONRobot { jsonRobot := &JSONRobot{ Name: r.Name,