Skip to content

Commit 75c5aba

Browse files
committed
Added generic RPC client (replaced example)
1 parent 8cffcb8 commit 75c5aba

File tree

9 files changed

+327
-156
lines changed

9 files changed

+327
-156
lines changed

.licenses/arduino-router/NOTICE

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
THIRD PARTY NOTICES
22

33
*****
4-
github.com/creack/goselect@v0.1.2
4+
github.com/creack/goselect@v0.1.3
55

66
The MIT License (MIT)
77

@@ -308,7 +308,7 @@ Apache License
308308
Cobra is released under the Apache 2.0 license. See [LICENSE.txt](LICENSE.txt)
309309

310310
*****
311-
github.com/spf13/pflag@v1.0.9
311+
github.com/spf13/pflag@v1.0.10
312312

313313
Copyright (c) 2012 Alex Ogier. All rights reserved.
314314
Copyright (c) 2012 The Go Authors. All rights reserved.
@@ -604,7 +604,7 @@ This software is released under the [BSD 3-clause license].
604604
[BSD 3-clause license]: https://github.com/bugst/go-serial/blob/master/LICENSE
605605

606606
*****
607-
golang.org/x/sys/unix@v0.37.0
607+
golang.org/x/sys/unix@v0.38.0
608608

609609
Copyright 2009 The Go Authors.
610610

.licenses/arduino-router/go/github.com/creack/goselect.dep.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
22
name: github.com/creack/goselect
3-
version: v0.1.2
3+
version: v0.1.3
44
type: go
5-
summary:
5+
summary:
66
homepage: https://pkg.go.dev/github.com/creack/goselect
77
license: mit
88
licenses:
@@ -33,4 +33,3 @@ licenses:
3333
- sources: README.md
3434
text: Released under the [MIT license](LICENSE).
3535
notices: []
36-
...

.licenses/arduino-router/go/github.com/spf13/pflag.dep.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: github.com/spf13/pflag
3-
version: v1.0.9
3+
version: v1.0.10
44
type: go
55
summary: Package pflag is a drop-in replacement for Go's flag package, implementing
66
POSIX/GNU-style --flags.

.licenses/arduino-router/go/golang.org/x/sys/unix.dep.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
---
22
name: golang.org/x/sys/unix
3-
version: v0.37.0
3+
version: v0.38.0
44
type: go
55
summary: Package unix contains an interface to the low-level operating system primitives.
66
homepage: https://pkg.go.dev/golang.org/x/sys/unix
77
license: bsd-3-clause
88
licenses:
9-
- sources: sys@v0.37.0/LICENSE
9+
- sources: sys@v0.38.0/LICENSE
1010
text: |
1111
Copyright 2009 The Go Authors.
1212
@@ -35,7 +35,7 @@ licenses:
3535
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3636
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3737
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38-
- sources: sys@v0.37.0/PATENTS
38+
- sources: sys@v0.38.0/PATENTS
3939
text: |
4040
Additional IP Rights Grant (Patents)
4141

