Skip to content
This repository was archived by the owner on Oct 1, 2024. It is now read-only.

Serial Plotter #470

Open
wants to merge 47 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
49e3148
add simple serial plotter
nd0ut Feb 21, 2018
cf4f13a
Merge remote-tracking branch 'microsoft/master' into feature/serial-p…
nd0ut Sep 30, 2018
e5bae20
fix buffer by line splitting
nd0ut Sep 30, 2018
42189c6
refactor
nd0ut Sep 30, 2018
6ba7cda
improve performance
nd0ut Sep 30, 2018
c9a9d5b
add refresh rate input
nd0ut Sep 30, 2018
6f07b89
start monitor if not started
nd0ut Sep 30, 2018
2cec6d5
allow to update plot refresh rate from UI
nd0ut Sep 30, 2018
52c3eab
add reset and play/pause controls
nd0ut Sep 30, 2018
644cb58
fix current frame merging
nd0ut Sep 30, 2018
57fe335
fix linting
nd0ut Sep 30, 2018
6059f26
add new command to tests
nd0ut Oct 1, 2018
7d18b04
Merge branch 'master' into feature/serial-plotter
nd0ut Oct 10, 2018
0ca41fa
Merge remote-tracking branch 'microsoft/master' into feature/serial-p…
nd0ut Jan 14, 2019
51a678b
replace deprecated `previewHtml` with webview api
nd0ut Jan 14, 2019
0c1ae8a
add `plotRegex` setting to specify custom regex to parse serial output
nd0ut Jan 14, 2019
9965bc3
add command to open serial plotter
nd0ut Jan 14, 2019
35c939c
add $ to the end of plot regex in the package.json
nd0ut Jan 14, 2019
ca204e2
update readme
nd0ut Jan 14, 2019
e35f71b
use vscode `postMessage` instead of wss server
nd0ut Jan 14, 2019
d56fa34
refactor code
nd0ut Jan 16, 2019
a180542
fix message proxy
nd0ut Jan 16, 2019
d4fad26
styling
nd0ut Jan 16, 2019
2fa5908
fix typo
nd0ut Jan 16, 2019
4916f26
update readme
nd0ut Jan 16, 2019
611f41a
remove extra new lines at readme
nd0ut Jan 16, 2019
10ccbfc
rename `plotRegex` to `plotterRegex`
nd0ut Jan 16, 2019
f74ec47
remove unneeded `ws` package
nd0ut Jan 16, 2019
8314902
refactor
nd0ut Jan 16, 2019
8e4d1ca
remove unneeded `prop-types` package
nd0ut Jan 16, 2019
036be64
revert back empty dependencies at package.json
nd0ut Jan 16, 2019
11218af
update readme
nd0ut Jan 17, 2019
2f319e1
use dygraphs instead of highcharts
nd0ut Jan 22, 2019
41ba027
Merge branch 'master' into feature/serial-plotter
nd0ut Jan 22, 2019
58dcea4
Merge branch 'master' into feature/serial-plotter
nd0ut Mar 9, 2019
209ad3f
Merge branch 'master' into feature/serial-plotter
nd0ut May 24, 2019
5fb99b2
Merge branch 'master' into feature/serial-plotter
nd0ut May 29, 2019
6c318d4
fix arduino commands test
nd0ut May 30, 2019
b987abb
fix react component props type
nd0ut May 30, 2019
ecb92bf
Merge branch 'master' into feature/serial-plotter
nd0ut May 31, 2019
fdf9142
Merge branch 'master' into feature/serial-plotter
nd0ut Jul 21, 2019
86a9e48
remove highcharts from deps
nd0ut Jul 21, 2019
a5d044c
Merge branch 'master' into feature/serial-plotter
nd0ut Aug 26, 2019
03fcbd7
Merge branch 'dev' into feature/serial-plotter
adiazulay Aug 30, 2021
c60ad73
fix merge conflict issues
adiazulay Aug 31, 2021
e492275
fix linting errors
adiazulay Aug 31, 2021
5a6ebe4
Merge branch 'dev' into feature/serial-plotter
benmcmorran Jan 10, 2022
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
43 changes: 42 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ This extension provides several commands in the Command Palette (<kbd>F1</kbd> o
- **Arduino: Initialize**: Scaffold a VS Code project with an Arduino sketch.
- **Arduino: Library Manager**: Explore and manage libraries.
- **Arduino: Open Serial Monitor**: Open the serial monitor in the integrated output window.
- **Arduino: Open Serial Plotter**: Open the serial plotter.
- **Arduino: Select Serial Port**: Change the current serial port.
- **Arduino: Send Text to Serial Port**: Send a line of text via the current serial port.
- **Arduino: Upload**: Build sketch and upload to Arduino board.
Expand Down Expand Up @@ -97,7 +98,8 @@ The following Visual Studio Code settings are available for the Arduino extensio
"https://raw.githubusercontent.com/VSChina/azureiotdevkit_tools/master/package_azureboard_index.json",
"http://arduino.esp8266.com/stable/package_esp8266com_index.json"
],
"arduino.defaultBaudRate": 115200
"arduino.defaultBaudRate": 115200,
"arduino.plotterRegex": "^PLOT\\[(\\d+)\\]\\[(.+?)=(.+?)\\]$",
}
```
*Note:* You only need to set `arduino.path` in Visual Studio Code settings, other options are not required.
Expand Down Expand Up @@ -203,6 +205,45 @@ Steps to start debugging:

> To learn more about how to debug Arduino code, visit our [team blog](https://blogs.msdn.microsoft.com/iotdev/2017/05/27/debug-your-arduino-code-with-visual-studio-code/).

## Using Serial Plotter

You can start Serial Plotter by calling `Arduino: Open Serial Plotter` from Command Pallete.

By default, it looks for lines of the following format in the serial input: `PLOT[time][variable=value]`

For example, `PLOT[1234][cos=0.5]` means that we have variable named `cos` with it's value `0.5` at the time `1234`.

You can use snippet below to print variables in such format.

```c
void plot(String name, float value)
{
String time = String(millis());
Serial.println("PLOT[" + time + "][" + name + "=" + value + "]");
}
```

### Throttling (refresh rate)

This Plotter is not working in real time. It's built on top of web technologies
with [dygraphs](http://dygraphs.com/) library to create interactive chart, so it's pretty fast but not instant.

Plotter accumulates data and flushes it to the chart with some periodicity that we will call `throttling` or `refresh rate`. By default it's 100ms, but you can change it as you want. This value was chosen empirically, lower values ​​can lead to noticable lags.

### Time window

Data is recorded for a specified period of time called `Time window`. By default it's 20 seconds and you can also change it in the way you need. The greater the value, the more resources are required to render chart, and the more lags we have.

### Override log format

You can override default regex to specify your own format, but the order will be remain the same: time, variable name, variable value.

```json
{
"arduino.plotterRegex": "^(\\d+):(.+?)=(.+?)$"
}
```

## Change Log
See the [Change log](https://github.com/Microsoft/vscode-arduino/blob/master/CHANGELOG.md) for details about the changes in each version.

Expand Down
11 changes: 8 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"onCommand:arduino.showLibraryManager",
"onCommand:arduino.showExamples",
"onCommand:arduino.initialize",
"onCommand:arduino.openSerialPlotter",
"onDebug"
],
"main": "./out/src/extension",
Expand Down Expand Up @@ -159,6 +160,10 @@
{
"command": "arduino.showExamples",
"title": "Arduino: Examples"
},
{
"command": "arduino.openSerialPlotter",
"title": "Arduino: Open Serial Plotter"
}
],
"menus": {
Expand Down Expand Up @@ -527,6 +532,10 @@
"type": "number",
"default": 115200
},
"arduino.plotterRegex": {
"type": "string",
"default": "^PLOT\\[(\\d+)\\]\\[(.+?)=(.+?)\\]$"
},
"arduino.disableIntelliSenseAutoGen": {
"type": "boolean",
"default": false,
Expand Down Expand Up @@ -631,6 +640,7 @@
"extract-zip": "^2.0.1",
"glob": "^7.1.1",
"iconv-lite": "^0.4.18",
"lodash.throttle": "^4.1.1",
"impor": "^0.1.1",
"node-usb-native": "^0.0.20",
"properties": "^1.2.1",
Expand Down
39 changes: 38 additions & 1 deletion src/arduino/arduinoContentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import * as vscode from "vscode";
import ArduinoActivator from "../arduinoActivator";
import ArduinoContext from "../arduinoContext";
import * as Constants from "../common/constants";
import { SERIAL_PLOTTER_URI } from "../common/constants";
import * as JSONHelper from "../common/cycle";
import { DeviceContext } from "../deviceContext";
import * as Logger from "../logger/logger";
import { SerialMonitor } from "../serialmonitor/serialMonitor";
import LocalWebServer from "./localWebServer";

export class ArduinoContentProvider implements vscode.TextDocumentContentProvider {
Expand Down Expand Up @@ -47,7 +49,12 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide
this.addHandlerWithLogger("load-examples", "/api/examples", async (req, res) => await this.getExamples(req, res));
this.addHandlerWithLogger("open-example", "/api/openexample", (req, res) => this.openExample(req, res), true);

// Arduino Serial Plotter
this.addHandlerWithLogger("show-serialplotter", "/serialplotter", (req, res) => this.getHtmlView(req, res));
this.addHandlerWithLogger("updateplotrate", "/api/updateplotrate", (req, res) => this.updatePlotRefreshRate(req, res), true);

await this._webserver.start();

}

public async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
Expand All @@ -63,6 +70,8 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide
type = "boardConfig";
} else if (uri.toString() === Constants.EXAMPLES_URI.toString()) {
type = "examples";
} else if (uri.toString() === Constants.SERIAL_PLOTTER_URI.toString()) {
type = "serialplotter";
}

const timeNow = new Date().getTime();
Expand All @@ -81,7 +90,17 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide
"theme=" + encodeURIComponent(theme.trim()) +
"&backgroundcolor=" + encodeURIComponent(backgroundcolor.trim()) +
"&color=" + encodeURIComponent(color.trim());
document.getElementById('frame').src = url;

var iframe = document.getElementById('frame');

iframe.onload = function() {
window.addEventListener('message', msg => {
var data = msg.data;
iframe.contentWindow.postMessage(data, url);
})
}

iframe.src = url;
};
</script>
</head>
Expand Down Expand Up @@ -291,6 +310,24 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide
}
}

public updatePlotRefreshRate(req, res) {
if (!req.body.rate) {
return res.status(400).send("BAD Request! Missing parameters!");
} else {
try {
const serialMonitor = SerialMonitor.getInstance();

serialMonitor.serialPlotter.setThrottling(req.body.rate);

return res.json({
status: "OK",
});
} catch (error) {
return res.status(500).send(`Update plot refresh rate failed with message "code:${error.code}, err:${error.stderr}"`);
}
}
}

private addHandlerWithLogger(handlerName: string, url: string, handler: (req, res) => void, post: boolean = false): void {
const wrappedHandler = async (req, res) => {
const guid = Uuid().replace(/-/g, "");
Expand Down
8 changes: 8 additions & 0 deletions src/arduino/vscodeSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ const configKeys = {
IGNORE_BOARDS: "arduino.ignoreBoards",
SKIP_HEADER_PROVIDER: "arduino.skipHeaderProvider",
DEFAULT_BAUD_RATE: "arduino.defaultBaudRate",
PLOTTER_REGEX: "arduino.plotterRegex",
USE_ARDUINO_CLI: "arduino.useArduinoCli",
DISABLE_INTELLISENSE_AUTO_GEN: "arduino.disableIntelliSenseAutoGen",

};

export interface IVscodeSettings {
Expand All @@ -32,6 +34,7 @@ export interface IVscodeSettings {
ignoreBoards: string[];
skipHeaderProvider: boolean;
defaultBaudRate: number;
plotterRegex: string;
useArduinoCli: boolean;
disableIntelliSenseAutoGen: boolean;
updateAdditionalUrls(urls: string | string[]): void;
Expand Down Expand Up @@ -101,8 +104,13 @@ export class VscodeSettings implements IVscodeSettings {
return this.getConfigValue<boolean>(configKeys.SKIP_HEADER_PROVIDER);
}

public get plotterRegex(): string {
return this.getConfigValue<string>(configKeys.PLOTTER_REGEX);
}

public get disableIntelliSenseAutoGen(): boolean {
return this.getConfigValue<boolean>(configKeys.DISABLE_INTELLISENSE_AUTO_GEN);

}

public async updateAdditionalUrls(value) {
Expand Down
2 changes: 2 additions & 0 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const BOARD_MANAGER_URI = vscode.Uri.parse("arduino-manager://arduino/ard
export const LIBRARY_MANAGER_URI = vscode.Uri.parse("arduino-manager://arduino/arduino-librariesmanager");
export const BOARD_CONFIG_URI = vscode.Uri.parse("arduino-manager://arduino/arduino-config");
export const EXAMPLES_URI = vscode.Uri.parse("arduino-manager://arduino/arduino-examples");
export const SERIAL_PLOTTER_URI = vscode.Uri.parse("arduino-manager://arduino/arduino-serialplotter");

export const messages = {
ARDUINO_FILE_ERROR: "The arduino.json file format is not correct.",
Expand All @@ -43,6 +44,7 @@ export const statusBarPriority = {
PORT: 20,
OPEN_PORT: 30,
BAUD_RATE: 40,
OPEN_SERIAL_PLOTTER: 50,
BOARD: 60,
ENDING: 70,
SKETCH: 80,
Expand Down
14 changes: 12 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const arduinoActivatorModule = impor("./arduinoActivator") as typeof import ("./
const arduinoContextModule = impor("./arduinoContext") as typeof import ("./arduinoContext");
import {
ARDUINO_CONFIG_FILE, ARDUINO_MANAGER_PROTOCOL, ARDUINO_MODE, BOARD_CONFIG_URI, BOARD_MANAGER_URI, EXAMPLES_URI,
LIBRARY_MANAGER_URI,
LIBRARY_MANAGER_URI, SERIAL_PLOTTER_URI,
} from "./common/constants";
import { validateArduinoPath } from "./common/platform";
import * as util from "./common/util";
Expand All @@ -29,8 +29,11 @@ const nsatModule =
impor("./nsat") as typeof import ("./nsat");
import { BuildMode } from "./arduino/arduino";
import { SerialMonitor } from "./serialmonitor/serialMonitor";
import { SerialPlotterPanel } from "./serialmonitor/serialPlotterPanel";
const usbDetectorModule = impor("./serialmonitor/usbDetector") as typeof import ("./serialmonitor/usbDetector");

const status: any = {};

export async function activate(context: vscode.ExtensionContext) {
Logger.configure(context);
const activeGuid = uuidModule().replace(/-/g, "");
Expand Down Expand Up @@ -129,7 +132,6 @@ export async function activate(context: vscode.ExtensionContext) {
arduinoContextModule.default.boardManager.currentBoard.name,
};
});

registerArduinoCommand("arduino.upload", async () => {
if (!arduinoContextModule.default.arduinoApp.building) {
await vscode.window.withProgress({
Expand Down Expand Up @@ -281,8 +283,10 @@ export async function activate(context: vscode.ExtensionContext) {
// serial monitor commands
const serialMonitor = SerialMonitor.getInstance();
context.subscriptions.push(serialMonitor);

registerNonArduinoCommand("arduino.selectSerialPort", () => serialMonitor.selectSerialPort(null, null));
registerNonArduinoCommand("arduino.openSerialMonitor", () => serialMonitor.openSerialMonitor());
registerNonArduinoCommand("arduino.openSerialPlotter", () => serialMonitor.openSerialPlotter());
registerNonArduinoCommand("arduino.changeBaudRate", () => serialMonitor.changeBaudRate());
registerNonArduinoCommand("arduino.sendMessageToSerialPort", () => serialMonitor.sendMessageToSerialPort());
registerNonArduinoCommand("arduino.closeSerialMonitor", (port, showWarning = true) => serialMonitor.closeSerialMonitor(port, showWarning));
Expand Down Expand Up @@ -406,6 +410,12 @@ export async function activate(context: vscode.ExtensionContext) {
arduinoContextModule.default.boardManager.currentBoard.name,
};
});
registerArduinoCommand("arduino.showSerialPlotter", async () => {
const html = await arduinoManagerProvider.provideTextDocumentContent(SERIAL_PLOTTER_URI);
const serialPlotter = SerialMonitor.getInstance().serialPlotter;

SerialPlotterPanel.createOrShow({serialPlotter, html});
});
}, 100);

setTimeout(() => {
Expand Down
Loading