Skip to content
/ spie Public

A compreensive serial monitor/plotter application using Electron, Node SerialPort and Ionic/Angular

License

Notifications You must be signed in to change notification settings

robsonos/spie

Repository files navigation

SPIE

Maintenance status GitHub Workflow Status (with event) GitHub License
GitHub Release version GitHub contributors from allcontributors.org

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, linux and macOS)
  • 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 workflows
  • 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 19.x.x
    ionic 8.x.x
    electron 33.3.x
    nx 20.2.2
    typescript 5.5.x

For a demo, check the sample binaries.

Index

Features

Connection


Sending Data


Terminal


Plotter


Auto update


Back to Index

Getting Started

Firstly, ensure the following are installed:

  • Node.js (preferably using nvm for version management)
  • NX CLI (npm install -g nx, or you can use npx nx ... if you prefer)

Steps

  1. Clone the repository:
git clone https://github.com/robsonos/spie
cd spie
  1. Install dependencies:
npm i
  1. Run the application:
nx run-many -t serve

Sample Arduino code

If 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.

Plotter

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

Back to Index

NX tasks

Learn more about NX in this Angular Monorepo tutorial. Here are the most commonly used NX tasks:

  • Serve the applications:
nx run-many -t serve

[NOTE] If you see a blank screen, that will be because spie finished building before spie-ui. You can reload the web application with either CTRL+R on the develop tool window or typing r followed by ENTER on the terminal window. Alternatively, you can run nx run spie-ui:serve first and then nx run spie:serve.

  • Lint the code:
nx run-many -t lint
  • Run unit tests:
nx run-many -t test
  • Run e2e tests:
nx run-many -t e2e
  • Build the applications (development):
nx run-many -t build
  • Build the applications (production):
nx run-many -t build --prod
  • Build and generate unpacked executables:

Warning

Build the applications first

nx run spie:package

Output files are located in dist\packages

  • Build and generate the executables:

Warning

Build the applications first

nx run spie:make

Output files are located in dist\executables

Back to Index

CI/CD workflows

There are many ways CD/CI 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 branch will trigger the CI workflow, which will test the code that changes since the last release, and display a summary of the the next release.
  • main: holds the code for the latest release. Pushes to this branch will trigger the CD workflow, which will create a new github release, a tag. New releases will then trigger the Binaries workflow to build and upload binaries the release.
  • If you need to maintain more release channels, form instance main is at v3.x.x and you need to support v1.x.x, I would recommend using a similar approach:
    • main for v3.x.x
    • main/v1 for v1.x.x
    • dev for v3.x.x development
    • dev/v1 for v1.x.x development
  • I may look into exemplifying the above and pre-releases in the feature

act

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.json

Sample event.json

{
  "action": "created",
  "release": {
    "name": "v1.0.0",
    "tag_name": "1.0.0"
  }
}

Back to Index

Troubleshooting

  • 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 every 5ms, 115200 baud rate and with show 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 use use readline parser to 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 plotter look off when using timestamp instead of sample count.
  • macOS application must be signed in order for auto updating to work. See electron-builder Auto Update for more details.

Back to Index

Contributors

Back to Index