cmd/arduino-router-client/main.go

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
// This file is part of arduino-router
2+
//
3+
// Copyright 2025 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-router
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to license@arduino.cc.
15+
16+
package main
17+
18+
import (
19+
"context"
20+
"fmt"
21+
"net"
22+
"os"
23+
"strconv"
24+
"strings"
25+
26+
"github.com/arduino/arduino-router/msgpackrpc"
27+
28+
"github.com/spf13/cobra"
29+
"gopkg.in/yaml.v3"
30+
)
31+
32+
func main() {
33+
var notification bool
34+
var server string
35+
appname := os.Args[0]
36+
cmd := cobra.Command{
37+
Short: "Send a MsgPack RPC REQUEST or NOTIFICATION.",
38+
Use: appname + " [flags] <METHOD> [<ARG> [<ARG> ...]]\n\n" +
39+
"Send REQUEST: " + appname + " [-s server_addr] <METHOD> [<ARG> [<ARG> ...]]\n" +
40+
"Send NOTIFICATION: " + appname + " [-s server_addr] -n <METHOD> [<ARG> [<ARG> ...]]\n\n" +
41+
" <METHOD> is the method name to request/notify,\n" +
42+
" <ARG> are the arguments to pass to the method:\n" +
43+
" - Use 'true', 'false' for boolean\n" +
44+
" - Use 'null' for null.\n" +
45+
" - Use integer values directly (e.g., 42).\n" +
46+
" - Use the 'f32:' or 'f64:' prefix for floating point values (e.g. f32:3.14159).\n" +
47+
" - Use '[' and ']' to start and end an array.\n" +
48+
" - Use '{' and '}' to start and end a map.\n" +
49+
" Keys and values should be listed in order { KEY1 VAL1 KEY2 VAL2 }.\n" +
50+
" - Any other value is treated as a string, or you may use the 'str:' prefix\n" +
51+
" explicitly in case of ambiguity (e.g. str:42)",
52+
Run: func(cmd *cobra.Command, cliArgs []string) {
53+
// Compose method and arguments
54+
args, rest, err := composeArgs(append(append([]string{"["}, cliArgs[1:]...), "]"))
55+
if err != nil {
56+
fmt.Println("Invalid arguments:", err)
57+
os.Exit(1)
58+
}
59+
if len(rest) > 0 {
60+
fmt.Println("Invalid arguments: extra data:", rest)
61+
os.Exit(1)
62+
}
63+
if _, ok := args.([]any); !ok {
64+
fmt.Println("Invalid arguments: expected array")
65+
os.Exit(1)
66+
}
67+
68+
// Perfom request send
69+
ctx := cmd.Context()
70+
method := cliArgs[0]
71+
rpcResp, rpcErr, err := send(ctx, server, method, args.([]any), notification)
72+
if err != nil {
73+
fmt.Println("Error sending request:", err)
74+
os.Exit(1)
75+
}
76+
77+
yamlEncoder := yaml.NewEncoder(os.Stdout)
78+
yamlEncoder.SetIndent(2)
79+
if notification {
80+
fmt.Printf("Sending notification for method '%s', with parameters:\n", method)
81+
} else {
82+
fmt.Printf("Sending request for method '%s', with parameters:\n", method)
83+
}
84+
_ = yamlEncoder.Encode(args)
85+
if !notification {
86+
if rpcErr != nil {
87+
fmt.Println("Got RPC error response:")
88+
_ = yamlEncoder.Encode(rpcErr)
89+
}
90+
if rpcResp != nil {
91+
fmt.Println("Got RPC response:")
92+
_ = yamlEncoder.Encode(rpcResp)
93+
}
94+
}
95+
},
96+
Args: cobra.MinimumNArgs(1),
97+
SilenceUsage: true,
98+
}
99+
cmd.Flags().BoolVarP(
100+
&notification, "notification", "n", false,
101+
"Send a NOTIFICATION instead of a CALL")
102+
cmd.Flags().StringVarP(
103+
&server, "server", "s", "/var/run/arduino-router.sock",
104+
"Server address (file path for unix socket)")
105+
if err := cmd.Execute(); err != nil {
106+
fmt.Printf("Use: %s -h for help.\n", appname)
107+
os.Exit(1)
108+
}
109+
}
110+
111+
func composeArgs(args []string) (any, []string, error) {
112+
if len(args) == 0 {
113+
return nil, nil, fmt.Errorf("no arguments provided")
114+
}
115+
if args[0] == "null" {
116+
return nil, args[1:], nil
117+
}
118+
if args[0] == "true" {
119+
return true, args[1:], nil
120+
}
121+
if args[0] == "false" {
122+
return false, args[1:], nil
123+
}
124+
if f32, ok := strings.CutPrefix(args[0], "f32:"); ok {
125+
f, err := strconv.ParseFloat(f32, 32)
126+
if err != nil {
127+
return nil, args, fmt.Errorf("invalid f32 value: %s", args[0])
128+
}
129+
return float32(f), args[1:], nil
130+
}
131+
if f64, ok := strings.CutPrefix(args[0], "f64:"); ok {
132+
f, err := strconv.ParseFloat(f64, 64)
133+
if err != nil {
134+
return nil, args, fmt.Errorf("invalid f64 value: %s", args[0])
135+
}
136+
return f, args[1:], nil
137+
}
138+
if str, ok := strings.CutPrefix(args[0], "str:"); ok {
139+
return str, args[1:], nil
140+
}
141+
if args[0] == "[" {
142+
arr := []any{}
143+
rest := args[1:]
144+
for {
145+
if len(rest) == 0 {
146+
return nil, args, fmt.Errorf("unterminated array")
147+
}
148+
if rest[0] == "]" {
149+
break
150+
}
151+
if elem, r, err := composeArgs(rest); err != nil {
152+
return nil, args, err
153+
} else {
154+
arr = append(arr, elem)
155+
rest = r
156+
}
157+
}
158+
return arr, rest[1:], nil
159+
}
160+
if args[0] == "{" {
161+
m := make(map[any]any)
162+
rest := args[1:]
163+
for {
164+
if len(rest) == 0 {
165+
return nil, args, fmt.Errorf("unterminated map")
166+
}
167+
if rest[0] == "}" {
168+
break
169+
}
170+
key, r, err := composeArgs(rest)
171+
if err != nil {
172+
return nil, args, fmt.Errorf("invalid map key: %w", err)
173+
}
174+
rest = r
175+
if len(rest) == 0 {
176+
return nil, args, fmt.Errorf("unterminated map (missing value)")
177+
}
178+
value, r, err := composeArgs(rest)
179+
if err != nil {
180+
return nil, args, fmt.Errorf("invalid map value: %w", err)
181+
}
182+
m[key] = value
183+
rest = r
184+
}
185+
return m, rest[1:], nil
186+
}
187+
// Autodetect int or string
188+
if i, err := strconv.Atoi(args[0]); err == nil {
189+
return i, args[1:], nil
190+
}
191+
return args[0], args[1:], nil
192+
}
193+
194+
func send(ctx context.Context, server string, method string, args []any, notification bool) (any, any, error) {
195+
netType := "unix"
196+
if strings.Contains(server, ":") {
197+
netType = "tcp"
198+
}
199+
c, err := net.Dial(netType, server)
200+
if err != nil {
201+
return nil, nil, fmt.Errorf("error connecting to server: %w", err)
202+
}
203+
204+
conn := msgpackrpc.NewConnection(c, c, nil, nil, nil)
205+
defer conn.Close()
206+
go conn.Run()
207+
208+
// Send notification...
209+
if notification {
210+
if err := conn.SendNotification(method, args...); err != nil {
211+
return nil, nil, fmt.Errorf("error sending notification: %w", err)
212+
}
213+
return nil, nil, nil
214+
}
215+
216+
// ...or send Request
217+
reqResult, reqError, err := conn.SendRequest(ctx, method, args...)
218+
if err != nil {
219+
return nil, nil, fmt.Errorf("error sending request: %w", err)
220+
}
221+
return reqResult, reqError, nil
222+
}

