commit
66cfedbb63
14
README.md
14
README.md
|
@ -54,6 +54,20 @@ func main() {
|
|||
robot.Start()
|
||||
}
|
||||
```
|
||||
## API:
|
||||
|
||||
Gobot includes a RESTful API to query the status of any robot running within a group, including the connection and device status, and execute device commands.
|
||||
|
||||
To activate the API, use the `Api` command like this:
|
||||
|
||||
```go
|
||||
master := gobot.GobotMaster()
|
||||
gobot.Api(master)
|
||||
```
|
||||
To specify the api port run your Gobot program with the `PORT` environment variable
|
||||
```
|
||||
$ PORT=8080 go run gobotProgram.go
|
||||
```
|
||||
|
||||
## Hardware Support
|
||||
Gobot has a extensible system for connecting to hardware devices. The following robotics and physical computing platforms are currently supported:
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package gobot
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/codegangsta/martini"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type api struct{}
|
||||
|
||||
func Api(bot *Master) {
|
||||
a := new(api)
|
||||
m := martini.Classic()
|
||||
|
||||
m.Get("/robots", func() string {
|
||||
return toJson(bot.Robots)
|
||||
})
|
||||
|
||||
m.Get("/robots/:robotname", func(params martini.Params) string {
|
||||
return toJson(bot.FindRobot(params["robotname"]))
|
||||
})
|
||||
|
||||
m.Get("/robots/:robotname/devices", func(params martini.Params) string {
|
||||
return toJson(bot.FindRobot(params["robotname"]).GetDevices())
|
||||
})
|
||||
|
||||
m.Get("/robots/:robotname/devices/:devicename", func(params martini.Params) string {
|
||||
return toJson(bot.FindRobotDevice(params["robotname"], params["devicename"]))
|
||||
})
|
||||
|
||||
m.Get("/robots/:robotname/devices/:devicename/commands", func(params martini.Params) string {
|
||||
return toJson(bot.FindRobotDevice(params["robotname"], params["devicename"]).Commands())
|
||||
})
|
||||
|
||||
command_route := "/robots/:robotname/devices/:devicename/commands/:command"
|
||||
|
||||
m.Get(command_route, func(params martini.Params, res http.ResponseWriter, req *http.Request) string {
|
||||
return a.executeCommand(bot, params, res, req)
|
||||
})
|
||||
m.Post(command_route, func(params martini.Params, res http.ResponseWriter, req *http.Request) string {
|
||||
return a.executeCommand(bot, params, res, req)
|
||||
})
|
||||
|
||||
go m.Run()
|
||||
}
|
||||
|
||||
func (a *api) executeCommand(bot *Master, params martini.Params, res http.ResponseWriter, req *http.Request) string {
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
var body map[string]interface{}
|
||||
decoder.Decode(&body)
|
||||
robot := bot.FindRobotDevice(params["robotname"], params["devicename"])
|
||||
commands := robot.Commands().([]string)
|
||||
for command := range commands {
|
||||
if commands[command] == params["command"] {
|
||||
ret := Call(robot.Driver, params["command"], body)
|
||||
return toJson(map[string]interface{}{"results": ret})
|
||||
}
|
||||
}
|
||||
return toJson(map[string]interface{}{"results": "Unknown Command"})
|
||||
}
|
|
@ -9,7 +9,7 @@ type Connection struct {
|
|||
Name string
|
||||
Adaptor interface{}
|
||||
Port string
|
||||
Robot *Robot
|
||||
Robot *Robot `json:"-"`
|
||||
Params map[string]string
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
type Device struct {
|
||||
Name string
|
||||
Interval string
|
||||
Robot *Robot
|
||||
Robot *Robot `json:"-"`
|
||||
Driver interface{}
|
||||
Params map[string]string
|
||||
}
|
||||
|
@ -29,6 +29,6 @@ func (d *Device) Start() {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *Device) Command(method_name string, arguments []string) {
|
||||
//dt.Driver.Command(method_name, arguments)
|
||||
func (d *Device) Commands() interface{} {
|
||||
return reflect.ValueOf(d.Driver).Elem().FieldByName("Commands").Interface()
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ type Driver struct {
|
|||
Pin string
|
||||
Name string
|
||||
Params map[string]string
|
||||
Events map[string]chan interface{}
|
||||
Commands []string
|
||||
Events map[string]chan interface{} `json:"-"`
|
||||
}
|
||||
|
||||
func NewDriver(d Driver) Driver {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/hybridgroup/gobot"
|
||||
"github.com/hybridgroup/gobot-sphero"
|
||||
)
|
||||
|
||||
func main() {
|
||||
master := gobot.GobotMaster()
|
||||
gobot.Api(master)
|
||||
|
||||
spheros := map[string]string{
|
||||
"Sphero-BPO": "127.0.0.1:4560",
|
||||
}
|
||||
|
||||
for name, port := range spheros {
|
||||
spheroAdaptor := new(gobotSphero.SpheroAdaptor)
|
||||
spheroAdaptor.Name = "sphero"
|
||||
spheroAdaptor.Port = port
|
||||
|
||||
sphero := gobotSphero.NewSphero(spheroAdaptor)
|
||||
sphero.Name = "sphero"
|
||||
sphero.Interval = "0.5s"
|
||||
|
||||
work := func() {
|
||||
sphero.SetRGB(uint8(255), uint8(0), uint8(0))
|
||||
}
|
||||
|
||||
master.Robots = append(master.Robots, gobot.Robot{
|
||||
Name: name,
|
||||
Connections: []interface{}{spheroAdaptor},
|
||||
Devices: []interface{}{sphero},
|
||||
Work: work,
|
||||
})
|
||||
}
|
||||
|
||||
master.Start()
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/hybridgroup/gobot"
|
||||
"github.com/hybridgroup/gobot-sphero"
|
||||
)
|
||||
|
||||
func main() {
|
||||
master := gobot.GobotMaster()
|
||||
|
||||
spheros := map[string]string{
|
||||
"Sphero-BPO": "127.0.0.1:4560",
|
||||
}
|
||||
|
||||
for name, port := range spheros {
|
||||
spheroAdaptor := new(gobotSphero.SpheroAdaptor)
|
||||
spheroAdaptor.Name = "sphero"
|
||||
spheroAdaptor.Port = port
|
||||
|
||||
sphero := gobotSphero.NewSphero(spheroAdaptor)
|
||||
sphero.Name = "sphero"
|
||||
sphero.Interval = "0.5s"
|
||||
|
||||
work := func() {
|
||||
sphero.SetRGB(uint8(255), uint8(0), uint8(0))
|
||||
}
|
||||
|
||||
master.Robots = append(master.Robots, gobot.Robot{
|
||||
Name: name,
|
||||
Connections: []interface{}{spheroAdaptor},
|
||||
Devices: []interface{}{sphero},
|
||||
Work: work,
|
||||
})
|
||||
}
|
||||
|
||||
master.Robots = append(master.Robots, gobot.Robot{
|
||||
Work: func() {
|
||||
sphero := master.FindRobot("Sphero-BPO")
|
||||
gobot.Every("1s", func() {
|
||||
gobot.Call(sphero.GetDevice("sphero").Driver, "SetRGB", uint8(gobot.Rand(255)), uint8(gobot.Rand(255)), uint8(gobot.Rand(255)))
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
master.Start()
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package gobot
|
||||
|
||||
import "time"
|
||||
|
||||
type Master struct {
|
||||
Robots []Robot
|
||||
}
|
||||
|
||||
func GobotMaster() *Master {
|
||||
m := new(Master)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Master) Start() {
|
||||
for s := range m.Robots {
|
||||
go m.Robots[s].Start()
|
||||
}
|
||||
|
||||
for {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Master) FindRobot(name string) *Robot {
|
||||
for s := range m.Robots {
|
||||
if m.Robots[s].Name == name {
|
||||
return &m.Robots[s]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Master) FindRobotDevice(name string, device string) *Device {
|
||||
for r := range m.Robots {
|
||||
if m.Robots[r].Name == name {
|
||||
for d := range m.Robots[r].devices {
|
||||
if m.Robots[r].devices[d].Name == device {
|
||||
return m.Robots[r].devices[d]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Master) FindRobotConnection(name string, connection string) *Connection {
|
||||
for r := range m.Robots {
|
||||
if m.Robots[r].Name == name {
|
||||
for c := range m.Robots[r].connections {
|
||||
if m.Robots[r].connections[c].Name == connection {
|
||||
return m.Robots[r].connections[c]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
19
robot.go
19
robot.go
|
@ -11,9 +11,9 @@ type Robot struct {
|
|||
Connections []interface{}
|
||||
Devices []interface{}
|
||||
Name string
|
||||
Work func()
|
||||
connections []*Connection
|
||||
devices []*Device
|
||||
Work func() `json:"-"`
|
||||
connections []*Connection `json:"-"`
|
||||
devices []*Device `json:"-"`
|
||||
}
|
||||
|
||||
func (r *Robot) Start() {
|
||||
|
@ -65,3 +65,16 @@ func (r *Robot) startDevices() {
|
|||
r.devices[i].Start()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Robot) GetDevices() []*Device {
|
||||
return r.devices
|
||||
}
|
||||
|
||||
func (r *Robot) GetDevice(name string) *Device {
|
||||
for i := range r.devices {
|
||||
if r.devices[i].Name == name {
|
||||
return r.devices[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package gobot
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"net"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -25,9 +27,6 @@ func After(t string, f func()) {
|
|||
}
|
||||
|
||||
func parseDuration(t string) time.Duration {
|
||||
return ParseDuration(t)
|
||||
}
|
||||
func ParseDuration(t string) time.Duration {
|
||||
dur, err := time.ParseDuration(t)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -35,9 +34,9 @@ func ParseDuration(t string) time.Duration {
|
|||
return dur
|
||||
}
|
||||
|
||||
func Random(min int, max int) int {
|
||||
func Rand(max int) int {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
return rand.Intn(max-min) + min
|
||||
return rand.Intn(max)
|
||||
}
|
||||
|
||||
func On(cs chan interface{}) interface{} {
|
||||
|
@ -47,15 +46,6 @@ func On(cs chan interface{}) interface{} {
|
|||
return nil
|
||||
}
|
||||
|
||||
func Work(robots []Robot) {
|
||||
for s := range robots {
|
||||
go robots[s].Start()
|
||||
}
|
||||
for {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func ConnectTo(port string) net.Conn {
|
||||
tcpPort, err := net.Dial("tcp", port)
|
||||
if err != nil {
|
||||
|
@ -63,3 +53,16 @@ func ConnectTo(port string) net.Conn {
|
|||
}
|
||||
return tcpPort
|
||||
}
|
||||
|
||||
func Call(thing interface{}, method string, params ...interface{}) []reflect.Value {
|
||||
in := make([]reflect.Value, len(params))
|
||||
for k, param := range params {
|
||||
in[k] = reflect.ValueOf(param)
|
||||
}
|
||||
return reflect.ValueOf(thing).MethodByName(method).Call(in)
|
||||
}
|
||||
|
||||
func toJson(obj interface{}) string {
|
||||
b, _ := json.Marshal(obj)
|
||||
return string(b)
|
||||
}
|
Loading…
Reference in New Issue