Skip to content

Commit efc07a1

Browse files
committed
Add Cloud API integration
This method discovers if a connected board needs an additional core and helps the user downloading it via BoardManager
1 parent f96f1d3 commit efc07a1

File tree

5 files changed

+148
-0
lines changed

5 files changed

+148
-0
lines changed

app/src/processing/app/Base.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,9 @@ public Base(String[] args) throws Exception {
463463

464464
new Thread(new BuiltInCoreIsNewerCheck(this)).start();
465465

466+
// Check for boards which need an additional core
467+
new Thread(new NewBoardListener(this)).start();
468+
466469
// Check for updates
467470
if (PreferencesData.getBoolean("update.check")) {
468471
new UpdateCheck(this);
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package processing.app;
2+
3+
import java.awt.event.WindowEvent;
4+
import java.awt.event.WindowFocusListener;
5+
import java.beans.PropertyChangeEvent;
6+
import java.beans.PropertyChangeListener;
7+
8+
import javax.swing.SwingUtilities;
9+
10+
import cc.arduino.UpdatableBoardsLibsFakeURLsHandler;
11+
import cc.arduino.view.NotificationPopup;
12+
import processing.app.Base;
13+
14+
public class NewBoardListener implements PropertyChangeListener, Runnable {
15+
private Base base;
16+
private Editor ed;
17+
18+
public NewBoardListener(Base base) {
19+
this.base = base;
20+
}
21+
22+
@Override
23+
public void propertyChange(PropertyChangeEvent event) {
24+
checkForNewBoardAttached();
25+
}
26+
27+
@Override
28+
public void run() {
29+
while (base.getActiveEditor() == null) {
30+
try {
31+
Thread.sleep(1000);
32+
} catch (InterruptedException e) {
33+
e.printStackTrace();
34+
}
35+
}
36+
BaseNoGui.addPropertyChangeListener(this);
37+
checkForNewBoardAttached();
38+
}
39+
40+
public void checkForNewBoardAttached() {
41+
String newBoardManagerLink = BaseNoGui.getBoardManagerLink();
42+
if (newBoardManagerLink.isEmpty()) {
43+
return;
44+
}
45+
46+
SwingUtilities.invokeLater(() -> {
47+
48+
ed = base.getActiveEditor();
49+
NotificationPopup notificationPopup = new NotificationPopup(ed,
50+
new UpdatableBoardsLibsFakeURLsHandler(base),
51+
newBoardManagerLink, false);
52+
if (ed.isFocused()) {
53+
notificationPopup.begin();
54+
return;
55+
}
56+
57+
// If the IDE is not focused wait until it is focused again to
58+
// display the notification, this avoids the annoying side effect
59+
// to "steal" the focus from another application.
60+
WindowFocusListener wfl = new WindowFocusListener() {
61+
@Override
62+
public void windowLostFocus(WindowEvent evt) {
63+
}
64+
65+
@Override
66+
public void windowGainedFocus(WindowEvent evt) {
67+
notificationPopup.begin();
68+
for (Editor e : base.getEditors())
69+
e.removeWindowFocusListener(this);
70+
}
71+
};
72+
73+
for (Editor e : base.getEditors())
74+
e.addWindowFocusListener(wfl);
75+
});
76+
}
77+
}

arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ public synchronized void retriggerDiscovery(boolean polled) {
159159
} else {
160160
if (parts[1] != "0000") {
161161
boardPort.setVIDPID(parts[1], parts[2]);
162+
// ask Cloud API to match the board with known VID/PID pair
163+
platform.getBoardWithMatchingVidPidFromCloud(parts[1], parts[2]);
162164
} else {
163165
boardPort.setVIDPID("0000", "0000");
164166
boardPort.setISerial("");

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import processing.app.packages.LibraryList;
2626
import processing.app.packages.UserLibrary;
2727

28+
import java.beans.PropertyChangeListener;
29+
import java.beans.PropertyChangeSupport;
2830
import java.io.File;
2931
import java.io.FileWriter;
3032
import java.io.IOException;
@@ -87,6 +89,8 @@ public class BaseNoGui {
8789
public static ContributionsIndexer indexer;
8890
public static LibrariesIndexer librariesIndexer;
8991

92+
private static String boardManagerLink = "";
93+
9094
// Returns a File object for the given pathname. If the pathname
9195
// is not absolute, it is interpreted relative to the current
9296
// directory when starting the IDE (which is not the same as the
@@ -398,6 +402,21 @@ static public LibraryList getUserLibs() {
398402
return libs.filterLibrariesInSubfolder(getSketchbookFolder());
399403
}
400404

405+
static public String getBoardManagerLink() {
406+
return boardManagerLink;
407+
}
408+
409+
protected static PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(BaseNoGui.class);;
410+
411+
public static void setBoardManagerLink(String temp) {
412+
boardManagerLink = temp;
413+
propertyChangeSupport.firePropertyChange("boardManagerLink", "", boardManagerLink);
414+
}
415+
416+
public static void addPropertyChangeListener(PropertyChangeListener listener) {
417+
propertyChangeSupport.addPropertyChangeListener(listener);
418+
}
419+
401420
/**
402421
* Given a folder, return a list of the header files in that folder (but not
403422
* the header files in its sub-folders, as those should be included from

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@
3838
import java.util.ArrayList;
3939
import java.util.Arrays;
4040

41+
import java.net.URL;
42+
import java.net.URLConnection;
43+
import java.net.HttpURLConnection;
44+
import com.fasterxml.jackson.databind.ObjectMapper;
45+
import com.fasterxml.jackson.databind.DeserializationFeature;
46+
import java.io.InputStream;
47+
4148
import static processing.app.I18n.tr;
4249

4350

@@ -181,6 +188,46 @@ public List<String> listSerialsNames(){
181188
return list;
182189
}
183190

191+
public static class BoardCloudAPIid {
192+
public BoardCloudAPIid() { }
193+
private String name;
194+
private String architecture;
195+
private String id;
196+
public String getName() { return name; }
197+
public String getArchitecture() { return architecture; }
198+
public String getId() { return id; }
199+
public void setName(String tmp) { name = tmp; }
200+
public void setArchitecture(String tmp) { architecture = tmp; }
201+
public void setId(String tmp) { id = tmp; }
202+
}
203+
204+
public synchronized void getBoardWithMatchingVidPidFromCloud(String vid, String pid) {
205+
// this method is less useful in Windows < WIN10 since you need drivers to be already installed
206+
ObjectMapper mapper = new ObjectMapper();
207+
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
208+
URLConnection con;
209+
try {
210+
URL jsonUrl = new URL("http", "api-builder.arduino.cc", 80, "/builder/boards/0x"+vid+"/0x"+pid);
211+
URLConnection connection = jsonUrl.openConnection();
212+
connection.connect();
213+
HttpURLConnection httpConnection = (HttpURLConnection) connection;
214+
int code = httpConnection.getResponseCode();
215+
if (code == 404) {
216+
return;
217+
}
218+
InputStream is = httpConnection.getInputStream();
219+
BoardCloudAPIid board = mapper.readValue(is, BoardCloudAPIid.class);
220+
// Launch a popup with a link to boardmanager#board.getName()
221+
// replace spaces with &
222+
String boardNameReplaced = board.getName().replaceAll(" ", "&");
223+
String message = I18n.format(tr("{0}Install{1} the package to use your {2}"), "<a href=\"http://boardsmanager/all#"+boardNameReplaced+"\">", "</a>", board.getName());
224+
BaseNoGui.setBoardManagerLink(message);
225+
} catch (Exception e) {
226+
// No connection no problem, fail silently
227+
//e.printStackTrace();
228+
}
229+
}
230+
184231
public synchronized Map<String, Object> resolveDeviceByVendorIdProductId(String serial, Map<String, TargetPackage> packages) {
185232
String vid_pid_iSerial = resolveDeviceAttachedToNative(serial);
186233
for (TargetPackage targetPackage : packages.values()) {

0 commit comments

Comments
 (0)