1
0
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:
Javier Cervantes 2014-10-15 12:57:07 -05:00
parent 6d2e25b0d8
commit ad96293edb
10 changed files with 141 additions and 16 deletions

View File

@ -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(),

View File

@ -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)

View File

@ -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)),

View File

@ -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
View 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

View File

@ -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()

View File

@ -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()

View File

@ -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(),

View File

@ -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{}

View File

@ -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) {