Skip to content

Commit 26ee6b2

Browse files
committed
created an initial golang rosbridge client
1 parent 14b0fb5 commit 26ee6b2

File tree

4 files changed

+168
-0
lines changed

4 files changed

+168
-0
lines changed

example/main.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package main
2+
3+
import (
4+
"log"
5+
6+
"github.com/brychanrobot/goros"
7+
)
8+
9+
func main() {
10+
ros := goros.NewRos("ws://192.168.27.20:9090")
11+
12+
topics := ros.GetTopics()
13+
log.Println(topics)
14+
15+
select {} //keeps the application open
16+
}

ros.go

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package goros
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"log"
8+
"regexp"
9+
"strings"
10+
"sync"
11+
12+
"golang.org/x/net/websocket"
13+
)
14+
15+
var (
16+
messageCount = 0
17+
)
18+
19+
type Ros struct {
20+
origin string
21+
url string
22+
ws *websocket.Conn
23+
receivedMapMutex sync.Mutex
24+
receivedMap map[string]chan interface{}
25+
}
26+
27+
func NewRos(url string) *Ros {
28+
ros := Ros{url: url, origin: "https://localhost"}
29+
ros.receivedMap = make(map[string]chan interface{})
30+
ros.connect()
31+
go ros.handleIncoming()
32+
return &ros
33+
}
34+
35+
func (ros *Ros) connect() {
36+
ws, err := websocket.Dial(ros.url, "", ros.origin)
37+
if err != nil {
38+
log.Fatal(err)
39+
}
40+
41+
ros.ws = ws
42+
}
43+
44+
func (ros *Ros) getServiceResponse(service *ServiceCall) *ServiceResponse {
45+
response := make(chan interface{})
46+
ros.receivedMapMutex.Lock()
47+
ros.receivedMap[service.Id] = response
48+
ros.receivedMapMutex.Unlock()
49+
err := websocket.JSON.Send(ros.ws, service)
50+
if err != nil {
51+
fmt.Println("Couldn't send msg")
52+
}
53+
54+
serviceResponse := <-response
55+
return serviceResponse.(*ServiceResponse)
56+
}
57+
58+
func (ros *Ros) returnToAppropriateChannel(id string, data interface{}) {
59+
ros.receivedMapMutex.Lock()
60+
ros.receivedMap[id] <- data
61+
ros.receivedMapMutex.Unlock()
62+
}
63+
64+
func (ros *Ros) handleIncoming() {
65+
var msg []byte
66+
for {
67+
err := websocket.Message.Receive(ros.ws, &msg)
68+
if err != nil {
69+
if err == io.EOF {
70+
break
71+
}
72+
fmt.Println("Couldn't receive msg " + err.Error())
73+
break
74+
}
75+
76+
opRegex, err := regexp.Compile(`"op"\s*:\s*"[[:alpha:],_]*`)
77+
if err != nil {
78+
log.Println(err)
79+
}
80+
opString := opRegex.FindString(string(msg))
81+
splitOpString := strings.Split(opString, "\"")
82+
operation := splitOpString[len(splitOpString)-1]
83+
84+
//log.Println(operation)
85+
86+
/*
87+
var data map[string]interface{}
88+
jsonErr := json.Unmarshal(msg, &data)
89+
//fmt.Printf("Received from server: %s\n", data)
90+
if jsonErr != nil {
91+
panic(jsonErr)
92+
}
93+
94+
ros.receivedMapMutex.Lock()
95+
ros.receivedMap[data["id"].(string)] <- data
96+
ros.receivedMapMutex.Unlock()
97+
*/
98+
if operation == "service_response" {
99+
var serviceResponse ServiceResponse
100+
json.Unmarshal(msg, &serviceResponse)
101+
ros.receivedMapMutex.Lock()
102+
ros.receivedMap[serviceResponse.Id] <- &serviceResponse
103+
ros.receivedMapMutex.Unlock()
104+
}
105+
}
106+
}
107+
108+
func (ros *Ros) GetTopics() []string {
109+
response := ros.getServiceResponse(newServiceCall("/rosapi/topics"))
110+
var topics []string
111+
json.Unmarshal(response.Values["topics"], &topics)
112+
return topics
113+
}
114+
115+
func (ros *Ros) Subscribe(topic *Topic) {
116+
117+
}

service.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package goros
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
)
7+
8+
type ServiceCall struct {
9+
Op string `json:"op"`
10+
Id string `json:"id"`
11+
Service string `json:"service"`
12+
Args string `json:"args,omitempty"`
13+
}
14+
15+
func newServiceCall(service string) *ServiceCall {
16+
serviceCall := &ServiceCall{Op: "call_service", Service: service}
17+
serviceCall.Id = fmt.Sprintf("%s:%s:%d", serviceCall.Op, serviceCall.Service, messageCount)
18+
messageCount++
19+
20+
return serviceCall
21+
}
22+
23+
type ServiceResponse struct {
24+
Op string `json:"op"`
25+
Id string `json:"id"`
26+
Service string `json:"service"`
27+
Result bool `json:"result"`
28+
Values map[string]json.RawMessage `json:"values"`
29+
}

topic.go

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package goros
2+
3+
type Topic struct {
4+
Op string
5+
Id string
6+
}

0 commit comments

Comments
 (0)