Skip to content

Commit 568eb88

Browse files
committed
Initial POC
0 parents  commit 568eb88

File tree

2 files changed

+230
-0
lines changed

2 files changed

+230
-0
lines changed

main.go

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
//
2+
// This file is part of serial-discovery.
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 main
19+
20+
import (
21+
"bufio"
22+
"encoding/json"
23+
"fmt"
24+
"os"
25+
"strings"
26+
"sync"
27+
28+
properties "github.com/arduino/go-properties-orderedmap"
29+
"github.com/oleksandr/bonjour"
30+
)
31+
32+
func main() {
33+
syncStarted := false
34+
var syncCloseChan chan<- bool
35+
36+
reader := bufio.NewReader(os.Stdin)
37+
for {
38+
cmd, err := reader.ReadString('\n')
39+
if err != nil {
40+
outputError(err)
41+
os.Exit(1)
42+
}
43+
cmd = strings.ToUpper(strings.TrimSpace(cmd))
44+
switch cmd {
45+
case "START":
46+
outputMessage("start", "OK")
47+
case "STOP":
48+
if syncStarted {
49+
syncCloseChan <- true
50+
syncStarted = false
51+
}
52+
outputMessage("stop", "OK")
53+
case "LIST":
54+
outputList()
55+
case "QUIT":
56+
outputMessage("quit", "OK")
57+
os.Exit(0)
58+
case "START_SYNC":
59+
if syncStarted {
60+
outputMessage("startSync", "OK")
61+
} else if close, err := startSync(); err != nil {
62+
outputError(err)
63+
} else {
64+
syncCloseChan = close
65+
syncStarted = true
66+
}
67+
default:
68+
outputError(fmt.Errorf("Command %s not supported", cmd))
69+
}
70+
}
71+
}
72+
73+
type boardPortJSON struct {
74+
Address string `json:"address"`
75+
Label string `json:"label,omitempty"`
76+
Prefs *properties.Map `json:"prefs,omitempty"`
77+
IdentificationPrefs *properties.Map `json:"identificationPrefs,omitempty"`
78+
Protocol string `json:"protocol,omitempty"`
79+
ProtocolLabel string `json:"protocolLabel,omitempty"`
80+
}
81+
82+
type listOutputJSON struct {
83+
EventType string `json:"eventType"`
84+
Ports []*boardPortJSON `json:"ports"`
85+
}
86+
87+
func outputList() {
88+
/*
89+
list, err := enumerator.GetDetailedPortsList()
90+
if err != nil {
91+
outputError(err)
92+
return
93+
}
94+
portsJSON := []*boardPortJSON{}
95+
for _, port := range list {
96+
portJSON := newBoardPortJSON(port)
97+
portsJSON = append(portsJSON, portJSON)
98+
}
99+
d, err := json.MarshalIndent(&listOutputJSON{
100+
EventType: "list",
101+
Ports: portsJSON,
102+
}, "", " ")
103+
if err != nil {
104+
outputError(err)
105+
return
106+
}
107+
syncronizedPrintLn(string(d))
108+
*/
109+
}
110+
111+
func newBoardPortJSON(port *bonjour.ServiceEntry) *boardPortJSON {
112+
prefs := properties.NewMap()
113+
identificationPrefs := properties.NewMap()
114+
portJSON := &boardPortJSON{
115+
Address: port.AddrIPv4.String(),
116+
Label: port.AddrIPv4.String(),
117+
Protocol: "network",
118+
ProtocolLabel: "Network Port",
119+
Prefs: prefs,
120+
IdentificationPrefs: identificationPrefs,
121+
}
122+
portJSON.Prefs.Set("hostname", port.HostName)
123+
portJSON.Prefs.Set("text", port.Text[0])
124+
return portJSON
125+
}
126+
127+
type messageOutputJSON struct {
128+
EventType string `json:"eventType"`
129+
Message string `json:"message"`
130+
}
131+
132+
func outputMessage(eventType, message string) {
133+
d, err := json.MarshalIndent(&messageOutputJSON{
134+
EventType: eventType,
135+
Message: message,
136+
}, "", " ")
137+
if err != nil {
138+
outputError(err)
139+
} else {
140+
syncronizedPrintLn(string(d))
141+
}
142+
}
143+
144+
func outputError(err error) {
145+
outputMessage("error", err.Error())
146+
}
147+
148+
var stdoutMutext sync.Mutex
149+
150+
func syncronizedPrintLn(a ...interface{}) {
151+
stdoutMutext.Lock()
152+
fmt.Println(a...)
153+
stdoutMutext.Unlock()
154+
}

sync.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//
2+
// This file is part of serial-discovery.
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 main
19+
20+
import (
21+
"encoding/json"
22+
"fmt"
23+
"log"
24+
25+
"github.com/oleksandr/bonjour"
26+
)
27+
28+
type syncOutputJSON struct {
29+
EventType string `json:"eventType"`
30+
Port *boardPortJSON `json:"port"`
31+
}
32+
33+
func outputSyncMessage(message *syncOutputJSON) {
34+
d, err := json.MarshalIndent(message, "", " ")
35+
if err != nil {
36+
outputError(err)
37+
} else {
38+
syncronizedPrintLn(string(d))
39+
}
40+
}
41+
42+
func startSync() (chan<- bool, error) {
43+
44+
closeChan := make(chan bool)
45+
46+
resolver, err := bonjour.NewResolver(nil)
47+
if err != nil {
48+
log.Println("Failed to initialize resolver:", err.Error())
49+
return nil, err
50+
}
51+
52+
results := make(chan *bonjour.ServiceEntry)
53+
54+
go func(results chan *bonjour.ServiceEntry, exitCh chan<- bool) {
55+
for {
56+
for e := range results {
57+
log.Printf("%+v", e)
58+
if e.AddrIPv4 != nil {
59+
fmt.Println(e)
60+
}
61+
}
62+
}
63+
}(results, resolver.Exit)
64+
65+
// Sample output
66+
//2018/12/12 18:05:14 &{ServiceRecord:{Instance:Arduino Service:_arduino._tcp Domain:local serviceName: serviceInstanceName: serviceTypeName:} HostName:Arduino.local. Port:65280 Text:[ssh_upload=no tcp_check=no auth_upload=yes board=uno2018] TTL:120 AddrIPv4:10.130.22.247 AddrIPv6:<nil>}
67+
//&{{Arduino _arduino._tcp local } Arduino.local. 65280 [ssh_upload=no tcp_check=no auth_upload=yes board=uno2018] 120 10.130.22.247 <nil>}
68+
69+
err = resolver.Browse("_arduino._tcp", "", results)
70+
if err != nil {
71+
log.Println("Failed to browse:", err.Error())
72+
return nil, err
73+
}
74+
75+
return closeChan, nil
76+
}

0 commit comments

Comments
 (0)