mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-04-27 13:48:56 +08:00
Adds godoc to api package
This commit is contained in:
parent
6d2e25b0d8
commit
ad96293edb
10
adaptor.go
10
adaptor.go
@ -9,6 +9,7 @@ type Adaptor struct {
|
|||||||
adaptorType string
|
adaptorType string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdaptorInterface defines behaviour expected for a Gobot Adaptor
|
||||||
type AdaptorInterface interface {
|
type AdaptorInterface interface {
|
||||||
Finalize() bool
|
Finalize() bool
|
||||||
Connect() bool
|
Connect() bool
|
||||||
@ -22,6 +23,7 @@ type AdaptorInterface interface {
|
|||||||
ToJSON() *JSONConnection
|
ToJSON() *JSONConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAdaptor returns a new Gobot Adaptor
|
||||||
func NewAdaptor(name string, adaptorType string, v ...interface{}) *Adaptor {
|
func NewAdaptor(name string, adaptorType string, v ...interface{}) *Adaptor {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1)))
|
name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1)))
|
||||||
@ -43,34 +45,42 @@ func NewAdaptor(name string, adaptorType string, v ...interface{}) *Adaptor {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Port returns adaptor port
|
||||||
func (a *Adaptor) Port() string {
|
func (a *Adaptor) Port() string {
|
||||||
return a.port
|
return a.port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPort sets adaptor port
|
||||||
func (a *Adaptor) SetPort(s string) {
|
func (a *Adaptor) SetPort(s string) {
|
||||||
a.port = s
|
a.port = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns adaptor name
|
||||||
func (a *Adaptor) Name() string {
|
func (a *Adaptor) Name() string {
|
||||||
return a.name
|
return a.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetName sets adaptor name
|
||||||
func (a *Adaptor) SetName(s string) {
|
func (a *Adaptor) SetName(s string) {
|
||||||
a.name = s
|
a.name = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type returns adaptor type
|
||||||
func (a *Adaptor) Type() string {
|
func (a *Adaptor) Type() string {
|
||||||
return a.adaptorType
|
return a.adaptorType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connected returns true if adaptor is connected
|
||||||
func (a *Adaptor) Connected() bool {
|
func (a *Adaptor) Connected() bool {
|
||||||
return a.connected
|
return a.connected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetConnected sets adaptor as connected/disconnected
|
||||||
func (a *Adaptor) SetConnected(b bool) {
|
func (a *Adaptor) SetConnected(b bool) {
|
||||||
a.connected = b
|
a.connected = b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToJSON returns a json representation of adaptor
|
||||||
func (a *Adaptor) ToJSON() *JSONConnection {
|
func (a *Adaptor) ToJSON() *JSONConnection {
|
||||||
return &JSONConnection{
|
return &JSONConnection{
|
||||||
Name: a.Name(),
|
Name: a.Name(),
|
||||||
|
48
api/api.go
48
api/api.go
@ -12,8 +12,6 @@ import (
|
|||||||
"github.com/hybridgroup/gobot/api/robeaux"
|
"github.com/hybridgroup/gobot/api/robeaux"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Optional restful API through Gobot has access
|
|
||||||
// all the robots.
|
|
||||||
type api struct {
|
type api struct {
|
||||||
gobot *gobot.Gobot
|
gobot *gobot.Gobot
|
||||||
router *pat.PatternServeMux
|
router *pat.PatternServeMux
|
||||||
@ -25,6 +23,8 @@ type api struct {
|
|||||||
start func(*api)
|
start func(*api)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newAPI returns a gobot api instance
|
||||||
|
// and starts a http server using configuration options
|
||||||
func NewAPI(g *gobot.Gobot) *api {
|
func NewAPI(g *gobot.Gobot) *api {
|
||||||
return &api{
|
return &api{
|
||||||
gobot: g,
|
gobot: g,
|
||||||
@ -47,6 +47,7 @@ func NewAPI(g *gobot.Gobot) *api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServeHTTP calls api handlers and then serves request using api router
|
||||||
func (a *api) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
func (a *api) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||||
for _, handler := range a.handlers {
|
for _, handler := range a.handlers {
|
||||||
handler(res, req)
|
handler(res, req)
|
||||||
@ -54,38 +55,43 @@ func (a *api) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
|||||||
a.router.ServeHTTP(res, req)
|
a.router.ServeHTTP(res, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Post wraps api router Post call
|
||||||
func (a *api) Post(path string, f func(http.ResponseWriter, *http.Request)) {
|
func (a *api) Post(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||||
a.router.Post(path, http.HandlerFunc(f))
|
a.router.Post(path, http.HandlerFunc(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Put wraps api router Put call
|
||||||
func (a *api) Put(path string, f func(http.ResponseWriter, *http.Request)) {
|
func (a *api) Put(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||||
a.router.Put(path, http.HandlerFunc(f))
|
a.router.Put(path, http.HandlerFunc(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete wraps api router Delete call
|
||||||
func (a *api) Delete(path string, f func(http.ResponseWriter, *http.Request)) {
|
func (a *api) Delete(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||||
a.router.Del(path, http.HandlerFunc(f))
|
a.router.Del(path, http.HandlerFunc(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Options wraps api router Options call
|
||||||
func (a *api) Options(path string, f func(http.ResponseWriter, *http.Request)) {
|
func (a *api) Options(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||||
a.router.Options(path, http.HandlerFunc(f))
|
a.router.Options(path, http.HandlerFunc(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get wraps api router Get call
|
||||||
func (a *api) Get(path string, f func(http.ResponseWriter, *http.Request)) {
|
func (a *api) Get(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||||
a.router.Get(path, http.HandlerFunc(f))
|
a.router.Get(path, http.HandlerFunc(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Head wraps api router Head call
|
||||||
func (a *api) Head(path string, f func(http.ResponseWriter, *http.Request)) {
|
func (a *api) Head(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||||
a.router.Head(path, http.HandlerFunc(f))
|
a.router.Head(path, http.HandlerFunc(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddHandler appends handler to api handlers
|
||||||
func (a *api) AddHandler(f func(http.ResponseWriter, *http.Request)) {
|
func (a *api) AddHandler(f func(http.ResponseWriter, *http.Request)) {
|
||||||
a.handlers = append(a.handlers, f)
|
a.handlers = append(a.handlers, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// start starts the api using the start function
|
// Start initializes the api by setting up c3pio routes and robeaux
|
||||||
// sets on the API on initialization.
|
|
||||||
func (a *api) Start() {
|
func (a *api) Start() {
|
||||||
// api
|
|
||||||
mcpCommandRoute := "/api/commands/:command"
|
mcpCommandRoute := "/api/commands/:command"
|
||||||
deviceCommandRoute := "/api/robots/:robot/devices/:device/commands/:command"
|
deviceCommandRoute := "/api/robots/:robot/devices/:device/commands/:command"
|
||||||
robotCommandRoute := "/api/robots/:robot/commands/:command"
|
robotCommandRoute := "/api/robots/:robot/commands/:command"
|
||||||
@ -108,7 +114,6 @@ func (a *api) Start() {
|
|||||||
a.Get("/api/robots/:robot/connections/:connection", a.robotConnection)
|
a.Get("/api/robots/:robot/connections/:connection", a.robotConnection)
|
||||||
a.Get("/api/", a.mcp)
|
a.Get("/api/", a.mcp)
|
||||||
|
|
||||||
// robeaux
|
|
||||||
a.Get("/", func(res http.ResponseWriter, req *http.Request) {
|
a.Get("/", func(res http.ResponseWriter, req *http.Request) {
|
||||||
http.Redirect(res, req, "/index.html", http.StatusMovedPermanently)
|
http.Redirect(res, req, "/index.html", http.StatusMovedPermanently)
|
||||||
})
|
})
|
||||||
@ -125,6 +130,8 @@ func (a *api) Start() {
|
|||||||
a.start(a)
|
a.start(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robeaux returns handler for robeaux routes.
|
||||||
|
// Writes asset in response and sets correct header
|
||||||
func (a *api) robeaux(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robeaux(res http.ResponseWriter, req *http.Request) {
|
||||||
path := req.URL.Path
|
path := req.URL.Path
|
||||||
buf, err := robeaux.Asset(path[1:])
|
buf, err := robeaux.Asset(path[1:])
|
||||||
@ -141,14 +148,20 @@ func (a *api) robeaux(res http.ResponseWriter, req *http.Request) {
|
|||||||
res.Write(buf)
|
res.Write(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mcp returns MCP route handler.
|
||||||
|
// Writes JSON with gobot representation
|
||||||
func (a *api) mcp(res http.ResponseWriter, req *http.Request) {
|
func (a *api) mcp(res http.ResponseWriter, req *http.Request) {
|
||||||
a.writeJSON(map[string]interface{}{"MCP": a.gobot.ToJSON()}, res)
|
a.writeJSON(map[string]interface{}{"MCP": a.gobot.ToJSON()}, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mcpCommands returns commands route handler.
|
||||||
|
// Writes JSON with global commands representation
|
||||||
func (a *api) mcpCommands(res http.ResponseWriter, req *http.Request) {
|
func (a *api) mcpCommands(res http.ResponseWriter, req *http.Request) {
|
||||||
a.writeJSON(map[string]interface{}{"commands": a.gobot.ToJSON().Commands}, res)
|
a.writeJSON(map[string]interface{}{"commands": a.gobot.ToJSON().Commands}, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robots returns route handler.
|
||||||
|
// Writes JSON with robots representation
|
||||||
func (a *api) robots(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robots(res http.ResponseWriter, req *http.Request) {
|
||||||
jsonRobots := []*gobot.JSONRobot{}
|
jsonRobots := []*gobot.JSONRobot{}
|
||||||
a.gobot.Robots().Each(func(r *gobot.Robot) {
|
a.gobot.Robots().Each(func(r *gobot.Robot) {
|
||||||
@ -157,14 +170,20 @@ func (a *api) robots(res http.ResponseWriter, req *http.Request) {
|
|||||||
a.writeJSON(map[string]interface{}{"robots": jsonRobots}, res)
|
a.writeJSON(map[string]interface{}{"robots": jsonRobots}, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robot returns route handler.
|
||||||
|
// Writes JSON with robot representation
|
||||||
func (a *api) robot(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robot(res http.ResponseWriter, req *http.Request) {
|
||||||
a.writeJSON(map[string]interface{}{"robot": a.gobot.Robot(req.URL.Query().Get(":robot")).ToJSON()}, res)
|
a.writeJSON(map[string]interface{}{"robot": a.gobot.Robot(req.URL.Query().Get(":robot")).ToJSON()}, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robotCommands returns commands route handler
|
||||||
|
// Writes JSON with robot commands representation
|
||||||
func (a *api) robotCommands(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robotCommands(res http.ResponseWriter, req *http.Request) {
|
||||||
a.writeJSON(map[string]interface{}{"commands": a.gobot.Robot(req.URL.Query().Get(":robot")).ToJSON().Commands}, res)
|
a.writeJSON(map[string]interface{}{"commands": a.gobot.Robot(req.URL.Query().Get(":robot")).ToJSON().Commands}, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robotDevices returns devices route handler.
|
||||||
|
// Writes JSON with robot devices representation
|
||||||
func (a *api) robotDevices(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robotDevices(res http.ResponseWriter, req *http.Request) {
|
||||||
jsonDevices := []*gobot.JSONDevice{}
|
jsonDevices := []*gobot.JSONDevice{}
|
||||||
a.gobot.Robot(req.URL.Query().Get(":robot")).Devices().Each(func(d gobot.Device) {
|
a.gobot.Robot(req.URL.Query().Get(":robot")).Devices().Each(func(d gobot.Device) {
|
||||||
@ -173,6 +192,8 @@ func (a *api) robotDevices(res http.ResponseWriter, req *http.Request) {
|
|||||||
a.writeJSON(map[string]interface{}{"devices": jsonDevices}, res)
|
a.writeJSON(map[string]interface{}{"devices": jsonDevices}, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robotDevice returns device route handler.
|
||||||
|
// Writes JSON with robot device representation
|
||||||
func (a *api) robotDevice(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robotDevice(res http.ResponseWriter, req *http.Request) {
|
||||||
a.writeJSON(
|
a.writeJSON(
|
||||||
map[string]interface{}{"device": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
map[string]interface{}{"device": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||||
@ -180,6 +201,9 @@ func (a *api) robotDevice(res http.ResponseWriter, req *http.Request) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robotDeviceEvent returns device event route handler.
|
||||||
|
// Creates an event stream connection
|
||||||
|
// and queries event data to be written when received
|
||||||
func (a *api) robotDeviceEvent(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robotDeviceEvent(res http.ResponseWriter, req *http.Request) {
|
||||||
f, _ := res.(http.Flusher)
|
f, _ := res.(http.Flusher)
|
||||||
c, _ := res.(http.CloseNotifier)
|
c, _ := res.(http.CloseNotifier)
|
||||||
@ -210,6 +234,8 @@ func (a *api) robotDeviceEvent(res http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robotDeviceCommands returns device commands route handler
|
||||||
|
// writes JSON with robot device commands representation
|
||||||
func (a *api) robotDeviceCommands(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robotDeviceCommands(res http.ResponseWriter, req *http.Request) {
|
||||||
a.writeJSON(
|
a.writeJSON(
|
||||||
map[string]interface{}{"commands": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
map[string]interface{}{"commands": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||||
@ -217,6 +243,8 @@ func (a *api) robotDeviceCommands(res http.ResponseWriter, req *http.Request) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robotConnections returns connections route handler
|
||||||
|
// writes JSON with robot connections representation
|
||||||
func (a *api) robotConnections(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robotConnections(res http.ResponseWriter, req *http.Request) {
|
||||||
jsonConnections := []*gobot.JSONConnection{}
|
jsonConnections := []*gobot.JSONConnection{}
|
||||||
a.gobot.Robot(req.URL.Query().Get(":robot")).Connections().Each(func(c gobot.Connection) {
|
a.gobot.Robot(req.URL.Query().Get(":robot")).Connections().Each(func(c gobot.Connection) {
|
||||||
@ -225,6 +253,8 @@ func (a *api) robotConnections(res http.ResponseWriter, req *http.Request) {
|
|||||||
a.writeJSON(map[string]interface{}{"connections": jsonConnections}, res)
|
a.writeJSON(map[string]interface{}{"connections": jsonConnections}, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// robotConnection returns connection route handler
|
||||||
|
// writes JSON with robot connection representation
|
||||||
func (a *api) robotConnection(res http.ResponseWriter, req *http.Request) {
|
func (a *api) robotConnection(res http.ResponseWriter, req *http.Request) {
|
||||||
a.writeJSON(
|
a.writeJSON(
|
||||||
map[string]interface{}{"connection": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
map[string]interface{}{"connection": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||||
@ -233,6 +263,7 @@ func (a *api) robotConnection(res http.ResponseWriter, req *http.Request) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// executeMcpCommand calls a global command asociated to requested route
|
||||||
func (a *api) executeMcpCommand(res http.ResponseWriter, req *http.Request) {
|
func (a *api) executeMcpCommand(res http.ResponseWriter, req *http.Request) {
|
||||||
a.executeCommand(a.gobot.Command(req.URL.Query().Get(":command")),
|
a.executeCommand(a.gobot.Command(req.URL.Query().Get(":command")),
|
||||||
res,
|
res,
|
||||||
@ -240,6 +271,7 @@ func (a *api) executeMcpCommand(res http.ResponseWriter, req *http.Request) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// executeDeviceCommand calls a device command asociated to requested route
|
||||||
func (a *api) executeDeviceCommand(res http.ResponseWriter, req *http.Request) {
|
func (a *api) executeDeviceCommand(res http.ResponseWriter, req *http.Request) {
|
||||||
a.executeCommand(
|
a.executeCommand(
|
||||||
a.gobot.Robot(req.URL.Query().Get(":robot")).
|
a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||||
@ -250,6 +282,7 @@ func (a *api) executeDeviceCommand(res http.ResponseWriter, req *http.Request) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// executeRobotCommand calls a robot command asociated to requested route
|
||||||
func (a *api) executeRobotCommand(res http.ResponseWriter, req *http.Request) {
|
func (a *api) executeRobotCommand(res http.ResponseWriter, req *http.Request) {
|
||||||
a.executeCommand(
|
a.executeCommand(
|
||||||
a.gobot.Robot(req.URL.Query().Get(":robot")).
|
a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||||
@ -259,6 +292,7 @@ func (a *api) executeRobotCommand(res http.ResponseWriter, req *http.Request) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// executeCommand writes JSON response with `f` returned value.
|
||||||
func (a *api) executeCommand(f func(map[string]interface{}) interface{},
|
func (a *api) executeCommand(f func(map[string]interface{}) interface{},
|
||||||
res http.ResponseWriter,
|
res http.ResponseWriter,
|
||||||
req *http.Request,
|
req *http.Request,
|
||||||
@ -274,12 +308,14 @@ func (a *api) executeCommand(f func(map[string]interface{}) interface{},
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeJSON writes `j` as JSON in response
|
||||||
func (a *api) writeJSON(j interface{}, res http.ResponseWriter) {
|
func (a *api) writeJSON(j interface{}, res http.ResponseWriter) {
|
||||||
data, _ := json.Marshal(j)
|
data, _ := json.Marshal(j)
|
||||||
res.Header().Set("Content-Type", "application/json; charset=utf-8")
|
res.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
res.Write(data)
|
res.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug add handler to api that prints each request
|
||||||
func (a *api) Debug() {
|
func (a *api) Debug() {
|
||||||
a.AddHandler(func(res http.ResponseWriter, req *http.Request) {
|
a.AddHandler(func(res http.ResponseWriter, req *http.Request) {
|
||||||
log.Println(req)
|
log.Println(req)
|
||||||
|
@ -6,9 +6,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BasicAuth returns basic auth handler.
|
||||||
|
// Inspired by https://github.com/codegangsta/martini-contrib/blob/master/auth/
|
||||||
func BasicAuth(username, password string) http.HandlerFunc {
|
func BasicAuth(username, password string) http.HandlerFunc {
|
||||||
// basic auth inspired by
|
|
||||||
// https://github.com/codegangsta/martini-contrib/blob/master/auth/
|
|
||||||
return func(res http.ResponseWriter, req *http.Request) {
|
return func(res http.ResponseWriter, req *http.Request) {
|
||||||
if !secureCompare(req.Header.Get("Authorization"),
|
if !secureCompare(req.Header.Get("Authorization"),
|
||||||
"Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)),
|
"Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)),
|
||||||
|
@ -14,6 +14,7 @@ type CORS struct {
|
|||||||
allowOriginPatterns []string
|
allowOriginPatterns []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AllowRequestFrom returns handler to verify that requests come from allowedOrigins
|
||||||
func AllowRequestsFrom(allowedOrigins ...string) http.HandlerFunc {
|
func AllowRequestsFrom(allowedOrigins ...string) http.HandlerFunc {
|
||||||
c := &CORS{
|
c := &CORS{
|
||||||
AllowOrigins: allowedOrigins,
|
AllowOrigins: allowedOrigins,
|
||||||
@ -35,6 +36,7 @@ func AllowRequestsFrom(allowedOrigins ...string) http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isOriginAllowed returns true if origin matches an allowed origin pattern.
|
||||||
func (c *CORS) isOriginAllowed(origin string) (allowed bool) {
|
func (c *CORS) isOriginAllowed(origin string) (allowed bool) {
|
||||||
for _, allowedOriginPattern := range c.allowOriginPatterns {
|
for _, allowedOriginPattern := range c.allowOriginPatterns {
|
||||||
allowed, _ = regexp.MatchString(allowedOriginPattern, origin)
|
allowed, _ = regexp.MatchString(allowedOriginPattern, origin)
|
||||||
@ -45,6 +47,7 @@ func (c *CORS) isOriginAllowed(origin string) (allowed bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generatePatterns generates regex expresions for AllowOrigins
|
||||||
func (c *CORS) generatePatterns() {
|
func (c *CORS) generatePatterns() {
|
||||||
if c.AllowOrigins != nil {
|
if c.AllowOrigins != nil {
|
||||||
for _, origin := range c.AllowOrigins {
|
for _, origin := range c.AllowOrigins {
|
||||||
@ -56,10 +59,12 @@ func (c *CORS) generatePatterns() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AllowedHeaders returns allowed headers in a string
|
||||||
func (c *CORS) AllowedHeaders() string {
|
func (c *CORS) AllowedHeaders() string {
|
||||||
return strings.Join(c.AllowHeaders, ",")
|
return strings.Join(c.AllowHeaders, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AllowedMethods returns allowed http methods in a string
|
||||||
func (c *CORS) AllowedMethods() string {
|
func (c *CORS) AllowedMethods() string {
|
||||||
return strings.Join(c.AllowMethods, ",")
|
return strings.Join(c.AllowMethods, ",")
|
||||||
}
|
}
|
||||||
|
40
api/doc.go
Normal file
40
api/doc.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Package api provides functionally to expose your gobot programs
|
||||||
|
to other by using starting a web server and adding commands.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
It follows Common Protocol for Programming Physical Input and Output (CPPP-IO) spec:
|
||||||
|
https://github.com/hybridgroup/cppp-io
|
||||||
|
*/
|
||||||
|
package api
|
@ -5,6 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// JSONConnection holds 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"`
|
||||||
@ -14,17 +15,19 @@ type Connection AdaptorInterface
|
|||||||
|
|
||||||
type connections []Connection
|
type connections []Connection
|
||||||
|
|
||||||
|
// 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
|
||||||
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() starts all the connections.
|
// Start initializes all the connections.
|
||||||
func (c *connections) Start() error {
|
func (c *connections) Start() error {
|
||||||
var err error
|
var err error
|
||||||
log.Println("Starting connections...")
|
log.Println("Starting connections...")
|
||||||
@ -42,7 +45,7 @@ func (c *connections) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize() finalizes all the connections.
|
// Finalize finishes all the connections.
|
||||||
func (c *connections) Finalize() {
|
func (c *connections) Finalize() {
|
||||||
for _, connection := range *c {
|
for _, connection := range *c {
|
||||||
connection.Finalize()
|
connection.Finalize()
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// JSONDevice is a JSON representation of a Gobot Device.
|
||||||
type JSONDevice struct {
|
type JSONDevice struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Driver string `json:"driver"`
|
Driver string `json:"driver"`
|
||||||
@ -16,17 +17,19 @@ type Device DriverInterface
|
|||||||
|
|
||||||
type devices []Device
|
type devices []Device
|
||||||
|
|
||||||
|
// 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
|
||||||
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 starts all the devices.
|
||||||
func (d *devices) Start() error {
|
func (d *devices) Start() error {
|
||||||
var err error
|
var err error
|
||||||
log.Println("Starting devices...")
|
log.Println("Starting devices...")
|
||||||
@ -44,7 +47,7 @@ func (d *devices) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Halt() stop all the devices.
|
// Halt stop all the devices.
|
||||||
func (d *devices) Halt() {
|
func (d *devices) Halt() {
|
||||||
for _, device := range *d {
|
for _, device := range *d {
|
||||||
device.Halt()
|
device.Halt()
|
||||||
|
18
driver.go
18
driver.go
@ -5,6 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DriverInterface defines Driver expected behaviour
|
||||||
type DriverInterface interface {
|
type DriverInterface interface {
|
||||||
Start() bool
|
Start() bool
|
||||||
Halt() bool
|
Halt() bool
|
||||||
@ -35,6 +36,8 @@ type Driver struct {
|
|||||||
driverType string
|
driverType string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDriver returns a Driver with specified parameters
|
||||||
|
// and sets driver pin, adaptor and interval
|
||||||
func NewDriver(name string, driverType string, v ...interface{}) *Driver {
|
func NewDriver(name string, driverType string, v ...interface{}) *Driver {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1)))
|
name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1)))
|
||||||
@ -64,42 +67,52 @@ func NewDriver(name string, driverType string, v ...interface{}) *Driver {
|
|||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adaptor returns driver adaptor
|
||||||
func (d *Driver) Adaptor() AdaptorInterface {
|
func (d *Driver) Adaptor() AdaptorInterface {
|
||||||
return d.adaptor
|
return d.adaptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetInterval defines driver interval duration.
|
||||||
func (d *Driver) SetInterval(t time.Duration) {
|
func (d *Driver) SetInterval(t time.Duration) {
|
||||||
d.interval = t
|
d.interval = t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Interval current driver interval duration
|
||||||
func (d *Driver) Interval() time.Duration {
|
func (d *Driver) Interval() time.Duration {
|
||||||
return d.interval
|
return d.interval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetName sets driver name.
|
||||||
func (d *Driver) SetName(s string) {
|
func (d *Driver) SetName(s string) {
|
||||||
d.name = s
|
d.name = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns driver name.
|
||||||
func (d *Driver) Name() string {
|
func (d *Driver) Name() string {
|
||||||
return d.name
|
return d.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pin returns driver pin
|
||||||
func (d *Driver) Pin() string {
|
func (d *Driver) Pin() string {
|
||||||
return d.pin
|
return d.pin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPin defines driver pin
|
||||||
func (d *Driver) SetPin(pin string) {
|
func (d *Driver) SetPin(pin string) {
|
||||||
d.pin = pin
|
d.pin = pin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type returns driver type
|
||||||
func (d *Driver) Type() string {
|
func (d *Driver) Type() string {
|
||||||
return d.driverType
|
return d.driverType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Events returns driver events map
|
||||||
func (d *Driver) Events() map[string]*Event {
|
func (d *Driver) Events() map[string]*Event {
|
||||||
return d.events
|
return d.events
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Event returns an event by name if exists
|
||||||
func (d *Driver) Event(name string) *Event {
|
func (d *Driver) Event(name string) *Event {
|
||||||
e, ok := d.events[name]
|
e, ok := d.events[name]
|
||||||
if ok {
|
if ok {
|
||||||
@ -109,22 +122,27 @@ func (d *Driver) Event(name string) *Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddEvents adds a new event by name
|
||||||
func (d *Driver) AddEvent(name string) {
|
func (d *Driver) AddEvent(name string) {
|
||||||
d.events[name] = NewEvent()
|
d.events[name] = NewEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Command retrieves a command by name
|
||||||
func (d *Driver) Command(name string) func(map[string]interface{}) interface{} {
|
func (d *Driver) Command(name string) func(map[string]interface{}) interface{} {
|
||||||
return d.commands[name]
|
return d.commands[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Commands returns a map of driver commands
|
||||||
func (d *Driver) Commands() map[string]func(map[string]interface{}) interface{} {
|
func (d *Driver) Commands() map[string]func(map[string]interface{}) interface{} {
|
||||||
return d.commands
|
return d.commands
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddCommand links specified command name to `f`
|
||||||
func (d *Driver) AddCommand(name string, f func(map[string]interface{}) interface{}) {
|
func (d *Driver) AddCommand(name string, f func(map[string]interface{}) interface{}) {
|
||||||
d.commands[name] = f
|
d.commands[name] = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToJSON returns JSON Driver represnentation including adaptor and commands
|
||||||
func (d *Driver) ToJSON() *JSONDevice {
|
func (d *Driver) ToJSON() *JSONDevice {
|
||||||
jsonDevice := &JSONDevice{
|
jsonDevice := &JSONDevice{
|
||||||
Name: d.Name(),
|
Name: d.Name(),
|
||||||
|
5
event.go
5
event.go
@ -10,6 +10,8 @@ type Event struct {
|
|||||||
Callbacks []callback
|
Callbacks []callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEvent generates a new event by making a channel
|
||||||
|
// and start reading from it
|
||||||
func NewEvent() *Event {
|
func NewEvent() *Event {
|
||||||
e := &Event{
|
e := &Event{
|
||||||
Chan: make(chan interface{}, 1),
|
Chan: make(chan interface{}, 1),
|
||||||
@ -23,6 +25,7 @@ func NewEvent() *Event {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes sends event data to channel
|
||||||
func (e *Event) Write(data interface{}) {
|
func (e *Event) Write(data interface{}) {
|
||||||
select {
|
select {
|
||||||
case e.Chan <- data:
|
case e.Chan <- data:
|
||||||
@ -30,6 +33,8 @@ func (e *Event) Write(data interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read waits data from channel and execute callbacks
|
||||||
|
// for each event when received
|
||||||
func (e *Event) Read() {
|
func (e *Event) Read() {
|
||||||
for s := range e.Chan {
|
for s := range e.Chan {
|
||||||
tmp := []callback{}
|
tmp := []callback{}
|
||||||
|
13
utils.go
13
utils.go
@ -10,13 +10,10 @@ import (
|
|||||||
// Every triggers f every `t` time until the end of days.
|
// Every triggers f every `t` time until the end of days.
|
||||||
func Every(t time.Duration, f func()) {
|
func Every(t time.Duration, f func()) {
|
||||||
c := time.Tick(t)
|
c := time.Tick(t)
|
||||||
// start a go routine to not bloc the function
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
// wait for the ticker to tell us to run
|
|
||||||
<-c
|
<-c
|
||||||
// run the passed function in another go routine
|
|
||||||
// so we don't slow down the loop.
|
|
||||||
go f()
|
go f()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -27,27 +24,35 @@ func After(t time.Duration, f func()) {
|
|||||||
time.AfterFunc(t, f)
|
time.AfterFunc(t, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Publish emits an event by writting value
|
||||||
func Publish(e *Event, val interface{}) {
|
func Publish(e *Event, val interface{}) {
|
||||||
e.Write(val)
|
e.Write(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On adds `f` to callbacks that are executed on specified event
|
||||||
func On(e *Event, f func(s interface{})) {
|
func On(e *Event, f func(s interface{})) {
|
||||||
e.Callbacks = append(e.Callbacks, callback{f, false})
|
e.Callbacks = append(e.Callbacks, callback{f, false})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Once adds `f` to callbacks that are executed on specified event
|
||||||
|
// and sets flag to be called only once
|
||||||
func Once(e *Event, f func(s interface{})) {
|
func Once(e *Event, f func(s interface{})) {
|
||||||
e.Callbacks = append(e.Callbacks, callback{f, true})
|
e.Callbacks = append(e.Callbacks, callback{f, true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rand generates random int lower than max
|
||||||
func Rand(max int) int {
|
func Rand(max int) int {
|
||||||
i, _ := rand.Int(rand.Reader, big.NewInt(int64(max)))
|
i, _ := rand.Int(rand.Reader, big.NewInt(int64(max)))
|
||||||
return int(i.Int64())
|
return int(i.Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FromScale creates a scale using min and max values
|
||||||
|
// to be used in combination with ToScale
|
||||||
func FromScale(input, min, max float64) float64 {
|
func FromScale(input, min, max float64) float64 {
|
||||||
return (input - math.Min(min, max)) / (math.Max(min, max) - math.Min(min, max))
|
return (input - math.Min(min, max)) / (math.Max(min, max) - math.Min(min, max))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToScale is used with FromScale to return input converted to new scale
|
||||||
func ToScale(input, min, max float64) float64 {
|
func ToScale(input, min, max float64) float64 {
|
||||||
i := input*(math.Max(min, max)-math.Min(min, max)) + math.Min(min, max)
|
i := input*(math.Max(min, max)-math.Min(min, max)) + math.Min(min, max)
|
||||||
if i < math.Min(min, max) {
|
if i < math.Min(min, max) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user