Skip to content

Commit b4b4ad6

Browse files
authored
[skip-changelog] serial-discovery now talks pluggable discovery protocol v1 (#1327)
* Added Port object in grpc API * serial-discovery now talks Pluggable Discovery protocol v1
1 parent 2344d99 commit b4b4ad6

File tree

10 files changed

+437
-70
lines changed

10 files changed

+437
-70
lines changed

Diff for: arduino/cores/packagemanager/identify.go

+1
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,6 @@ func (pm *PackageManager) IdentifyBoard(idProps *properties.Map) []*cores.Board
6060
id++
6161
}
6262
}
63+
6364
return foundBoards
6465
}

Diff for: arduino/discovery/discovery.go

+54-23
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"sync"
2222
"time"
2323

24+
"github.com/arduino/arduino-cli/cli/globals"
2425
"github.com/arduino/arduino-cli/executils"
2526
"github.com/arduino/go-properties-orderedmap"
2627
"github.com/pkg/errors"
@@ -30,7 +31,6 @@ import (
3031
// with the boards.
3132
type PluggableDiscovery struct {
3233
id string
33-
args []string
3434
process *executils.Process
3535
outgoingCommandsPipe io.Writer
3636
incomingMessagesChan <-chan *discoveryMessage
@@ -45,20 +45,21 @@ type PluggableDiscovery struct {
4545
}
4646

4747
type discoveryMessage struct {
48-
EventType string `json:"eventType"`
49-
Message string `json:"message"`
50-
Ports []*Port `json:"ports"`
51-
Port *Port `json:"port"`
48+
EventType string `json:"eventType"`
49+
Message string `json:"message"`
50+
Error bool `json:"error"`
51+
ProtocolVersion int `json:"protocolVersion"` // Used in HELLO command
52+
Ports []*Port `json:"ports"` // Used in LIST command
53+
Port *Port `json:"port"` // Used in add and remove events
5254
}
5355

5456
// Port containts metadata about a port to connect to a board.
5557
type Port struct {
56-
Address string `json:"address"`
57-
AddressLabel string `json:"label"`
58-
Protocol string `json:"protocol"`
59-
ProtocolLabel string `json:"protocolLabel"`
60-
Properties *properties.Map `json:"prefs"`
61-
IdentificationProperties *properties.Map `json:"identificationPrefs"`
58+
Address string `json:"address"`
59+
AddressLabel string `json:"label"`
60+
Protocol string `json:"protocol"`
61+
ProtocolLabel string `json:"protocolLabel"`
62+
Properties *properties.Map `json:"properties"`
6263
}
6364

6465
func (p *Port) String() string {
@@ -121,20 +122,20 @@ func (disc *PluggableDiscovery) jsonDecodeLoop(in io.Reader, outChan chan<- *dis
121122
disc.statusMutex.Unlock()
122123
close(outChan)
123124
}
125+
124126
for {
125127
var msg discoveryMessage
126128
if err := decoder.Decode(&msg); err != nil {
127129
closeAndReportError(err)
128130
return
129131
}
130-
131132
if msg.EventType == "add" {
132133
if msg.Port == nil {
133134
closeAndReportError(errors.New("invalid 'add' message: missing port"))
134135
return
135136
}
136137
disc.statusMutex.Lock()
137-
disc.cachedPorts[msg.Port.Address] = msg.Port
138+
disc.cachedPorts[msg.Port.Address+"|"+msg.Port.Protocol] = msg.Port
138139
if disc.eventChan != nil {
139140
disc.eventChan <- &Event{"add", msg.Port}
140141
}
@@ -145,7 +146,7 @@ func (disc *PluggableDiscovery) jsonDecodeLoop(in io.Reader, outChan chan<- *dis
145146
return
146147
}
147148
disc.statusMutex.Lock()
148-
delete(disc.cachedPorts, msg.Port.Address)
149+
delete(disc.cachedPorts, msg.Port.Address+"|"+msg.Port.Protocol)
149150
if disc.eventChan != nil {
150151
disc.eventChan <- &Event{"remove", msg.Port}
151152
}
@@ -187,13 +188,35 @@ func (disc *PluggableDiscovery) waitMessage(timeout time.Duration) (*discoveryMe
187188
}
188189

189190
func (disc *PluggableDiscovery) sendCommand(command string) error {
190-
if n, err := disc.outgoingCommandsPipe.Write([]byte(command)); err != nil {
191+
data := []byte(command)
192+
for {
193+
n, err := disc.outgoingCommandsPipe.Write(data)
194+
if err != nil {
195+
return err
196+
}
197+
if n == len(data) {
198+
return nil
199+
}
200+
data = data[n:]
201+
}
202+
}
203+
204+
// Hello sends the HELLO command to the discovery to agree on the pluggable discovery protocol. This
205+
// must be the first command to run in the communication with the discovery.
206+
func (disc *PluggableDiscovery) Hello() error {
207+
if err := disc.sendCommand("HELLO 1 \"arduino-cli " + globals.VersionInfo.VersionString + "\"\n"); err != nil {
191208
return err
192-
} else if n < len(command) {
193-
return disc.sendCommand(command[n:])
194-
} else {
195-
return nil
196209
}
210+
if msg, err := disc.waitMessage(time.Second * 10); err != nil {
211+
return err
212+
} else if msg.EventType != "hello" {
213+
return errors.Errorf("communication out of sync, expected 'hello', received '%s'", msg.EventType)
214+
} else if msg.Message != "OK" || msg.Error {
215+
return errors.Errorf("command failed: %s", msg.Message)
216+
} else if msg.ProtocolVersion > 1 {
217+
return errors.Errorf("protocol version not supported: requested 1, got %d", msg.ProtocolVersion)
218+
}
219+
return nil
197220
}
198221

199222
// Start initializes and start the discovery internal subroutines. This command must be
@@ -206,7 +229,7 @@ func (disc *PluggableDiscovery) Start() error {
206229
return err
207230
} else if msg.EventType != "start" {
208231
return errors.Errorf("communication out of sync, expected 'start', received '%s'", msg.EventType)
209-
} else if msg.Message != "OK" {
232+
} else if msg.Message != "OK" || msg.Error {
210233
return errors.Errorf("command failed: %s", msg.Message)
211234
}
212235
return nil
@@ -223,7 +246,7 @@ func (disc *PluggableDiscovery) Stop() error {
223246
return err
224247
} else if msg.EventType != "stop" {
225248
return errors.Errorf("communication out of sync, expected 'stop', received '%s'", msg.EventType)
226-
} else if msg.Message != "OK" {
249+
} else if msg.Message != "OK" || msg.Error {
227250
return errors.Errorf("command failed: %s", msg.Message)
228251
}
229252
return nil
@@ -238,7 +261,7 @@ func (disc *PluggableDiscovery) Quit() error {
238261
return err
239262
} else if msg.EventType != "quit" {
240263
return errors.Errorf("communication out of sync, expected 'quit', received '%s'", msg.EventType)
241-
} else if msg.Message != "OK" {
264+
} else if msg.Message != "OK" || msg.Error {
242265
return errors.Errorf("command failed: %s", msg.Message)
243266
}
244267
return nil
@@ -254,6 +277,8 @@ func (disc *PluggableDiscovery) List() ([]*Port, error) {
254277
return nil, err
255278
} else if msg.EventType != "list" {
256279
return nil, errors.Errorf("communication out of sync, expected 'list', received '%s'", msg.EventType)
280+
} else if msg.Error {
281+
return nil, errors.Errorf("command failed: %s", msg.Message)
257282
} else {
258283
return msg.Ports, nil
259284
}
@@ -285,7 +310,13 @@ func (disc *PluggableDiscovery) StartSync() error {
285310
return err
286311
}
287312

288-
// START_SYNC does not give any response
313+
if msg, err := disc.waitMessage(time.Second * 10); err != nil {
314+
return err
315+
} else if msg.EventType != "start_sync" {
316+
return errors.Errorf("communication out of sync, expected 'start_sync', received '%s'", msg.EventType)
317+
} else if msg.Message != "OK" || msg.Error {
318+
return errors.Errorf("command failed: %s", msg.Message)
319+
}
289320

290321
disc.eventsMode = true
291322
disc.cachedPorts = map[string]*Port{}

0 commit comments

Comments
 (0)