Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pluggable monitor cli command #1495

Merged
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
42 changes: 40 additions & 2 deletions cli/monitor/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package monitor

import (
"context"
"errors"
"io"
"os"
"sort"
"strings"
Expand Down Expand Up @@ -78,8 +80,44 @@ func runMonitorCmd(cmd *cobra.Command, args []string) {
return
}

feedback.Error("Monitor functionality not yet implemented")
os.Exit(errorcodes.ErrGeneric)
tty, err := newStdInOutTerminal()
if err != nil {
feedback.Error(err)
os.Exit(errorcodes.ErrGeneric)
}
defer tty.Close()

portProxy, _, err := monitor.Monitor(context.Background(), &rpc.MonitorRequest{
Instance: instance,
Port: port.ToRPC(),
Fqbn: "",
})
if err != nil {
feedback.Error(err)
os.Exit(errorcodes.ErrGeneric)
}
defer portProxy.Close()

ctx, cancel := context.WithCancel(context.Background())
go func() {
_, err := io.Copy(tty, portProxy)
if err != nil && !errors.Is(err, io.EOF) {
feedback.Error(tr("Port closed:"), err)
}
cancel()
}()
go func() {
_, err := io.Copy(portProxy, tty)
if err != nil && !errors.Is(err, io.EOF) {
feedback.Error(tr("Port closed:"), err)
}
cancel()
}()

feedback.Print(tr("Connected to %s! Press CTRL-C to exit.", port.String()))

// Wait for port closed
<-ctx.Done()
}

