Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .licenses/arduino-router/NOTICE
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
THIRD PARTY NOTICES

*****
github.com/creack/goselect@v0.1.2
github.com/creack/goselect@v0.1.3

The MIT License (MIT)

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

*****
github.com/spf13/pflag@v1.0.9
github.com/spf13/pflag@v1.0.10

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

*****
golang.org/x/sys/unix@v0.37.0
golang.org/x/sys/unix@v0.38.0

Copyright 2009 The Go Authors.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
name: github.com/creack/goselect
version: v0.1.2
version: v0.1.3
type: go
summary:
summary:
homepage: https://pkg.go.dev/github.com/creack/goselect
license: mit
licenses:
Expand Down Expand Up @@ -33,4 +33,3 @@ licenses:
- sources: README.md
text: Released under the [MIT license](LICENSE).
notices: []
...
2 changes: 1 addition & 1 deletion .licenses/arduino-router/go/github.com/spf13/pflag.dep.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: github.com/spf13/pflag
version: v1.0.9
version: v1.0.10
type: go
summary: Package pflag is a drop-in replacement for Go's flag package, implementing
POSIX/GNU-style --flags.
Expand Down
6 changes: 3 additions & 3 deletions .licenses/arduino-router/go/golang.org/x/sys/unix.dep.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
name: golang.org/x/sys/unix
version: v0.37.0
version: v0.38.0
type: go
summary: Package unix contains an interface to the low-level operating system primitives.
homepage: https://pkg.go.dev/golang.org/x/sys/unix
license: bsd-3-clause
licenses:
- sources: sys@v0.37.0/LICENSE
- sources: sys@v0.38.0/LICENSE
text: |
Copyright 2009 The Go Authors.

Expand Down Expand Up @@ -35,7 +35,7 @@ licenses:
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- sources: sys@v0.37.0/PATENTS
- sources: sys@v0.38.0/PATENTS
text: |
Additional IP Rights Grant (Patents)

Expand Down
216 changes: 216 additions & 0 deletions cmd/arduino-router-client/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// This file is part of arduino-router
//
// Copyright 2025 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-router
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.

package main

import (
"context"
"fmt"
"net"
"os"
"strconv"
"strings"

"github.com/arduino/arduino-router/msgpackrpc"

"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
)

func main() {
var notification bool
var server string
appname := os.Args[0]
cmd := cobra.Command{
Short: "Send a MsgPack RPC REQUEST or NOTIFICATION.",
Use: appname + " [flags] <METHOD> [<ARG> [<ARG> ...]]\n\n" +
"Send REQUEST: " + appname + " [-s server_addr] <METHOD> [<ARG> [<ARG> ...]]\n" +
"Send NOTIFICATION: " + appname + " [-s server_addr] -n <METHOD> [<ARG> [<ARG> ...]]\n\n" +
" <METHOD> is the method name to request/notify,\n" +
" <ARG> are the arguments to pass to the method:\n" +
" - Use 'true', 'false' for boolean\n" +
" - Use 'null' for null.\n" +
" - Use integer values directly (e.g., 42).\n" +
" - Use the 'f32:' or 'f64:' prefix for floating point values (e.g. f32:3.14159).\n" +
" - Use '[' and ']' to start and end an array.\n" +
" - Use '{' and '}' to start and end a map.\n" +
" Keys and values should be listed in order { KEY1 VAL1 KEY2 VAL2 }.\n" +
" - Any other value is treated as a string, or you may use the 'str:' prefix\n" +
" explicitly in case of ambiguity (e.g. str:42)",
Run: func(cmd *cobra.Command, cliArgs []string) {
// Compose method and arguments
args, rest, err := composeArgs(append(append([]string{"["}, cliArgs[1:]...), "]"))
if err != nil {
fmt.Println("Invalid arguments:", err)
os.Exit(1)
}
if len(rest) > 0 {
fmt.Println("Invalid arguments: extra data:", rest)
os.Exit(1)
}
if _, ok := args.([]any); !ok {
fmt.Println("Invalid arguments: expected array")
os.Exit(1)
}

yamlEncoder := yaml.NewEncoder(os.Stdout)
yamlEncoder.SetIndent(2)
fmt.Println("Sending parameters:")
_ = yamlEncoder.Encode(args)

// Perfom request send
if rpcResp, rpcErr, err := send(server, cliArgs[0], args.([]any), notification); err != nil {
fmt.Println("Error sending request:", err)
os.Exit(1)
} else if !notification {
yamlEncoder := yaml.NewEncoder(os.Stdout)
yamlEncoder.SetIndent(2)
if rpcErr != nil {
fmt.Println("Got RPC error response:")
_ = yamlEncoder.Encode(rpcErr)
}
if rpcResp != nil {
fmt.Println("Got RPC response:")
_ = yamlEncoder.Encode(rpcResp)
}
}
},
Args: cobra.MinimumNArgs(1),
SilenceUsage: true,
}
cmd.Flags().BoolVarP(
&notification, "notification", "n", false,
"Send a NOTIFICATION instead of a CALL")
cmd.Flags().StringVarP(
&server, "server", "s", "/var/run/arduino-router.sock",
"Server address (file path for unix socket)")
if err := cmd.Execute(); err != nil {
fmt.Printf("Use: %s -h for help.\n", appname)
os.Exit(1)
}
}

