@@ -20,8 +20,11 @@ import (
20
20
"context"
21
21
"fmt"
22
22
"io"
23
+ "os"
23
24
"strings"
25
+ "sync"
24
26
"testing"
27
+ "time"
25
28
26
29
"github.com/arduino/arduino-cli/executils"
27
30
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
@@ -105,3 +108,131 @@ func (cli *ArduinoCLI) Run(args ...string) ([]byte, []byte, error) {
105
108
106
109
return stdoutBuf .Bytes (), stderrBuf .Bytes (), cliErr
107
110
}
111
+
112
+ // StartDeamon starts the Arduino CLI daemon. It returns the address of the daemon.
113
+ func (cli * ArduinoCLI ) StartDeamon (verbose bool ) string {
114
+ args := []string {"daemon" , "--format" , "json" }
115
+ if cli .cliConfigPath != nil {
116
+ args = append ([]string {"--config-file" , cli .cliConfigPath .String ()}, args ... )
117
+ }
118
+ if verbose {
119
+ args = append (args , "-v" , "--log-level" , "debug" )
120
+ }
121
+ cliProc , err := executils .NewProcessFromPath (cli .cliEnvVars , cli .path , args ... )
122
+ cli .t .NoError (err )
123
+ stdout , err := cliProc .StdoutPipe ()
124
+ cli .t .NoError (err )
125
+ stderr , err := cliProc .StderrPipe ()
126
+ cli .t .NoError (err )
127
+ _ , err = cliProc .StdinPipe ()
128
+ cli .t .NoError (err )
129
+
130
+ cli .t .NoError (cliProc .Start ())
131
+ cli .proc = cliProc
132
+
133
+ // var daemonAddr struct {
134
+ // IP string
135
+ // Port string
136
+ // }
137
+ // dec := json.NewDecoder(stdout)
138
+ // cli.t.NoError(dec.Decode(&daemonAddr))
139
+ // cli.daemonAddr = daemonAddr.IP + ":" + daemonAddr.Port
140
+ cli .daemonAddr = "127.0.0.1:50051"
141
+
142
+ copy := func (dst io.Writer , src io.Reader ) {
143
+ buff := make ([]byte , 1024 )
144
+ for {
145
+ n , err := src .Read (buff )
146
+ if err != nil {
147
+ return
148
+ }
149
+ dst .Write ([]byte (color .YellowString (string (buff [:n ]))))
150
+ }
151
+ }
152
+ go copy (os .Stdout , stdout )
153
+ go copy (os .Stderr , stderr )
154
+ conn , err := grpc .Dial (cli .daemonAddr , grpc .WithInsecure (), grpc .WithBlock ())
155
+ cli .t .NoError (err )
156
+ cli .daemonConn = conn
157
+ cli .daemonClient = commands .NewArduinoCoreServiceClient (conn )
158
+
159
+ return cli .daemonAddr
160
+ }
161
+
162
+ // ArduinoCLIInstance is an Arduino CLI gRPC instance.
163
+ type ArduinoCLIInstance struct {
164
+ cli * ArduinoCLI
165
+ instance * commands.Instance
166
+ }
167
+
168
+ var logCallfMutex sync.Mutex
169
+
170
+ func logCallf (format string , a ... interface {}) {
171
+ logCallfMutex .Lock ()
172
+ fmt .Print (color .HiRedString (format , a ... ))
173
+ logCallfMutex .Unlock ()
174
+ }
175
+
176
+ // Create calls the "Create" gRPC method.
177
+ func (cli * ArduinoCLI ) Create () * ArduinoCLIInstance {
178
+ logCallf (">>> Create()" )
179
+ resp , err := cli .daemonClient .Create (context .Background (), & commands.CreateRequest {})
180
+ cli .t .NoError (err )
181
+ logCallf (" -> %v\n " , resp )
182
+ return & ArduinoCLIInstance {
183
+ cli : cli ,
184
+ instance : resp .Instance ,
185
+ }
186
+ }
187
+
188
+ // Init calls the "Init" gRPC method.
189
+ func (inst * ArduinoCLIInstance ) Init (profile string , sketchPath string , respCB func (* commands.InitResponse )) error {
190
+ initReq := & commands.InitRequest {
191
+ Instance : inst .instance ,
192
+ Profile : profile ,
193
+ SketchPath : sketchPath ,
194
+ }
195
+ logCallf (">>> Init(%v)\n " , initReq )
196
+ initClient , err := inst .cli .daemonClient .Init (context .Background (), initReq )
197
+ if err != nil {
198
+ return err
199
+ }
200
+ for {
201
+ msg , err := initClient .Recv ()
202
+ if err == io .EOF {
203
+ logCallf ("<<< Init EOF\n " )
204
+ return nil
205
+ }
206
+ if err != nil {
207
+ return err
208
+ }
209
+ if respCB != nil {
210
+ respCB (msg )
211
+ }
212
+ }
213
+ }
214
+
215
+ // BoardList calls the "BoardList" gRPC method.
216
+ func (inst * ArduinoCLIInstance ) BoardList (timeout time.Duration ) (* commands.BoardListResponse , error ) {
217
+ boardListReq := & commands.BoardListRequest {
218
+ Instance : inst .instance ,
219
+ Timeout : timeout .Milliseconds (),
220
+ }
221
+ logCallf (">>> BoardList(%v) -> " , boardListReq )
222
+ resp , err := inst .cli .daemonClient .BoardList (context .Background (), boardListReq )
223
+ logCallf ("err=%v\n " , err )
224
+ return resp , err
225
+ }
226
+
227
+ // BoardListWatch calls the "BoardListWatch" gRPC method.
228
+ func (inst * ArduinoCLIInstance ) BoardListWatch () (commands.ArduinoCoreService_BoardListWatchClient , error ) {
229
+ boardListWatchReq := & commands.BoardListWatchRequest {
230
+ Instance : inst .instance ,
231
+ }
232
+ logCallf (">>> BoardListWatch(%v)\n " , boardListWatchReq )
233
+ watcher , err := inst .cli .daemonClient .BoardListWatch (context .Background ())
234
+ if err != nil {
235
+ return watcher , err
236
+ }
237
+ return watcher , watcher .Send (boardListWatchReq )
238
+ }
0 commit comments