Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,11 @@
"title": "Telnet",
"category": "PyMakr"
},
{
"command": "pymakr.newDeviceWS",
"title": "WebSocket",
"category": "PyMakr"
},
{
"command": "pymakr.setVisibleDevices",
"title": "Set visible devices",
Expand Down Expand Up @@ -559,12 +564,6 @@
"title": "Select devices",
"category": "PyMakr"
},
{
"command": "pymakr.removeDeviceFromProject",
"title": "Remove device from project",
"shortTitle": "Remove device",
"category": "PyMakr"
},
{
"command": "pymakr.uploadPrompt",
"title": "Upload to device",
Expand Down Expand Up @@ -710,6 +709,10 @@
"command": "pymakr.newDeviceTelnet",
"when": "false"
},
{
"command": "pymakr.newDeviceWS",
"when": "false"
},
{
"command": "pymakr.setVisibleDevices",
"when": "false"
Expand All @@ -730,10 +733,6 @@
"command": "pymakr.selectDevicesForProjectPrompt",
"when": "false"
},
{
"command": "pymakr.removeDeviceFromProject",
"when": "false"
},
{
"command": "pymakr.uploadPrompt",
"when": "false"
Expand All @@ -757,6 +756,9 @@
},
{
"command": "pymakr.newDeviceTelnet"
},
{
"command": "pymakr.newDeviceWS"
}
],
"pymakr.projectMenu": [
Expand Down Expand Up @@ -791,11 +793,6 @@
"command": "pymakr.disconnect",
"group": "1-primary"
},
{
"command": "pymakr.removeDeviceFromProject",
"when": "viewItem =~ /.+#project#device/",
"group": "4-config"
},
{
"command": "pymakr.eraseDevicePrompt",
"group": "4-config"
Expand Down
22 changes: 16 additions & 6 deletions src/Device.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ class Device {
}

get serialized() {
return serializeKeyValuePairs(this.raw);
// raw is set only for Serial connected devices
return (this.raw === undefined) ? '' : serializeKeyValuePairs(this.raw);
}

/** the full device name using the naming template */
Expand Down Expand Up @@ -272,7 +273,7 @@ class Device {

// We need to wrap the rawAdapter in a blocking proxy to make sure commands
// run in sequence rather in in parallel. See JSDoc comment for more info.
const adapter = createBlockingProxy(rawAdapter, { exceptions: ["sendData", "connectSerial", "getState"] });
const adapter = createBlockingProxy(rawAdapter, { exceptions: ["sendData", "connectSerial", "connectNetwork", "getState"] });
adapter.__proxyMeta.beforeEachCall(({ item }) => {
this.action.set(item.field.toString());
this.busy.set(true);
Expand Down Expand Up @@ -343,7 +344,7 @@ class Device {
const reconnectIntervals = [0, 5, 500, 1000];
while (reconnectIntervals.length) {
try {
await this._connectSerial();
await this._connect();
this.connected.set(true);
resolve(this._onConnectedHandler());
return this.__connectingPromise;
Expand Down Expand Up @@ -424,9 +425,18 @@ class Device {
}

/** @private */
async _connectSerial() {
const connectPromise = this.adapter.connectSerial(this.address, this.config.adapterOptions);
await waitFor(connectPromise, 2000, "Timed out while connecting.");
async _connect() {
if (this.protocol == "serial") {
const connectPromise = this.adapter.connectSerial(this.address, this.config.adapterOptions);
await waitFor(connectPromise, 2000, "Timed out while connecting.");
} else if (this.protocol == "ws") {
const connectPromise = this.adapter.connectNetwork(this.address, this.password);
await waitFor(connectPromise, 10000, "Timed out while connecting.");
} else if (this.protocol == "telnet") {
// TODO: not handled
} else {
// unknown protocol
}
}

async disconnect() {
Expand Down
11 changes: 9 additions & 2 deletions src/PyMakr.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,13 @@ class PyMakr {
}

getTerminalProfile(protocol, address) {
const hasNode = () => require("child_process").execSync("node -v").toString().startsWith("v");
const hasNode = () => {
try {
return require("child_process").execSync("node -v", {}).toString().startsWith("v");
} catch (err) {
this.log.info("Node not found. Using prebuild binaries");
}
};

const binariesPath = resolve(__dirname, "terminal/bin");
const userSelection = this.config.get().get("terminalProfile");
Expand Down Expand Up @@ -153,6 +159,7 @@ class PyMakr {
}),
vscode.workspace.registerFileSystemProvider("serial", this.fileSystemProvider, { isCaseSensitive: true }),
// vscode.workspace.registerFileSystemProvider("telnet", this.fileSystemProvider, { isCaseSensitive: true }),
vscode.workspace.registerFileSystemProvider("ws", this.fileSystemProvider, { isCaseSensitive: true }),
vscode.window.registerTreeDataProvider("pymakr-projects-tree", this.projectsProvider),
vscode.window.registerTreeDataProvider("pymakr-devices-tree", this.devicesProvider),
vscode.workspace.registerTextDocumentContentProvider("pymakrDocument", this.textDocumentProvider),
Expand Down Expand Up @@ -182,7 +189,7 @@ class PyMakr {
* Registers usb devices and scans for projects in workspace
*/
async setup() {
await Promise.all([this.devicesStore.registerUSBDevices(), this.registerProjects()]);
await Promise.all([this.devicesStore.registerUSBDevices(), this.devicesStore.registerWSDevices(), this.registerProjects()]);
this.projectsProvider.refresh(); // tell the provider that projects were updated
this.context.subscriptions.push(coerceDisposable(this.devicesStore.watchUSBDevices()));
}
Expand Down
29 changes: 28 additions & 1 deletion src/commands/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ class Commands {
* @param {{device: Device}} param0
*/
"debug.showDeviceSummary": async ({ device }) => {
let uri = vscode.Uri.parse("pymakrDocument:" + "Pymakr: device summary - " + device.raw.path);
let path;
if (device.protocol === "serial") {
path = device.raw.path;
} else {
path = device.id;
}
let uri = vscode.Uri.parse("pymakrDocument:" + "Pymakr: device summary - " + path);
this.pymakr.textDocumentProvider.onDidChangeEmitter.fire(uri);
vscode.commands.executeCommand("markdown.showPreview", uri);
},
Expand Down Expand Up @@ -591,6 +597,27 @@ class Commands {
this.pymakr.devicesStore.upsert({ address, protocol, name, username, password });
},

/**
* Not currently in supported
*/
newDeviceWS: async () => {
const address = await vscode.window.showInputBox({
placeHolder: "192.168.0.x",
prompt: "Hostname or IP of your device",
});
const password = await vscode.window.showInputBox({
password: true,
prompt: "Password for your device [default: python]",
value: "python",
});
const name = await vscode.window.showInputBox({
value: `ws://${address}`,
prompt: "Name of your device",
});
const protocol = "ws";
this.pymakr.devicesStore.upsert({ address, protocol, name, password });
},

/**
* Create a serial device manually
*/
Expand Down
9 changes: 7 additions & 2 deletions src/providers/TextDocumentProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,15 @@ class TextDocumentProvider {
match: /device summary - (.+)/,
body: (_all, path) => {
const GithubMaxLengthUri = 8170; //8182 to be exact
const device = this.pymakr.devicesStore.get().find((device) => device.raw.path === path);
const device = this.pymakr.devicesStore.get().find((device) => device.raw?.path === path || device.id === path);
const config = { ...device.config, password: "***", username: "***" };
const configTable = arraysToMarkdownTable([["Config", ""], ...Object.entries(config || {})]);
const deviceTable = arraysToMarkdownTable([["Device", ""], ...Object.entries(device.raw || {})]);
let deviceTable;
if (device.protocol === "serial") {
deviceTable = arraysToMarkdownTable([["Device", ""], ...Object.entries(device.raw || {})]);
} else {
deviceTable = arraysToMarkdownTable([["Device", ""], ["protocol", device.protocol]]);
}
const systemTable = arraysToMarkdownTable([["System", ""], ...Object.entries(device.info || {})]);
const hostTable = arraysToMarkdownTable([
["Host", ""],
Expand Down
25 changes: 25 additions & 0 deletions src/stores/devices.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ const rawSerialToDeviceInput = (raw) => ({
raw,
});

/**
* converts configuration's websocket DeviceInput into a DeviceInput
* @param {String} id
* @param {DeviceInput} diConf
* @returns {DeviceInput}
*/
const wsConfigToDeviceInput = (id, diConf) => {
const address = id.substring('ws://'.length);
const protocol = "ws";
const name = diConf.name == undefined || diConf.name === '' ? id : diConf.name;
const password = diConf.password;
return { address, protocol, name, password, id };
};


/**
* @param {DeviceInput} device
* @returns {string}
Expand Down Expand Up @@ -77,6 +92,15 @@ const createDevicesStore = (pymakr) => {
});
};

const registerWSDevices = async () => {
pymakr.log.trace("register WS devices");
const deviceConfigs = pymakr.config.get().get("devices").configs;
const deviceInputs = Object.keys(deviceConfigs)
.filter(k => k.startsWith('ws://')) // register only ws protocol
.map(k => wsConfigToDeviceInput(k, deviceConfigs[k]));
upsert(deviceInputs);
};

/** @type {NodeJS.Timer} */
let watchIntervalHandle;
const watchUSBDevices = () => {
Expand All @@ -96,6 +120,7 @@ const createDevicesStore = (pymakr) => {
getAllById,
upsert,
remove,
registerWSDevices,
registerUSBDevices,
watchUSBDevices,
stopWatchingUSBDevices: () => clearInterval(watchIntervalHandle),
Expand Down
8 changes: 7 additions & 1 deletion src/terminal/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ class Server {
// listen to keystrokes from client
socket.on("data", (data) => {
this.log.debug("received", data.toString(), data[0]);
device.adapter.sendData(data);
if (device.protocol === "ws") {
// Terminal data should be sent as string for WS protocol
// As it is specified in webrepl README Terminal Protocol
device.adapter.sendData(data.toString());
} else {
device.adapter.sendData(data);
}
// make sure device data is sent to the last active terminal
device.__onTerminalDataExclusive = (data) => socket.write(data);
});
Expand Down
2 changes: 1 addition & 1 deletion types/typedef.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
/**
* @typedef {Object} DeviceInput
* @prop {string} name
* @prop {'serial'|'telnet'} protocol
* @prop {'serial'|'telnet'|'ws'} protocol
* @prop {string} address
* @prop {string=} username
* @prop {string=} password
Expand Down