func composeArgs(args []string) (any, []string, error) {
if len(args) == 0 {
return nil, nil, fmt.Errorf("no arguments provided")
}
if args[0] == "null" {
return nil, args[1:], nil
}
if args[0] == "true" {
return true, args[1:], nil
}
if args[0] == "false" {
return false, args[1:], nil
}
if f32, ok := strings.CutPrefix(args[0], "f32:"); ok {
f, err := strconv.ParseFloat(f32, 32)
if err != nil {
return nil, args, fmt.Errorf("invalid f32 value: %s", args[0])
}
return float32(f), args[1:], nil
}
if f64, ok := strings.CutPrefix(args[0], "f64:"); ok {
f, err := strconv.ParseFloat(f64, 64)
if err != nil {
return nil, args, fmt.Errorf("invalid f64 value: %s", args[0])
}
return f, args[1:], nil
}
if str, ok := strings.CutPrefix(args[0], "str:"); ok {
return str, args[1:], nil
}
if args[0] == "[" {
arr := []any{}
rest := args[1:]
for {
if len(rest) == 0 {
return nil, args, fmt.Errorf("unterminated array")
}
if rest[0] == "]" {
break
}
if elem, r, err := composeArgs(rest); err != nil {
return nil, args, err
} else {
arr = append(arr, elem)
rest = r
}
}
return arr, rest[1:], nil
}
if args[0] == "{" {
m := make(map[any]any)
rest := args[1:]
for {
if len(rest) == 0 {
return nil, args, fmt.Errorf("unterminated map")
}
if rest[0] == "}" {
break
}
key, r, err := composeArgs(rest)
if err != nil {
return nil, args, fmt.Errorf("invalid map key: %w", err)
}
rest = r
if len(rest) == 0 {
return nil, args, fmt.Errorf("unterminated map (missing value)")
}
value, r, err := composeArgs(rest)
if err != nil {
return nil, args, fmt.Errorf("invalid map value: %w", err)
}
m[key] = value
rest = r
}
return m, rest[1:], nil
}
// Autodetect int or string
if i, err := strconv.Atoi(args[0]); err == nil {
return i, args[1:], nil
}
return args[0], args[1:], nil
}

func send(server string, method string, args []any, notification bool) (any, any, error) {
netType := "unix"
if strings.Contains(server, ":") {
netType = "tcp"
}
c, err := net.Dial(netType, server)
if err != nil {
return nil, nil, fmt.Errorf("error connecting to server: %w", err)
}

conn := msgpackrpc.NewConnection(c, c, nil, nil, nil)
defer conn.Close()
go conn.Run()

// Send notification...
if notification {
if err := conn.SendNotification(method, args); err != nil {
return nil, nil, fmt.Errorf("error sending notification: %w", err)
}
return nil, nil, nil
}

// ...or send Request
reqResult, reqError, err := conn.SendRequest(context.Background(), method, args)
if err != nil {
return nil, nil, fmt.Errorf("error sending request: %w", err)
}
return reqResult, reqError, nil
}
6 changes: 3 additions & 3 deletions debian/arduino-router/usr/share/doc/arduino-router/copyright
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ To purchase a commercial license, send an email to license@arduino.cc.
THIRD PARTY NOTICES

*****
github.com/creack/goselect@v0.1.2
github.com/creack/goselect@v0.1.3

The MIT License (MIT)

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

*****
github.com/spf13/pflag@v1.0.9
github.com/spf13/pflag@v1.0.10

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

*****
golang.org/x/sys/unix@v0.37.0
golang.org/x/sys/unix@v0.38.0

Copyright 2009 The Go Authors.

Expand Down
72 changes: 0 additions & 72 deletions examples/generic_sock_client/main.go

This file was deleted.

Loading