diff --git a/adaptor.go b/adaptor.go index c2a7b0b5..7781ce00 100644 --- a/adaptor.go +++ b/adaptor.go @@ -74,7 +74,6 @@ func (a *Adaptor) SetConnected(b bool) { func (a *Adaptor) ToJSON() *JSONConnection { return &JSONConnection{ Name: a.Name(), - Port: a.Port(), Adaptor: a.Type(), } } diff --git a/api/api.go b/api/api.go index 0dc5b0d8..32991968 100644 --- a/api/api.go +++ b/api/api.go @@ -100,28 +100,32 @@ func (a *api) SetDebug() { // start starts the api using the start function // sets on the API on initialization. func (a *api) Start() { - mcpCommandRoute := "/commands/:command" - deviceCommandRoute := "/robots/:robot/devices/:device/commands/:command" - robotCommandRoute := "/robots/:robot/commands/:command" - // api - a.Get("/", a.mcp) - a.Get("/commands", a.mcpCommands) + mcpCommandRoute := "/api/commands/:command" + deviceCommandRoute := "/api/robots/:robot/devices/:device/commands/:command" + robotCommandRoute := "/api/robots/:robot/commands/:command" + + a.Get("/api/commands", a.mcpCommands) a.Get(mcpCommandRoute, a.executeMcpCommand) a.Post(mcpCommandRoute, a.executeMcpCommand) - a.Get("/robots", a.robots) - a.Get("/robots/:robot", a.robot) - a.Get("/robots/:robot/commands", a.robotCommands) + a.Get("/api/robots", a.robots) + a.Get("/api/robots/:robot", a.robot) + a.Get("/api/robots/:robot/commands", a.robotCommands) a.Get(robotCommandRoute, a.executeRobotCommand) a.Post(robotCommandRoute, a.executeRobotCommand) - a.Get("/robots/:robot/devices", a.robotDevices) - a.Get("/robots/:robot/devices/:device", a.robotDevice) - a.Get("/robots/:robot/devices/:device/commands", a.robotDeviceCommands) + a.Get("/api/robots/:robot/devices", a.robotDevices) + a.Get("/api/robots/:robot/devices/:device", a.robotDevice) + a.Get("/api/robots/:robot/devices/:device/commands", a.robotDeviceCommands) a.Get(deviceCommandRoute, a.executeDeviceCommand) a.Post(deviceCommandRoute, a.executeDeviceCommand) - a.Get("/robots/:robot/connections", a.robotConnections) - a.Get("/robots/:robot/connections/:connection", a.robotConnection) + a.Get("/api/robots/:robot/connections", a.robotConnections) + a.Get("/api/robots/:robot/connections/:connection", a.robotConnection) + a.Get("/api/", a.mcp) + // robeaux + a.Get("/", func(res http.ResponseWriter, req *http.Request) { + http.Redirect(res, req, "/index.html", http.StatusMovedPermanently) + }) a.Get("/index.html", a.robeaux) a.Get("/images/:a", a.robeaux) a.Get("/js/:a", a.robeaux) @@ -152,11 +156,11 @@ func (a *api) robeaux(res http.ResponseWriter, req *http.Request) { } func (a *api) mcp(res http.ResponseWriter, req *http.Request) { - a.writeJSON(a.gobot.ToJSON(), res) + a.writeJSON(map[string]interface{}{"MCP": a.gobot.ToJSON()}, res) } func (a *api) mcpCommands(res http.ResponseWriter, req *http.Request) { - a.writeJSON(a.gobot.ToJSON().Commands, res) + a.writeJSON(map[string]interface{}{"commands": a.gobot.ToJSON().Commands}, res) } func (a *api) robots(res http.ResponseWriter, req *http.Request) { @@ -164,15 +168,15 @@ func (a *api) robots(res http.ResponseWriter, req *http.Request) { a.gobot.Robots().Each(func(r *gobot.Robot) { jsonRobots = append(jsonRobots, r.ToJSON()) }) - a.writeJSON(jsonRobots, res) + a.writeJSON(map[string]interface{}{"robots": jsonRobots}, res) } func (a *api) robot(res http.ResponseWriter, req *http.Request) { - a.writeJSON(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) } func (a *api) robotCommands(res http.ResponseWriter, req *http.Request) { - a.writeJSON(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) } func (a *api) robotDevices(res http.ResponseWriter, req *http.Request) { @@ -180,20 +184,20 @@ func (a *api) robotDevices(res http.ResponseWriter, req *http.Request) { a.gobot.Robot(req.URL.Query().Get(":robot")).Devices().Each(func(d gobot.Device) { jsonDevices = append(jsonDevices, d.ToJSON()) }) - a.writeJSON(jsonDevices, res) + a.writeJSON(map[string]interface{}{"devices": jsonDevices}, res) } func (a *api) robotDevice(res http.ResponseWriter, req *http.Request) { a.writeJSON( - a.gobot.Robot(req.URL.Query().Get(":robot")). - Device(req.URL.Query().Get(":device")).ToJSON(), res, + map[string]interface{}{"device": a.gobot.Robot(req.URL.Query().Get(":robot")). + Device(req.URL.Query().Get(":device")).ToJSON()}, res, ) } func (a *api) robotDeviceCommands(res http.ResponseWriter, req *http.Request) { a.writeJSON( - a.gobot.Robot(req.URL.Query().Get(":robot")). - Device(req.URL.Query().Get(":device")).ToJSON().Commands, res, + map[string]interface{}{"commands": a.gobot.Robot(req.URL.Query().Get(":robot")). + Device(req.URL.Query().Get(":device")).ToJSON().Commands}, res, ) } @@ -202,13 +206,13 @@ func (a *api) robotConnections(res http.ResponseWriter, req *http.Request) { a.gobot.Robot(req.URL.Query().Get(":robot")).Connections().Each(func(c gobot.Connection) { jsonConnections = append(jsonConnections, c.ToJSON()) }) - a.writeJSON(jsonConnections, res) + a.writeJSON(map[string]interface{}{"connections": jsonConnections}, res) } func (a *api) robotConnection(res http.ResponseWriter, req *http.Request) { a.writeJSON( - a.gobot.Robot(req.URL.Query().Get(":robot")). - Connection(req.URL.Query().Get(":connection")).ToJSON(), + map[string]interface{}{"connection": a.gobot.Robot(req.URL.Query().Get(":robot")). + Connection(req.URL.Query().Get(":connection")).ToJSON()}, res, ) } @@ -248,7 +252,7 @@ func (a *api) executeCommand(f func(map[string]interface{}) interface{}, json.NewDecoder(req.Body).Decode(&body) if f != nil { - a.writeJSON(f(body), res) + a.writeJSON(map[string]interface{}{"result": f(body)}, res) } else { a.writeJSON("Unknown Command", res) } diff --git a/api/api_test.go b/api/api_test.go index c48b5d44..148f63c6 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -35,13 +35,13 @@ func TestBasicAuth(t *testing.T) { a.SetBasicAuth("admin", "password") - request, _ := http.NewRequest("GET", "/", nil) + request, _ := http.NewRequest("GET", "/api/", nil) request.SetBasicAuth("admin", "password") response := httptest.NewRecorder() a.ServeHTTP(response, request) gobot.Assert(t, response.Code, 200) - request, _ = http.NewRequest("GET", "/", nil) + request, _ = http.NewRequest("GET", "/api/", nil) request.SetBasicAuth("admin", "wrongPassword") response = httptest.NewRecorder() a.ServeHTTP(response, request) @@ -74,24 +74,25 @@ func TestRobeaux(t *testing.T) { func TestMcp(t *testing.T) { a := initTestAPI() - request, _ := http.NewRequest("GET", "/", nil) + request, _ := http.NewRequest("GET", "/api/", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, len(body), 2) + gobot.Refute(t, body["MCP"].(map[string]interface{})["robots"], nil) + gobot.Refute(t, body["MCP"].(map[string]interface{})["commands"], nil) } func TestMcpCommands(t *testing.T) { a := initTestAPI() - request, _ := http.NewRequest("GET", "/commands", nil) + request, _ := http.NewRequest("GET", "/api/commands", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) - var body []string + var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body, []string{"TestFunction"}) + gobot.Assert(t, body["commands"], []interface{}{"TestFunction"}) } func TestExecuteMcpCommand(t *testing.T) { @@ -100,7 +101,7 @@ func TestExecuteMcpCommand(t *testing.T) { // known command request, _ := http.NewRequest("GET", - "/commands/TestFunction", + "/api/commands/TestFunction", bytes.NewBufferString(`{"message":"Beep Boop"}`), ) request.Header.Add("Content-Type", "application/json") @@ -108,11 +109,11 @@ func TestExecuteMcpCommand(t *testing.T) { a.ServeHTTP(response, request) json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body, "hey Beep Boop") + gobot.Assert(t, body.(map[string]interface{})["result"], "hey Beep Boop") // unknown command request, _ = http.NewRequest("GET", - "/commands/TestFuntion1", + "/api/commands/TestFuntion1", bytes.NewBufferString(`{"message":"Beep Boop"}`), ) request.Header.Add("Content-Type", "application/json") @@ -125,46 +126,46 @@ func TestExecuteMcpCommand(t *testing.T) { func TestRobots(t *testing.T) { a := initTestAPI() - request, _ := http.NewRequest("GET", "/robots", nil) - response := httptest.NewRecorder() - a.ServeHTTP(response, request) - - var body []map[string]interface{} - json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, len(body), 3) -} - -func TestRobot(t *testing.T) { - a := initTestAPI() - request, _ := http.NewRequest("GET", "/robots/Robot1", nil) + request, _ := http.NewRequest("GET", "/api/robots", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body["name"].(string), "Robot1") + gobot.Assert(t, len(body["robots"].([]interface{})), 3) +} + +func TestRobot(t *testing.T) { + a := initTestAPI() + request, _ := http.NewRequest("GET", "/api/robots/Robot1", nil) + response := httptest.NewRecorder() + a.ServeHTTP(response, request) + + var body map[string]interface{} + json.NewDecoder(response.Body).Decode(&body) + gobot.Assert(t, body["robot"].(map[string]interface{})["name"].(string), "Robot1") } func TestRobotDevices(t *testing.T) { a := initTestAPI() - request, _ := http.NewRequest("GET", "/robots/Robot1/devices", nil) + request, _ := http.NewRequest("GET", "/api/robots/Robot1/devices", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) - var body []map[string]interface{} + var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, len(body), 3) + gobot.Assert(t, len(body["devices"].([]interface{})), 3) } func TestRobotCommands(t *testing.T) { a := initTestAPI() - request, _ := http.NewRequest("GET", "/robots/Robot1/commands", nil) + request, _ := http.NewRequest("GET", "/api/robots/Robot1/commands", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) - var body []string + var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body, []string{"robotTestFunction"}) + gobot.Assert(t, body["commands"], []interface{}{"robotTestFunction"}) } func TestExecuteRobotCommand(t *testing.T) { @@ -172,7 +173,7 @@ func TestExecuteRobotCommand(t *testing.T) { a := initTestAPI() // known command request, _ := http.NewRequest("GET", - "/robots/Robot1/commands/robotTestFunction", + "/api/robots/Robot1/commands/robotTestFunction", bytes.NewBufferString(`{"message":"Beep Boop", "robot":"Robot1"}`), ) request.Header.Add("Content-Type", "application/json") @@ -180,11 +181,11 @@ func TestExecuteRobotCommand(t *testing.T) { a.ServeHTTP(response, request) json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body, "hey Robot1, Beep Boop") + gobot.Assert(t, body.(map[string]interface{})["result"], "hey Robot1, Beep Boop") // unknown command request, _ = http.NewRequest("GET", - "/robots/Robot1/commands/robotTestFuntion1", + "/api/robots/Robot1/commands/robotTestFuntion1", bytes.NewBufferString(`{"message":"Beep Boop"}`), ) request.Header.Add("Content-Type", "application/json") @@ -198,7 +199,7 @@ func TestExecuteRobotCommand(t *testing.T) { func TestRobotDevice(t *testing.T) { a := initTestAPI() request, _ := http.NewRequest("GET", - "/robots/Robot1/devices/Device1", + "/api/robots/Robot1/devices/Device1", nil, ) response := httptest.NewRecorder() @@ -206,21 +207,21 @@ func TestRobotDevice(t *testing.T) { var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body["name"].(string), "Device1") + gobot.Assert(t, body["device"].(map[string]interface{})["name"].(string), "Device1") } func TestRobotDeviceCommands(t *testing.T) { a := initTestAPI() request, _ := http.NewRequest("GET", - "/robots/Robot1/devices/Device1/commands", + "/api/robots/Robot1/devices/Device1/commands", nil, ) response := httptest.NewRecorder() a.ServeHTTP(response, request) - var body []string + var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, len(body), 2) + gobot.Assert(t, len(body["commands"].([]interface{})), 2) } func TestExecuteRobotDeviceCommand(t *testing.T) { @@ -229,7 +230,7 @@ func TestExecuteRobotDeviceCommand(t *testing.T) { // known command request, _ := http.NewRequest("GET", - "/robots/Robot1/devices/Device1/commands/TestDriverCommand", + "/api/robots/Robot1/devices/Device1/commands/TestDriverCommand", bytes.NewBufferString(`{"name":"human"}`), ) request.Header.Add("Content-Type", "application/json") @@ -237,11 +238,11 @@ func TestExecuteRobotDeviceCommand(t *testing.T) { a.ServeHTTP(response, request) json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body, "hello human") + gobot.Assert(t, body.(map[string]interface{})["result"].(string), "hello human") // unknown command request, _ = http.NewRequest("GET", - "/robots/Robot1/devices/Device1/commands/DriverCommand1", + "/api/robots/Robot1/devices/Device1/commands/DriverCommand1", bytes.NewBufferString(`{"name":"human"}`), ) request.Header.Add("Content-Type", "application/json") @@ -254,19 +255,19 @@ func TestExecuteRobotDeviceCommand(t *testing.T) { func TestRobotConnections(t *testing.T) { a := initTestAPI() - request, _ := http.NewRequest("GET", "/robots/Robot1/connections", nil) + request, _ := http.NewRequest("GET", "/api/robots/Robot1/connections", nil) response := httptest.NewRecorder() a.ServeHTTP(response, request) - var body []map[string]interface{} + var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, len(body), 3) + gobot.Assert(t, len(body["connections"].([]interface{})), 3) } func TestRobotConnection(t *testing.T) { a := initTestAPI() request, _ := http.NewRequest("GET", - "/robots/Robot1/connections/Connection1", + "/api/robots/Robot1/connections/Connection1", nil, ) response := httptest.NewRecorder() @@ -274,7 +275,7 @@ func TestRobotConnection(t *testing.T) { var body map[string]interface{} json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body["name"].(string), "Connection1") + gobot.Assert(t, body["connection"].(map[string]interface{})["name"].(string), "Connection1") } func TestAPIRouter(t *testing.T) { diff --git a/connection.go b/connection.go index eba6ecda..49d4df3c 100644 --- a/connection.go +++ b/connection.go @@ -7,7 +7,6 @@ import ( type JSONConnection struct { Name string `json:"name"` - Port string `json:"port"` Adaptor string `json:"adaptor"` } diff --git a/device.go b/device.go index ee76c36d..febfa2df 100644 --- a/device.go +++ b/device.go @@ -6,10 +6,10 @@ import ( ) type JSONDevice struct { - Name string `json:"name"` - Driver string `json:"driver"` - Connection *JSONConnection `json:"connection"` - Commands []string `json:"commands"` + Name string `json:"name"` + Driver string `json:"driver"` + Connection string `json:"connection"` + Commands []string `json:"commands"` } type Device DriverInterface diff --git a/driver.go b/driver.go index 96875a75..6eda0702 100644 --- a/driver.go +++ b/driver.go @@ -130,11 +130,11 @@ func (d *Driver) ToJSON() *JSONDevice { Name: d.Name(), Driver: d.Type(), Commands: []string{}, - Connection: nil, + Connection: "", } if d.Adaptor() != nil { - jsonDevice.Connection = d.Adaptor().ToJSON() + jsonDevice.Connection = d.Adaptor().ToJSON().Name } for command := range d.Commands() { diff --git a/examples/batty.go b/examples/batty.go new file mode 100644 index 00000000..f335ab02 --- /dev/null +++ b/examples/batty.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + + "github.com/hybridgroup/gobot" + "github.com/hybridgroup/gobot/api" +) + +func main() { + gbot := gobot.NewGobot() + + api.NewAPI(gbot).Start() + + gbot.AddCommand("echo", func(params map[string]interface{}) interface{} { + return params["a"] + }) + + loopback := gobot.NewLoopbackAdaptor("loopback") + ping := gobot.NewPingDriver(loopback, "ping") + r := gobot.NewRobot("TestBot", + []gobot.Connection{loopback}, + []gobot.Device{ping}, + ) + + r.AddCommand("hello", func(params map[string]interface{}) interface{} { + return fmt.Sprintf("Hello, %v!", params["greeting"]) + }) + + gbot.AddRobot(r) + gbot.Start() +} diff --git a/robot.go b/robot.go index 2c1f994f..12288804 100644 --- a/robot.go +++ b/robot.go @@ -159,7 +159,7 @@ func (r *Robot) ToJSON() *JSONRobot { r.Devices().Each(func(device Device) { jsonDevice := device.ToJSON() - jsonRobot.Connections = append(jsonRobot.Connections, jsonDevice.Connection) + jsonRobot.Connections = append(jsonRobot.Connections, r.Connection(jsonDevice.Connection).ToJSON()) jsonRobot.Devices = append(jsonRobot.Devices, jsonDevice) }) return jsonRobot diff --git a/test_helper.go b/test_helper.go index 0d56c9c0..69668491 100644 --- a/test_helper.go +++ b/test_helper.go @@ -127,3 +127,42 @@ func NewTestRobot(name string) *Robot { }) return r } + +type loopbackAdaptor struct { + Adaptor +} + +func (t *loopbackAdaptor) Finalize() bool { return true } +func (t *loopbackAdaptor) Connect() bool { return true } + +func NewLoopbackAdaptor(name string) *loopbackAdaptor { + return &loopbackAdaptor{ + Adaptor: *NewAdaptor( + name, + "Loopback", + ), + } +} + +type pingDriver struct { + Driver +} + +func (t *pingDriver) Start() bool { return true } +func (t *pingDriver) Halt() bool { return true } + +func NewPingDriver(adaptor *loopbackAdaptor, name string) *pingDriver { + t := &pingDriver{ + Driver: *NewDriver( + name, + "Ping", + adaptor, + ), + } + + t.AddCommand("ping", func(params map[string]interface{}) interface{} { + return fmt.Sprintf("pong") + }) + + return t +}