Skip to content

Commit b8617f0

Browse files
committed
Merge branch 'discovery' into daemon
2 parents 74042f1 + bab5455 commit b8617f0

File tree

8 files changed

+467
-88
lines changed

8 files changed

+467
-88
lines changed

Gopkg.lock

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

-4
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@
5151
branch = "master"
5252
name = "github.com/bgentry/go-netrc"
5353

54-
[[constraint]]
55-
name = "github.com/codeclysm/cc"
56-
version = "1.2.1"
57-
5854
[[constraint]]
5955
branch = "master"
6056
name = "github.com/mitchellh/go-homedir"

arduino/cores/cores.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ package cores
2020
import (
2121
"strings"
2222

23-
"github.com/arduino/go-paths-helper"
23+
paths "github.com/arduino/go-paths-helper"
2424

2525
"github.com/arduino/arduino-cli/arduino/resources"
26-
"github.com/arduino/go-properties-orderedmap"
27-
"go.bug.st/relaxed-semver"
26+
properties "github.com/arduino/go-properties-orderedmap"
27+
semver "go.bug.st/relaxed-semver"
2828
)
2929

3030
// Platform represents a platform package.
@@ -158,7 +158,7 @@ func (platform *Platform) latestReleaseVersion() *semver.Version {
158158
func (platform *Platform) GetAllInstalled() []*PlatformRelease {
159159
res := []*PlatformRelease{}
160160
for _, release := range platform.Releases {
161-
if release.InstallDir != nil {
161+
if release.IsInstalled() {
162162
res = append(res, release)
163163
}
164164
}
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* This file is part of arduino-cli.
3+
*
4+
* Copyright 2018 ARDUINO SA (http://www.arduino.cc/)
5+
*
6+
* This software is released under the GNU General Public License version 3,
7+
* which covers the main part of arduino-cli.
8+
* The terms of this license can be found at:
9+
* https://www.gnu.org/licenses/gpl-3.0.en.html
10+
*
11+
* You can be released from the requirements of the above licenses by purchasing
12+
* a commercial license. Buying such a license is mandatory if you want to modify or
13+
* otherwise use the software for commercial activities involving the Arduino
14+
* software without disclosing the source code of your own applications. To purchase
15+
* a commercial license, send an email to license@arduino.cc.
16+
*/
17+
18+
package packagemanager
19+
20+
import (
21+
"fmt"
22+
23+
"github.com/arduino/arduino-cli/arduino/cores"
24+
properties "github.com/arduino/go-properties-orderedmap"
25+
)
26+
27+
// IdentifyBoard returns a list of baords matching the provided identification properties.
28+
func (pm *PackageManager) IdentifyBoard(idProps *properties.Map) []*cores.Board {
29+
if idProps.Size() == 0 {
30+
return []*cores.Board{}
31+
}
32+
33+
checkSuffix := func(props *properties.Map, s string) (checked bool, found bool) {
34+
for k, v1 := range idProps.AsMap() {
35+
v2, ok := props.GetOk(k + s)
36+
if !ok {
37+
return false, false
38+
}
39+
if v1 != v2 {
40+
return true, false
41+
}
42+
}
43+
return false, true
44+
}
45+
46+
foundBoards := []*cores.Board{}
47+
for _, board := range pm.InstalledBoards() {
48+
if _, found := checkSuffix(board.Properties, ""); found {
49+
foundBoards = append(foundBoards, board)
50+
continue
51+
}
52+
id := 0
53+
for {
54+
again, found := checkSuffix(board.Properties, fmt.Sprintf(".%d", id))
55+
if found {
56+
foundBoards = append(foundBoards, board)
57+
}
58+
if !again {
59+
break
60+
}
61+
id++
62+
}
63+
}
64+
return foundBoards
65+
}

arduino/cores/packagemanager/package_manager.go

+32-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ import (
2626

2727
"github.com/arduino/arduino-cli/arduino/cores"
2828
"github.com/arduino/arduino-cli/arduino/cores/packageindex"
29-
"github.com/arduino/go-paths-helper"
29+
paths "github.com/arduino/go-paths-helper"
3030
properties "github.com/arduino/go-properties-orderedmap"
3131
"github.com/sirupsen/logrus"
32-
"go.bug.st/relaxed-semver"
32+
semver "go.bug.st/relaxed-semver"
3333
)
3434

3535
// PackageManager defines the superior oracle which understands all about
@@ -354,6 +354,36 @@ func (pm *PackageManager) GetAllInstalledToolsReleases() []*cores.ToolRelease {
354354
return tools
355355
}
356356

357+
// InstalledPlatformReleases returns all installed PlatformReleases. This function is
358+
// useful to range all PlatformReleases in for loops.
359+
func (pm *PackageManager) InstalledPlatformReleases() []*cores.PlatformRelease {
360+
platforms := []*cores.PlatformRelease{}
361+
for _, targetPackage := range pm.packages.Packages {
362+
for _, platform := range targetPackage.Platforms {
363+
for _, release := range platform.GetAllInstalled() {
364+
platforms = append(platforms, release)
365+
}
366+
}
367+
}
368+
return platforms
369+
}
370+
371+
// InstalledBoards returns all installed Boards. This function is useful to range
372+
// all Boards in for loops.
373+
func (pm *PackageManager) InstalledBoards() []*cores.Board {
374+
boards := []*cores.Board{}
375+
for _, targetPackage := range pm.packages.Packages {
376+
for _, platform := range targetPackage.Platforms {
377+
for _, release := range platform.GetAllInstalled() {
378+
for _, board := range release.Boards {
379+
boards = append(boards, board)
380+
}
381+
}
382+
}
383+
}
384+
return boards
385+
}
386+
357387
func (pm *PackageManager) FindToolsRequiredForBoard(board *cores.Board) ([]*cores.ToolRelease, error) {
358388
pm.Log.Infof("Searching tools required for board %s", board)
359389

arduino/discovery/discovery.go

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
//
2+
// This file is part of arduino-cli.
3+
//
4+
// Copyright 2018 ARDUINO SA (http://www.arduino.cc/)
5+
//
6+
// This software is released under the GNU General Public License version 3,
7+
// which covers the main part of arduino-cli.
8+
// The terms of this license can be found at:
9+
// https://www.gnu.org/licenses/gpl-3.0.en.html
10+
//
11+
// You can be released from the requirements of the above licenses by purchasing
12+
// a commercial license. Buying such a license is mandatory if you want to modify or
13+
// otherwise use the software for commercial activities involving the Arduino
14+
// software without disclosing the source code of your own applications. To purchase
15+
// a commercial license, send an email to license@arduino.cc.
16+
//
17+
18+
package discovery
19+
20+
import (
21+
"encoding/json"
22+
"fmt"
23+
"io"
24+
"os/exec"
25+
"time"
26+
27+
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
28+
29+
properties "github.com/arduino/go-properties-orderedmap"
30+
31+
"github.com/arduino/arduino-cli/executils"
32+
)
33+
34+
// Discovery is an instance of a discovery tool
35+
type Discovery struct {
36+
in io.WriteCloser
37+
out io.ReadCloser
38+
outJSON *json.Decoder
39+
cmd *exec.Cmd
40+
Timeout time.Duration
41+
}
42+
43+
// BoardPort is a generic port descriptor
44+
type BoardPort struct {
45+
Address string `json:"address"`
46+
Label string `json:"label"`
47+
Prefs *properties.Map `json:"prefs"`
48+
IdentificationPrefs *properties.Map `json:"identificationPrefs"`
49+
Protocol string `json:"protocol"`
50+
ProtocolLabel string `json:"protocolLabel"`
51+
}
52+
53+
type eventJSON struct {
54+
EventType string `json:"eventType,required"`
55+
Ports []*BoardPort `json:"ports"`
56+
}
57+
58+
// NewFromCommandLine creates a new Discovery object
59+
func NewFromCommandLine(args ...string) (*Discovery, error) {
60+
cmd, err := executils.Command(args)
61+
if err != nil {
62+
return nil, fmt.Errorf("creating discovery process: %s", err)
63+
}
64+
disc := &Discovery{Timeout: time.Second}
65+
disc.cmd = cmd
66+
return disc, nil
67+
}
68+
69+
// Start starts the specified discovery
70+
func (d *Discovery) Start() error {
71+
if in, err := d.cmd.StdinPipe(); err == nil {
72+
d.in = in
73+
} else {
74+
return fmt.Errorf("creating stdin pipe for discovery: %s", err)
75+
}
76+
if out, err := d.cmd.StdoutPipe(); err == nil {
77+
d.out = out
78+
d.outJSON = json.NewDecoder(d.out)
79+
} else {
80+
return fmt.Errorf("creating stdout pipe for discovery: %s", err)
81+
}
82+
if err := d.cmd.Start(); err != nil {
83+
return fmt.Errorf("starting discovery process: %s", err)
84+
}
85+
return nil
86+
}
87+
88+
// List retrieve the port list from this discovery
89+
func (d *Discovery) List() ([]*BoardPort, error) {
90+
if _, err := d.in.Write([]byte("LIST\n")); err != nil {
91+
return nil, fmt.Errorf("sending LIST command to discovery: %s", err)
92+
}
93+
var event eventJSON
94+
done := make(chan bool)
95+
timeout := false
96+
go func() {
97+
select {
98+
case <-done:
99+
case <-time.After(d.Timeout):
100+
timeout = true
101+
d.Close()
102+
}
103+
}()
104+
if err := d.outJSON.Decode(&event); err != nil {
105+
if timeout {
106+
return nil, fmt.Errorf("decoding LIST command: timeout")
107+
}
108+
return nil, fmt.Errorf("decoding LIST command: %s", err)
109+
}
110+
done <- true
111+
return event.Ports, nil
112+
}
113+
114+
// Close stops the Discovery and free the resources
115+
func (d *Discovery) Close() error {
116+
// TODO: Send QUIT for safe close or terminate process after a small timeout
117+
if err := d.in.Close(); err != nil {
118+
return fmt.Errorf("closing stdin pipe: %s", err)
119+
}
120+
if err := d.out.Close(); err != nil {
121+
return fmt.Errorf("closing stdout pipe: %s", err)
122+
}
123+
if d.cmd != nil {
124+
d.cmd.Process.Kill()
125+
}
126+
return nil
127+
}
128+
129+
// ExtractDiscoveriesFromPlatforms returns all Discovery from all the installed platforms.
130+
func ExtractDiscoveriesFromPlatforms(pm *packagemanager.PackageManager) map[string]*Discovery {
131+
res := map[string]*Discovery{}
132+
133+
for _, platformRelease := range pm.InstalledPlatformReleases() {
134+
discoveries := platformRelease.Properties.SubTree("discovery").FirstLevelOf()
135+
136+
for name, props := range discoveries {
137+
if pattern, has := props.GetOk("pattern"); has {
138+
props.Merge(platformRelease.Properties)
139+
cmdLine := props.ExpandPropsInString(pattern)
140+
if cmdArgs, err := properties.SplitQuotedString(cmdLine, `"`, false); err != nil {
141+
// TODO
142+
} else if disc, err := NewFromCommandLine(cmdArgs...); err != nil {
143+
// TODO
144+
} else {
145+
res[name] = disc
146+
}
147+
}
148+
}
149+
}
150+
151+
return res
152+
}

0 commit comments

Comments
 (0)