1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-25 01:45:33 +02:00

Bug 516836 Terminal support for Arduino.

Add Arduino Serial Monitor as a Terminal Connector type. It uses the
Terminal's new cdtserial connector for communication and adds a
config panel that lets you pick the Arduino remote connection to
auto select the serial port. Also switched the Arduino launch
to fetch the serial port out of the global registry to pause and
resume the port while launching. The Terminal does not use the
remote connection to get the serial port.

Note: also adding the terminal as a dependency for builds. Yes,
further adds to our build cycle, but we're dealing with it so far
with o.e.remote.

Change-Id: I5a7cc9ffbf8ae60cd86e0e5440547d12202acbac
This commit is contained in:
Doug Schaefer 2017-05-17 13:57:01 -04:00
parent e74222b86c
commit 0880413e98
13 changed files with 506 additions and 7 deletions

View file

@ -365,7 +365,8 @@ public class SerialPort {
public void resume() throws IOException {
synchronized (pauseMutex) {
isPaused = false;
open();
handle = open0(portName, baudRate.getRate(), byteSize.getSize(), parity.ordinal(), stopBits.ordinal());
isOpen = true;
pauseMutex.notifyAll();
}
}

View file

@ -65,6 +65,11 @@
<unit id="org.eclipse.wst.xml_ui.feature.feature.group" version="0.0.0"/>
<repository location="http://download.eclipse.org/webtools/downloads/drops/R3.9.0/S-3.9.0M5-20170201000249/repository/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.tm.terminal.feature.feature.group" version="0.0.0"/>
<unit id="org.eclipse.tm.terminal.connector.cdtserial.feature.feature.group" version="0.0.0"/>
<repository location="http://download.eclipse.org/tm/terminal/updates/4.3milestones/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.tools.templates.core" version="0.0.0"/>
<unit id="org.eclipse.tools.templates.freemarker" version="0.0.0"/>

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.arduino.core;singleton:=true
Bundle-Version: 2.0.0.qualifier
Bundle-Version: 2.1.0.qualifier
Bundle-Activator: org.eclipse.cdt.arduino.core.internal.Activator
Bundle-Vendor: %providerName
Require-Bundle: org.eclipse.core.runtime,

View file

@ -7,7 +7,11 @@
*******************************************************************************/
package org.eclipse.cdt.arduino.core.internal.launch;
import java.io.IOException;
import org.eclipse.cdt.arduino.core.internal.Activator;
import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection;
import org.eclipse.cdt.serial.SerialPort;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
@ -33,7 +37,14 @@ public class ArduinoLaunch extends TargetedLaunch {
public void start() {
this.wasOpen = remote.getRemoteConnection().isOpen();
if (wasOpen) {
remote.pause();
SerialPort port = SerialPort.get(remote.getPortName());
if (port != null) {
try {
port.pause();
} catch (IOException e) {
Activator.log(e);
}
}
}
}
@ -41,7 +52,14 @@ public class ArduinoLaunch extends TargetedLaunch {
public void handleDebugEvents(DebugEvent[] events) {
super.handleDebugEvents(events);
if (isTerminated() && wasOpen) {
remote.resume();
SerialPort port = SerialPort.get(remote.getPortName());
if (port != null) {
try {
port.resume();
} catch (IOException e) {
Activator.log(e);
}
}
wasOpen = false;
}
}

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.arduino.ui;singleton:=true
Bundle-Version: 2.0.0.qualifier
Bundle-Version: 2.1.0.qualifier
Bundle-Activator: org.eclipse.cdt.arduino.ui.internal.Activator
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.expressions,
@ -17,7 +17,11 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.remote.ui;bundle-version="2.0.0",
org.eclipse.cdt.native.serial;bundle-version="1.0.0",
org.eclipse.tools.templates.ui;bundle-version="1.0.0",
org.eclipse.launchbar.remote.ui;bundle-version="1.0.0"
org.eclipse.launchbar.remote.ui;bundle-version="1.0.0",
org.eclipse.tm.terminal.connector.cdtserial;bundle-version="4.3.0",
org.eclipse.tm.terminal.view.ui;bundle-version="4.2.100",
org.eclipse.tm.terminal.view.core;bundle-version="4.2.0",
org.eclipse.tm.terminal.control;bundle-version="4.2.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Bundle-Vendor: %providerName

View file

@ -12,4 +12,6 @@ pluginName=Arduino C++ UI
providerName=Eclipse CDT
preferencePage.name=Arduino
arduinoDownloadsManager=Arduino Downloads Manager
arduinoDownloadsManager=Arduino Downloads Manager
arduinoTerminalConnector=Arduino Serial Monitor
arduinoTerminalLauncher=Arduino Serial Monitor

View file

@ -174,4 +174,11 @@
name="%arduinoDownloadsManager">
</command>
</extension>
<extension point="org.eclipse.tm.terminal.view.ui.launcherDelegates">
<delegate
class="org.eclipse.cdt.arduino.ui.internal.terminal.ArduinoTerminalLauncher"
id="org.eclipse.cdt.arduino.terminalLauncher"
label="%arduinoTerminalLauncher">
</delegate>
</extension>
</plugin>

View file

@ -30,6 +30,13 @@ public class Messages extends NLS {
public static String ArduinoPreferencePage_desc;
public static String PlatformDetailsDialog_0;
public static String PlatformDetailsDialog_1;
public static String ArduinoTerminalSettingsPage_BoardName;
public static String ArduinoTerminalSettingsPage_SerialPort;
public static String ArduinoTerminalSettingsPage_BaudRate;
public static String ArduinoTerminalSettingsPage_DataSize;
public static String ArduinoTerminalSettingsPage_Parity;
public static String ArduinoTerminalSettingsPage_StopBits;
public static String ArduinoTerminalSettingsPage_UnknownPort;
static {
// initialize resource bundle

View file

@ -26,3 +26,10 @@ libraries. For more information, see http://arduino.cc
ArduinoPreferencePage_desc=Enter URLs for package_index.json files one per line.
PlatformDetailsDialog_0=Platform:
PlatformDetailsDialog_1=Supports boards:\n
ArduinoTerminalSettingsPage_BoardName=Board Name:
ArduinoTerminalSettingsPage_SerialPort=Serial Port:
ArduinoTerminalSettingsPage_BaudRate=Baud Rate:
ArduinoTerminalSettingsPage_DataSize=Data Size:
ArduinoTerminalSettingsPage_Parity=Parity:
ArduinoTerminalSettingsPage_StopBits=Stop Bits:
ArduinoTerminalSettingsPage_UnknownPort=Unknown port

View file

@ -0,0 +1,104 @@
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.cdt.arduino.ui.internal.terminal;
import java.util.Map;
import org.eclipse.cdt.serial.BaudRate;
import org.eclipse.cdt.serial.ByteSize;
import org.eclipse.cdt.serial.Parity;
import org.eclipse.cdt.serial.StopBits;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.tm.terminal.connector.cdtserial.connector.SerialSettings;
import org.eclipse.tm.terminal.view.core.interfaces.constants.ITerminalsConnectorConstants;
import org.eclipse.tm.terminal.view.ui.interfaces.IConfigurationPanelContainer;
import org.eclipse.tm.terminal.view.ui.panels.AbstractExtendedConfigurationPanel;
public class ArduinoTerminalConfigPanel extends AbstractExtendedConfigurationPanel {
private ArduinoTerminalSettings settings;
private ArduinoTerminalSettingsPage page;
public ArduinoTerminalConfigPanel(IConfigurationPanelContainer container) {
super(container);
}
@Override
public void setupPanel(Composite parent) {
Composite panel = new Composite(parent, SWT.NONE);
panel.setLayout(new GridLayout());
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
panel.setLayoutData(data);
settings = new ArduinoTerminalSettings();
page = new ArduinoTerminalSettingsPage(settings, this);
page.createControl(panel);
createEncodingUI(panel, true);
setControl(panel);
}
@Override
public void extractData(Map<String, Object> data) {
if (data == null) {
return;
}
page.saveSettings();
data.put(ArduinoTerminalSettings.BOARD_ATTR, settings.getBoardName());
data.put(SerialSettings.PORT_NAME_ATTR, settings.getPortName());
data.put(SerialSettings.BAUD_RATE_ATTR, settings.getBaudRate());
data.put(SerialSettings.BYTE_SIZE_ATTR, settings.getByteSize());
data.put(SerialSettings.PARITY_ATTR, settings.getParity());
data.put(SerialSettings.STOP_BITS_ATTR, settings.getStopBits());
if (getEncoding() != null) {
data.put(ITerminalsConnectorConstants.PROP_ENCODING, getEncoding());
}
}
@Override
public void setupData(Map<String, Object> data) {
if (data == null) {
return;
}
settings.setBoardName((String) data.get(ArduinoTerminalSettings.BOARD_ATTR));
settings.setPortName((String) data.get(SerialSettings.PORT_NAME_ATTR));
settings.setBaudRate((BaudRate) data.get(SerialSettings.BAUD_RATE_ATTR));
settings.setByteSize((ByteSize) data.get(SerialSettings.BYTE_SIZE_ATTR));
settings.setParity((Parity) data.get(SerialSettings.PARITY_ATTR));
settings.setStopBits((StopBits) data.get(SerialSettings.STOP_BITS_ATTR));
String encoding = (String) data.get(ITerminalsConnectorConstants.PROP_ENCODING);
if (encoding != null) {
setEncoding(encoding);
}
}
@Override
protected void saveSettingsForHost(boolean add) {
}
@Override
protected void fillSettingsForHost(String host) {
}
@Override
protected String getHostFromSettings() {
if (page != null) {
page.saveSettings();
return settings.getPortName();
}
return null;
}
}

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.cdt.arduino.ui.internal.terminal;
import org.eclipse.tm.terminal.connector.cdtserial.launcher.SerialLauncherDelegate;
import org.eclipse.tm.terminal.view.ui.interfaces.IConfigurationPanel;
import org.eclipse.tm.terminal.view.ui.interfaces.IConfigurationPanelContainer;
import org.eclipse.tm.terminal.view.ui.interfaces.ILauncherDelegate;
public class ArduinoTerminalLauncher extends SerialLauncherDelegate implements ILauncherDelegate {
@Override
public IConfigurationPanel getPanel(IConfigurationPanelContainer container) {
return new ArduinoTerminalConfigPanel(container);
}
}

View file

@ -0,0 +1,34 @@
package org.eclipse.cdt.arduino.ui.internal.terminal;
import org.eclipse.tm.internal.terminal.provisional.api.ISettingsStore;
import org.eclipse.tm.terminal.connector.cdtserial.connector.SerialSettings;
public class ArduinoTerminalSettings extends SerialSettings {
public static final String BOARD_ATTR = "arduino.board"; //$NON-NLS-1$
private String boardName;
@Override
public void load(ISettingsStore store) {
super.load(store);
boardName = store.get(BOARD_ATTR);
}
@Override
public void save(ISettingsStore store) {
super.save(store);
store.put(BOARD_ATTR, boardName);
}
public String getBoardName() {
return boardName;
}
public void setBoardName(String boardName) {
this.boardName = boardName;
}
}

View file

@ -0,0 +1,288 @@
package org.eclipse.cdt.arduino.ui.internal.terminal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection;
import org.eclipse.cdt.arduino.ui.internal.Activator;
import org.eclipse.cdt.arduino.ui.internal.Messages;
import org.eclipse.cdt.serial.BaudRate;
import org.eclipse.cdt.serial.ByteSize;
import org.eclipse.cdt.serial.Parity;
import org.eclipse.cdt.serial.StopBits;
import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.remote.core.IRemoteConnection;
import org.eclipse.remote.core.IRemoteConnectionType;
import org.eclipse.remote.core.IRemoteServicesManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.tm.internal.terminal.provisional.api.AbstractSettingsPage;
import org.eclipse.tm.terminal.connector.cdtserial.connector.SerialSettings;
import org.eclipse.tm.terminal.view.ui.interfaces.IConfigurationPanel;
import org.eclipse.tm.terminal.view.ui.interfaces.IConfigurationPanelContainer;
public class ArduinoTerminalSettingsPage extends AbstractSettingsPage {
private final ArduinoTerminalSettings settings;
private final IConfigurationPanel panel;
private final IDialogSettings dialogSettings;
private Combo boardCombo;
private Label portNameLabel;
private Combo baudRateCombo;
private Combo byteSizeCombo;
private Combo parityCombo;
private Combo stopBitsCombo;
private String boardName;
private String portName;
private BaudRate baudRate;
private ByteSize byteSize;
private Parity parity;
private StopBits stopBits;
private IRemoteConnectionType arduinoType;
public ArduinoTerminalSettingsPage(ArduinoTerminalSettings settings, IConfigurationPanel panel) {
this.settings = settings;
this.panel = panel;
setHasControlDecoration(true);
dialogSettings = DialogSettings.getOrCreateSection(Activator.getDefault().getDialogSettings(),
this.getClass().getSimpleName());
boardName = dialogSettings.get(ArduinoTerminalSettings.BOARD_ATTR);
portName = dialogSettings.get(SerialSettings.PORT_NAME_ATTR);
String baudRateStr = dialogSettings.get(SerialSettings.BAUD_RATE_ATTR);
if (baudRateStr == null || baudRateStr.isEmpty()) {
baudRate = BaudRate.getDefault();
} else {
String[] rates = BaudRate.getStrings();
for (int i = 0; i < rates.length; ++i) {
if (baudRateStr.equals(rates[i])) {
baudRate = BaudRate.fromStringIndex(i);
break;
}
}
}
String byteSizeStr = dialogSettings.get(SerialSettings.BYTE_SIZE_ATTR);
if (byteSizeStr == null || byteSizeStr.isEmpty()) {
byteSize = ByteSize.getDefault();
} else {
String[] sizes = ByteSize.getStrings();
for (int i = 0; i < sizes.length; ++i) {
if (byteSizeStr.equals(sizes[i])) {
byteSize = ByteSize.fromStringIndex(i);
break;
}
}
}
String parityStr = dialogSettings.get(SerialSettings.PARITY_ATTR);
if (parityStr == null || parityStr.isEmpty()) {
parity = Parity.getDefault();
} else {
String[] parities = Parity.getStrings();
for (int i = 0; i < parities.length; ++i) {
if (parityStr.equals(parities[i])) {
parity = Parity.fromStringIndex(i);
break;
}
}
}
String stopBitsStr = dialogSettings.get(SerialSettings.STOP_BITS_ATTR);
if (stopBitsStr == null || stopBitsStr.isEmpty()) {
stopBits = StopBits.getDefault();
} else {
String[] bits = StopBits.getStrings();
for (int i = 0; i < bits.length; ++i) {
if (stopBitsStr.equals(bits[i])) {
stopBits = StopBits.fromStringIndex(i);
break;
}
}
}
}
@Override
public void createControl(Composite parent) {
Composite comp = new Composite(parent, SWT.NONE);
GridLayout gridLayout = new GridLayout(2, false);
gridLayout.marginWidth = gridLayout.marginHeight = 0;
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
comp.setLayout(gridLayout);
comp.setLayoutData(gridData);
Label boardLabel = new Label(comp, SWT.NONE);
boardLabel.setText(Messages.ArduinoTerminalSettingsPage_BoardName);
boardCombo = new Combo(comp, SWT.READ_ONLY);
boardCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
IRemoteServicesManager manager = Activator.getService(IRemoteServicesManager.class);
arduinoType = manager.getConnectionType(ArduinoRemoteConnection.TYPE_ID);
List<IRemoteConnection> connections = new ArrayList<>(arduinoType.getConnections());
Collections.sort(connections, (o1, o2) -> {
return o1.getName().compareToIgnoreCase(o2.getName());
});
for (IRemoteConnection connection : connections) {
boardCombo.add(connection.getName());
}
boardCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
validate();
updatePortLabel();
}
});
Label portLabel = new Label(comp, SWT.NONE);
portLabel.setText(Messages.ArduinoTerminalSettingsPage_SerialPort);
portNameLabel = new Label(comp, SWT.NONE);
portNameLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Label baudRateLabel = new Label(comp, SWT.NONE);
baudRateLabel.setText(Messages.ArduinoTerminalSettingsPage_BaudRate);
baudRateCombo = new Combo(comp, SWT.READ_ONLY);
baudRateCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
for (String baudRateStr : BaudRate.getStrings()) {
baudRateCombo.add(baudRateStr);
}
Label byteSizeLabel = new Label(comp, SWT.NONE);
byteSizeLabel.setText(Messages.ArduinoTerminalSettingsPage_DataSize);
byteSizeCombo = new Combo(comp, SWT.READ_ONLY);
byteSizeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
for (String byteSizeStr : ByteSize.getStrings()) {
byteSizeCombo.add(byteSizeStr);
}
Label parityLabel = new Label(comp, SWT.NONE);
parityLabel.setText(Messages.ArduinoTerminalSettingsPage_Parity);
parityCombo = new Combo(comp, SWT.READ_ONLY);
parityCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
for (String parityStr : Parity.getStrings()) {
parityCombo.add(parityStr);
}
Label stopBitsLabel = new Label(comp, SWT.NONE);
stopBitsLabel.setText(Messages.ArduinoTerminalSettingsPage_StopBits);
stopBitsCombo = new Combo(comp, SWT.READ_ONLY);
stopBitsCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
for (String stopBitsStr : StopBits.getStrings()) {
stopBitsCombo.add(stopBitsStr);
}
loadSettings();
}
void validate() {
IConfigurationPanelContainer container = panel.getContainer();
container.validate();
}
void updatePortLabel() {
String boardName = boardCombo.getItem(boardCombo.getSelectionIndex());
IRemoteConnection connection = arduinoType.getConnection(boardName);
if (connection != null) {
ArduinoRemoteConnection board = connection.getService(ArduinoRemoteConnection.class);
portName = board.getPortName();
portNameLabel.setText(portName);
} else {
portName = null;
portNameLabel.setText(Messages.ArduinoTerminalSettingsPage_UnknownPort);
}
}
@Override
public void loadSettings() {
String boardName = settings.getBoardName();
if (boardName == null || boardName.isEmpty()) {
boardName = this.boardName;
}
if (boardName != null && !boardName.isEmpty()) {
int i = 0;
for (String name : boardCombo.getItems()) {
if (boardName.equals(name)) {
boardCombo.select(i);
break;
}
i++;
}
} else if (boardCombo.getItemCount() > 0) {
boardCombo.select(0);
}
updatePortLabel();
BaudRate baudRate = settings.getBaudRate();
if (baudRate == null) {
baudRate = this.baudRate;
}
baudRateCombo.select(BaudRate.getStringIndex(baudRate));
ByteSize byteSize = settings.getByteSize();
if (byteSize == null) {
byteSize = this.byteSize;
}
byteSizeCombo.select(ByteSize.getStringIndex(byteSize));
Parity parity = settings.getParity();
if (parity == null) {
parity = this.parity;
}
parityCombo.select(Parity.getStringIndex(parity));
StopBits stopBits = settings.getStopBits();
if (stopBits == null) {
stopBits = this.stopBits;
}
stopBitsCombo.select(StopBits.getStringIndex(stopBits));
}
@Override
public void saveSettings() {
settings.setBoardName(boardCombo.getItem(boardCombo.getSelectionIndex()));
settings.setPortName(portNameLabel.getText());
settings.setBaudRate(BaudRate.fromStringIndex(baudRateCombo.getSelectionIndex()));
settings.setByteSize(ByteSize.fromStringIndex(byteSizeCombo.getSelectionIndex()));
settings.setParity(Parity.fromStringIndex(parityCombo.getSelectionIndex()));
settings.setStopBits(StopBits.fromStringIndex(stopBitsCombo.getSelectionIndex()));
dialogSettings.put(ArduinoTerminalSettings.BOARD_ATTR, boardCombo.getItem(boardCombo.getSelectionIndex()));
dialogSettings.put(SerialSettings.PORT_NAME_ATTR, portNameLabel.getText());
dialogSettings.put(SerialSettings.BAUD_RATE_ATTR,
BaudRate.getStrings()[baudRateCombo.getSelectionIndex()]);
dialogSettings.put(SerialSettings.BYTE_SIZE_ATTR,
ByteSize.getStrings()[byteSizeCombo.getSelectionIndex()]);
dialogSettings.put(SerialSettings.PARITY_ATTR, Parity.getStrings()[parityCombo.getSelectionIndex()]);
dialogSettings.put(SerialSettings.STOP_BITS_ATTR,
StopBits.getStrings()[stopBitsCombo.getSelectionIndex()]);
}
@Override
public boolean validateSettings() {
if (boardCombo.getSelectionIndex() < 0 && boardCombo.getText().isEmpty()) {
return false;
}
return true;
}
}