type detailsResult struct {
Expand Down
39 changes: 39 additions & 0 deletions cli/monitor/term.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// This file is part of arduino-cli.
//
// Copyright 2020 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-cli.
// 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 [email protected].

package monitor

import (
"os"
)

type stdInOut struct {
}

func newStdInOutTerminal() (*stdInOut, error) {
return &stdInOut{}, nil
}

func (n *stdInOut) Close() error {
return nil
}

func (n *stdInOut) Read(buff []byte) (int, error) {
return os.Stdin.Read(buff)
}

func (n *stdInOut) Write(buff []byte) (int, error) {
return os.Stdout.Write(buff)
}
73 changes: 73 additions & 0 deletions commands/monitor/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,85 @@
package monitor

import (
"context"
"io"

"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
pluggableMonitor "github.com/arduino/arduino-cli/arduino/monitor"
"github.com/arduino/arduino-cli/commands"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
)

// PortProxy is an io.ReadWriteCloser that maps into the monitor port of the board
type PortProxy struct {
rw io.ReadWriter
changeSettingsCB func(setting, value string) error
closeCB func() error
}

func (p *PortProxy) Read(buff []byte) (int, error) {
return p.rw.Read(buff)
}

func (p *PortProxy) Write(buff []byte) (int, error) {
return p.rw.Write(buff)
}

// Config sets the port configuration setting to the specified value
func (p *PortProxy) Config(setting, value string) error {
return p.changeSettingsCB(setting, value)
}

// Close the port
func (p *PortProxy) Close() error {
return p.closeCB()
}

// Monitor opens a communication port. It returns a PortProxy to communicate with the port and a PortDescriptor
// that describes the available configuration settings.
func Monitor(ctx context.Context, req *rpc.MonitorRequest) (*PortProxy, *pluggableMonitor.PortDescriptor, error) {
pm := commands.GetPackageManager(req.GetInstance().GetId())
if pm == nil {
return nil, nil, &commands.InvalidInstanceError{}
}

monitorRef, err := findMonitorForProtocolAndBoard(pm, req.GetPort(), req.GetFqbn())
if err != nil {
return nil, nil, err
}

tool := pm.FindMonitorDependency(monitorRef)
if tool == nil {
return nil, nil, &commands.MonitorNotFoundError{Monitor: monitorRef.String()}
}

m := pluggableMonitor.New(monitorRef.Name, tool.InstallDir.Join(monitorRef.Name).String())

if err := m.Run(); err != nil {
return nil, nil, &commands.FailedMonitorError{Cause: err}
}

descriptor, err := m.Describe()
if err != nil {
return nil, nil, &commands.FailedMonitorError{Cause: err}
}

monIO, err := m.Open(req.GetPort())
if err != nil {
return nil, nil, &commands.FailedMonitorError{Cause: err}
}

return &PortProxy{
rw: monIO,
changeSettingsCB: m.Configure(setting, value),
closeCB: func() error {
m.Close()
return m.Quit()
},
}, descriptor, nil
}

func findMonitorForProtocolAndBoard(pm *packagemanager.PackageManager, port *rpc.Port, fqbn string) (*cores.MonitorDependency, error) {
if port == nil {
return nil, &commands.MissingPortError{}
Expand Down
25 changes: 17 additions & 8 deletions i18n/data/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,10 @@ msgstr "Configuring platform."
msgid "Connected"
msgstr "Connected"

#: cli/monitor/monitor.go:117
msgid "Connected to %s! Press CTRL-C to exit."
msgstr "Connected to %s! Press CTRL-C to exit."

#: cli/board/list.go:87
#: cli/board/list.go:125
msgid "Core"
Expand Down Expand Up @@ -496,7 +500,7 @@ msgstr "Debugging not supported for board %s"
msgid "Debugging supported:"
msgstr "Debugging supported:"

#: cli/monitor/monitor.go:96
#: cli/monitor/monitor.go:134
msgid "Default"
msgstr "Default"

Expand Down Expand Up @@ -782,7 +786,7 @@ msgstr "Error getting information for library %s"
msgid "Error getting libraries info: %v"
msgstr "Error getting libraries info: %v"

#: cli/monitor/monitor.go:74
#: cli/monitor/monitor.go:76
msgid "Error getting port settings details: %s"
msgstr "Error getting port settings details: %s"

Expand Down Expand Up @@ -1130,7 +1134,7 @@ msgstr "Global variables use {0} bytes of dynamic memory."

#: cli/core/list.go:84
#: cli/core/search.go:114
#: cli/monitor/monitor.go:96
#: cli/monitor/monitor.go:134
#: cli/outdated/outdated.go:62
msgid "ID"
msgstr "ID"
Expand Down Expand Up @@ -1568,8 +1572,8 @@ msgstr "OS:"
msgid "Official Arduino board:"
msgstr "Official Arduino board:"

#: cli/monitor/monitor.go:45
#: cli/monitor/monitor.go:46
#: cli/monitor/monitor.go:47
#: cli/monitor/monitor.go:48
msgid "Open a communication port with a board."
msgstr "Open a communication port with a board."

Expand Down Expand Up @@ -1719,6 +1723,11 @@ msgstr "Platform size (bytes):"
msgid "Port"
msgstr "Port"

#: cli/monitor/monitor.go:105
#: cli/monitor/monitor.go:112
msgid "Port closed:"
msgstr "Port closed:"

#: commands/errors.go:508
msgid "Port monitor error"
msgstr "Port monitor error"
Expand Down Expand Up @@ -1852,7 +1861,7 @@ msgstr "Sets a setting value."
msgid "Sets where to save the configuration file."
msgstr "Sets where to save the configuration file."

#: cli/monitor/monitor.go:96
#: cli/monitor/monitor.go:134
msgid "Setting"
msgstr "Setting"

Expand All @@ -1869,7 +1878,7 @@ msgstr "Show all available core versions."
msgid "Show all build properties used instead of compiling."
msgstr "Show all build properties used instead of compiling."

#: cli/monitor/monitor.go:53
#: cli/monitor/monitor.go:55
msgid "Show all the settings of the communication port."
msgstr "Show all the settings of the communication port."

Expand Down Expand Up @@ -2327,7 +2336,7 @@ msgstr "VERSION"
msgid "VERSION_NUMBER"
msgstr "VERSION_NUMBER"

#: cli/monitor/monitor.go:96
#: cli/monitor/monitor.go:134
msgid "Values"
msgstr "Values"

Expand Down
8 changes: 4 additions & 4 deletions i18n/rice-box.go

Large diffs are not rendered by default.