debian/arduino-router/usr/share/doc/arduino-router/copyright

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ To purchase a commercial license, send an email to license@arduino.cc.
1616
THIRD PARTY NOTICES
1717

1818
*****
19-
github.com/creack/goselect@v0.1.2
19+
github.com/creack/goselect@v0.1.3
2020

2121
The MIT License (MIT)
2222

@@ -323,7 +323,7 @@ Apache License
323323
Cobra is released under the Apache 2.0 license. See [LICENSE.txt](LICENSE.txt)
324324

325325
*****
326-
github.com/spf13/pflag@v1.0.9
326+
github.com/spf13/pflag@v1.0.10
327327

328328
Copyright (c) 2012 Alex Ogier. All rights reserved.
329329
Copyright (c) 2012 The Go Authors. All rights reserved.
@@ -619,7 +619,7 @@ This software is released under the [BSD 3-clause license].
619619
[BSD 3-clause license]: https://github.com/bugst/go-serial/blob/master/LICENSE
620620

621621
*****
622-
golang.org/x/sys/unix@v0.37.0
622+
golang.org/x/sys/unix@v0.38.0
623623

624624
Copyright 2009 The Go Authors.
625625

examples/generic_sock_client/main.go

Lines changed: 0 additions & 72 deletions
This file was deleted.

0 commit comments

Comments
 (0)