This repository helps you quickly set up and develop your serial port communication project. Built with ElectronJS and a modern Ionic/Angular front-end, it uses an NX monorepo structure for efficient project management.
The repository provides:
- Core functionality of Arduino's Serial Monitor, enhanced with tools to configure, monitor, and communicate with serial devices
- Core functionality of Arduino's Serial Plotter, enhanced with tools to select, zoom, export and visualize data
- Cross-platform desktop application (
windows,linuxandmacOS) - Hot-reloading to accelerate development and testing cycles
- Enforced code linting and formatting
- Enforced conventional commits
- Streamlined workspace management and remote caching with NX
- CI/CD and Release pipelines with local testing
- Angular's signals and RxJS for reactivity and state management
- Unit testing examples
- E2E testing examples
- Automatic updates on new github releases (see limitations for more details)
- Modern tech stack:
Package version nodejs 22.x.x angular 20.x.x ionic 8.x.x electron 34.5.x nx 21.3.10 typescript 5.8.x
For a demo, check the sample binaries.
Firstly, ensure the following are installed:
- Node.js (preferably using
nvmfor version management) - NX CLI (
npm install -g nx, or you can usenpx nx ...if you prefer)
- Clone the repository:
git clone https://github.com/robsonos/spie
cd spie- Install dependencies:
npm i- Run the application:
npx nx run-many -t serveIf you want a minimalistic two way serial example, use the following:
#include <Arduino.h>
int period = 1000;
unsigned long time_now = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
if (Serial.available() > 0)
Serial.write(Serial.read());
if (millis() > time_now + period) {
time_now = millis();
Serial.print("Hello World ");
Serial.println(millis());
}
}For a example used on the plotter images, check out spie-firmware.
The Plotter expects a line feed LF (\n) to separate records. Ensure that there is a linebreak character after the last variable in each record.
You can use different delimiters to separate variables within a record: space ( ), tab (\t), or comma (,).
For labeled data, the plotter can interpret variables in the format <label>:<value>.
The Plotter supports parsing single and multiple variables in each record, handles duplicates for the same
variable label, and correctly groups the data under their respective labels.
Examples:
Single variable: 1\n, 2\n
Multiple variables: 1,2\n, 3,4\n
Multiple labeled variables: temp1:1,temp2:2\n, temp1:3,temp2:4\n
Learn more about NX in this Angular Monorepo tutorial. Here are the most commonly used NX tasks:
- Serve the applications:
npx nx run-many -t serve- Lint the code:
npx nx run-many -t lint- Run unit tests:
npx nx run-many -t test- Run e2e tests:
npx nx run-many -t e2e- Build the applications (development):
npx nx run-many -t build
- Build the applications (production):
npx nx run-many -t build --prod- Build and generate unpacked executables:
Warning
Build the applications first
npx nx run spie:packageOutput files are located in dist\packages
- Build and generate the executables:
Warning
Build the applications first
npx nx run spie:makeOutput files are located in dist\executables
There are many ways CD/CI/Release workflow can be implemented. I chose the most convenient one and here is how it is meant to work:
dev: holds the development code. Pushes to this will trigger theCI workflow, test your code, and create a PR to merge it intomain.main: holds the code for the latest release. Pushes to this will trigger theCD workflowand create a new github release and tag. You should never need to push commits tomain; usedevand create a PR instead. The code on this branch should always come from merges fromdev.- Once a new release is done, the
Releaseworkflow will be triggered to build and add the binaries to the release. - If you need to maintain more release channels, like
mainis atv3.x.xbut you need to supportv1.x.x, I would recommend using a similar approach:mainforv3.x.xmain/v1forv1.x.xdevforv3.x.xdevelopmentdev/v1forv1.x.xdevelopment
- I may look into exemplifying the above and
pre-releasesin the feature
You can use act to test workflows locally. Read more about act here. Also, check out .actrc
- CI
act push -W .github/workflows/ci.yml- CD
act push -W .github/workflows/cd.yml- Release
act release -W .github/workflows/release.yml -e event.jsonSample event.json
{
"action": "created",
"release": {
"name": "v1.0.0",
"tag_name": "1.0.0"
}
}- Serial data may be delivered in more than one
.on('data')event. This means data received by the serialport library might arrive in multiple packets. For details, see node-serialport/issues/659. This is not a problem in most cases, but unexpected behavior may occur if you are trying to monitor data at a fast rate. A good way to demonstrate the issues is to send data every5ms,115200baud rate and withshow timestamps. You will notice that every so often there is a "broken" message. If your data is terminated with a new line (\n) you can useuse readline parserto alleviate that. If you are developing your own application, I would recommend using one of the parsers available. - Depending on your operating system, the serial port ingestion may take a while, which could make the
plotterlook off when usingtimestampinstead ofsample count. macOSapplication must be signed in order for auto updating to work. See electron-builder Auto Update for more details.





