Skip to content

Commit a91cf0c

Browse files
committed
Added arduino-cli daemon startup and some basic control code
1 parent 769641a commit a91cf0c

File tree

4 files changed

+276
-0
lines changed

4 files changed

+276
-0
lines changed

app/src/processing/app/Base.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ public Base(String[] args) throws Exception {
238238
}
239239
}
240240

241+
BaseNoGui.initArduinoCoreService();
242+
241243
SplashScreenHelper splash;
242244
if (parser.isGuiMode()) {
243245
// Setup all notification widgets
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* This file is part of Arduino.
3+
*
4+
* Copyright 2019 Arduino LLC (http://www.arduino.cc/)
5+
*
6+
* Arduino is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19+
*
20+
* As a special exception, you may use this file as part of a free software
21+
* library without restriction. Specifically, if other files instantiate
22+
* templates or use macros or inline functions from this file, or you compile
23+
* this file and link it with other files to produce an executable, this
24+
* file does not by itself cause the resulting executable to be covered by
25+
* the GNU General Public License. This exception does not however
26+
* invalidate any other reasons why the executable file might be covered by
27+
* the GNU General Public License.
28+
*/
29+
30+
package cc.arduino.cli;
31+
32+
import java.io.File;
33+
import java.io.IOException;
34+
import java.util.Iterator;
35+
36+
import cc.arduino.cli.commands.ArduinoCoreGrpc;
37+
import cc.arduino.cli.commands.ArduinoCoreGrpc.ArduinoCoreBlockingStub;
38+
import cc.arduino.cli.commands.Commands.Configuration;
39+
import cc.arduino.cli.commands.Commands.InitReq;
40+
import cc.arduino.cli.commands.Commands.InitResp;
41+
import cc.arduino.cli.commands.Common.Instance;
42+
import io.grpc.ManagedChannel;
43+
import io.grpc.ManagedChannelBuilder;
44+
import processing.app.BaseNoGui;
45+
import processing.app.debug.MessageSiphon;
46+
import processing.app.helpers.ProcessUtils;
47+
48+
public class ArduinoCore {
49+
50+
private Process cliProcess;
51+
private ArduinoCoreBlockingStub blocking;
52+
// private ArduinoCoreStub async;
53+
54+
public ArduinoCore() throws IOException {
55+
String cliPath = BaseNoGui.getContentFile("arduino-cli").getAbsolutePath();
56+
cliProcess = ProcessUtils.exec(new String[] { cliPath, "daemon" });
57+
new MessageSiphon(cliProcess.getInputStream(), (msg) -> {
58+
System.out.println("CLI> " + msg);
59+
});
60+
new MessageSiphon(cliProcess.getErrorStream(), (msg) -> {
61+
System.err.println("CLI> " + msg);
62+
});
63+
64+
// TODO: Do a better job managing the arduino-cli process
65+
try {
66+
Thread.sleep(1000);
67+
} catch (InterruptedException e) {
68+
}
69+
if (!cliProcess.isAlive()) {
70+
int res;
71+
try {
72+
res = cliProcess.waitFor();
73+
throw new IOException(
74+
"Arduino server terminated with return code " + res);
75+
} catch (InterruptedException e) {
76+
}
77+
throw new IOException("Arduino server terminated");
78+
}
79+
80+
ManagedChannel channel = ManagedChannelBuilder //
81+
.forAddress("127.0.0.1", 50051) //
82+
.usePlaintext() //
83+
.build();
84+
85+
blocking = ArduinoCoreGrpc.newBlockingStub(channel);
86+
// async = ArduinoCoreGrpc.newStub(channel);
87+
}
88+
89+
public ArduinoCoreInstance init(File dataDir, File sketchbookDir) {
90+
InitReq req = InitReq.newBuilder()
91+
.setConfiguration(Configuration.newBuilder() //
92+
.setDataDir(dataDir.getAbsolutePath()) //
93+
.setSketchbookDir(sketchbookDir.getAbsolutePath()))
94+
.build();
95+
Iterator<InitResp> resp = blocking.init(req);
96+
Instance instance = null;
97+
while (resp.hasNext()) {
98+
InitResp r = resp.next();
99+
if (r.hasTaskProgress()) {
100+
System.out.println(r.getTaskProgress());
101+
}
102+
if (r.hasDownloadProgress()) {
103+
System.out.println(r.getDownloadProgress());
104+
}
105+
if (r.getInstance() != null) {
106+
if (!r.getLibrariesIndexError().isEmpty()) {
107+
System.err.println(r.getLibrariesIndexError());
108+
}
109+
r.getPlatformsIndexErrorsList().forEach(System.err::println);
110+
instance = r.getInstance();
111+
}
112+
}
113+
return new ArduinoCoreInstance(instance, blocking);
114+
}
115+
116+
public static void main(String[] args) {
117+
try {
118+
ArduinoCore core = new ArduinoCore();
119+
ArduinoCoreInstance instance = core.init(new File("/mnt/ramdisk"),
120+
new File("/mnt/ramdisk/sketchbook"));
121+
instance.boardDetails("arduino:samd:mkr1000");
122+
instance.compile("arduino:samd:mkr1000",
123+
"/home/megabug/Arduino/alloc_check");
124+
} catch (Throwable e) {
125+
e.printStackTrace();
126+
}
127+
System.exit(0);
128+
}
129+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* This file is part of Arduino.
3+
*
4+
* Copyright 2019 Arduino LLC (http://www.arduino.cc/)
5+
*
6+
* Arduino is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19+
*
20+
* As a special exception, you may use this file as part of a free software
21+
* library without restriction. Specifically, if other files instantiate
22+
* templates or use macros or inline functions from this file, or you compile
23+
* this file and link it with other files to produce an executable, this
24+
* file does not by itself cause the resulting executable to be covered by
25+
* the GNU General Public License. This exception does not however
26+
* invalidate any other reasons why the executable file might be covered by
27+
* the GNU General Public License.
28+
*/
29+
30+
package cc.arduino.cli;
31+
32+
import java.util.Iterator;
33+
import java.util.List;
34+
35+
import com.google.protobuf.ByteString;
36+
37+
import cc.arduino.cli.commands.Board.BoardDetailsReq;
38+
import cc.arduino.cli.commands.Board.BoardDetailsResp;
39+
import cc.arduino.cli.commands.Commands.DestroyReq;
40+
import cc.arduino.cli.commands.Commands.RescanReq;
41+
import cc.arduino.cli.commands.Common.Instance;
42+
import cc.arduino.cli.commands.Compile.CompileReq;
43+
import cc.arduino.cli.commands.Compile.CompileResp;
44+
import cc.arduino.cli.commands.Lib.LibrarySearchReq;
45+
import cc.arduino.cli.commands.Lib.LibrarySearchResp;
46+
import cc.arduino.cli.commands.Lib.SearchedLibrary;
47+
import io.grpc.StatusException;
48+
import io.grpc.StatusRuntimeException;
49+
import cc.arduino.cli.commands.ArduinoCoreGrpc.ArduinoCoreBlockingStub;
50+
51+
public class ArduinoCoreInstance {
52+
53+
private Instance instance;
54+
private ArduinoCoreBlockingStub stub;
55+
56+
public ArduinoCoreInstance(Instance instance,
57+
ArduinoCoreBlockingStub blocking) {
58+
this.instance = instance;
59+
this.stub = blocking;
60+
}
61+
62+
public void boardDetails(String fqbn) throws StatusException {
63+
try {
64+
BoardDetailsReq req = BoardDetailsReq.newBuilder() //
65+
.setFqbn(fqbn) //
66+
.setInstance(instance) //
67+
.build();
68+
BoardDetailsResp resp = stub.boardDetails(req);
69+
System.out.println(resp.getName());
70+
} catch (StatusRuntimeException e) {
71+
throw e.getStatus().asException();
72+
}
73+
}
74+
75+
public void compile(String fqbn, String sketchPath) throws StatusException {
76+
try {
77+
CompileReq req = CompileReq.newBuilder() //
78+
.setInstance(instance) //
79+
.setFqbn(fqbn) //
80+
.setSketchPath(sketchPath) //
81+
.setVerbose(true) //
82+
.build();
83+
Iterator<CompileResp> stream = stub.compile(req);
84+
while (stream.hasNext()) {
85+
CompileResp resp = stream.next();
86+
ByteString out = resp.getOutStream();
87+
if (out != null)
88+
System.out.print(out.toStringUtf8());
89+
}
90+
} catch (StatusRuntimeException e) {
91+
throw e.getStatus().asException();
92+
}
93+
}
94+
95+
public void rescan() throws StatusException {
96+
try {
97+
stub.rescan(RescanReq.newBuilder() //
98+
.setInstance(instance) //
99+
.build());
100+
} catch (StatusRuntimeException e) {
101+
throw e.getStatus().asException();
102+
}
103+
}
104+
105+
public void destroy() throws StatusException {
106+
try {
107+
stub.destroy(DestroyReq.newBuilder() //
108+
.setInstance(instance).build());
109+
} catch (StatusRuntimeException e) {
110+
throw e.getStatus().asException();
111+
}
112+
}
113+
114+
// Lib functions
115+
116+
public List<SearchedLibrary> searchLibrary(String query)
117+
throws StatusException {
118+
try {
119+
LibrarySearchResp resp = stub.librarySearch(LibrarySearchReq.newBuilder() //
120+
.setInstance(instance) //
121+
.setQuery(query) //
122+
.build());
123+
return resp.getLibrariesList();
124+
} catch (StatusRuntimeException e) {
125+
throw e.getStatus().asException();
126+
}
127+
}
128+
}

arduino-core/src/processing/app/BaseNoGui.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package processing.app;
22

33
import cc.arduino.Constants;
4+
import cc.arduino.cli.ArduinoCore;
5+
import cc.arduino.cli.ArduinoCoreInstance;
46
import cc.arduino.contributions.GPGDetachedSignatureVerifier;
57
import cc.arduino.contributions.VersionComparator;
68
import cc.arduino.contributions.libraries.LibrariesIndexer;
@@ -105,6 +107,21 @@ public class BaseNoGui {
105107

106108
private static File buildCache;
107109

110+
private static ArduinoCoreInstance arduinoCoreInstance;
111+
112+
public static void initArduinoCoreService() {
113+
try {
114+
ArduinoCore core = new ArduinoCore();
115+
arduinoCoreInstance = core.init(getSettingsFolder(), getSketchbookFolder());
116+
} catch (Exception e) {
117+
e.printStackTrace();
118+
}
119+
}
120+
121+
public static ArduinoCoreInstance getArduinoCoreService() {
122+
return arduinoCoreInstance;
123+
}
124+
108125
// Returns a File object for the given pathname. If the pathname
109126
// is not absolute, it is interpreted relative to the current
110127
// directory when starting the IDE (which is not the same as the

0 commit comments

Comments
 (0)