{"id":21672102,"url":"https://github.com/robsonos/spie","last_synced_at":"2025-10-06T01:57:52.308Z","repository":{"id":262635356,"uuid":"887033907","full_name":"robsonos/spie","owner":"robsonos","description":"A comprehensiveserial monitor/plotter application using Electron, Node SerialPort and Ionic/Angular","archived":false,"fork":false,"pushed_at":"2025-01-17T01:31:41.000Z","size":58429,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-25T23:11:54.803Z","etag":null,"topics":["angular","arduino","electronjs","ionic","serialport","uart"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robsonos.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-12T03:44:40.000Z","updated_at":"2025-02-21T01:14:01.000Z","dependencies_parsed_at":"2024-12-17T14:26:16.899Z","dependency_job_id":"7c47ce57-a5e8-4885-8f48-2593a539d9b7","html_url":"https://github.com/robsonos/spie","commit_stats":null,"previous_names":["robsonos/spie"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsonos%2Fspie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsonos%2Fspie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsonos%2Fspie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsonos%2Fspie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robsonos","download_url":"https://codeload.github.com/robsonos/spie/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248513205,"owners_count":21116771,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","arduino","electronjs","ionic","serialport","uart"],"created_at":"2024-11-25T13:17:14.597Z","updated_at":"2025-10-06T01:57:52.290Z","avatar_url":"https://github.com/robsonos.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/logo.png\" width=\"100\"\u003e\n\u003ch3 align=\"center\"\u003eSPIE\u003c/h3\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg\n      alt=\"Maintenance status\"\n      src=\"https://img.shields.io/maintenance/yes/2025?style=flat-square\"\u003e\n  \u003ca\n    href=\"https://github.com/robsonos/spie/actions/workflows/ci.yml\"\n    style=\"color: inherit; text-decoration: none;\"\u003e\n    \u003cimg\n      alt=\"GitHub Workflow Status (with event)\"\n      src=\"https://img.shields.io/github/actions/workflow/status/robsonos/spie/ci.yml\"\u003e\n  \u003c/a\u003e\n  \u003ca\n    href=\"LICENSE\"\n    style=\"color: inherit; text-decoration: none;\"\u003e\n    \u003cimg\n      alt=\"GitHub License\"\n      src=\"https://img.shields.io/github/license/robsonos/spie\"\u003e\n  \u003c/a\u003e\n  \u003cbr /\u003e\n  \u003ca\n    href=\"https://github.com/robsonos/spie/releases\"\n    style=\"color: inherit; text-decoration: none;\"\u003e\n    \u003cimg\n      alt=\"GitHub Release version\"\n      src=\"https://img.shields.io/github/v/release/robsonos/spie\"\u003e\n  \u003c/a\u003e\n  \u003ca\n    href=\"#contributors\"\n    style=\"color: inherit; text-decoration: none;\"\u003e\n    \u003cimg\n        alt=\"GitHub contributors from allcontributors.org\"\n        src=\"https://img.shields.io/github/all-contributors/robsonos/spie\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nThis 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.\n\nThe repository provides:\n\n- Core functionality of Arduino's Serial Monitor, enhanced with tools to configure, monitor, and communicate with serial devices\n- Core functionality of Arduino's Serial Plotter, enhanced with tools to select, zoom, export and visualize data\n- Cross-platform desktop application (`windows`, `linux` and `macOS`)\n- Hot-reloading to accelerate development and testing cycles\n- Enforced code linting and formatting\n- Enforced conventional commits\n- Streamlined workspace management and remote caching with [NX](https://nx.dev/)\n- CI/CD and Release pipelines with local testing\n- Angular's signals and RxJS for reactivity and state management\n- Unit testing examples\n- E2E testing examples\n- Automatic updates on new github releases (see [limitations](#limitations) for more details)\n- Modern tech stack:\n  | Package | version |\n  | ---------- | ------- |\n  | nodejs | 22.x.x |\n  | angular | 20.x.x |\n  | ionic | 8.x.x |\n  | electron | 34.5.x |\n  | nx | 21.3.10 |\n  | typescript | 5.8.x |\n\nFor a demo, check the [sample binaries](https://github.com/robsonos/spie/releases).\n\n## Index\n\n- [Features](#features)\n- [Getting started](#getting-started)\n- [Nx tasks](#nx-tasks)\n- [CD/CI/Release workflow](#cdcirelease-workflow)\n- [Troubleshooting](#troubleshooting)\n\n## Features\n\n### Connection\n\n\u003cp align=\"center\"\u003e\u003cbr\u003e\u003cimg src=\"./docs/demo-connection.gif\" width=\"500\"\u003e\u003c/p\u003e\n\n### Sending Data\n\n\u003cp align=\"center\"\u003e\u003cbr\u003e\u003cimg src=\"./docs/demo-send.gif\" width=\"500\"\u003e\u003c/p\u003e\n\n### Terminal\n\n\u003cp align=\"center\"\u003e\u003cbr\u003e\u003cimg src=\"./docs/demo-terminal.gif\" width=\"500\"\u003e\u003c/p\u003e\n\n### Plotter\n\n\u003cp align=\"center\"\u003e\u003cbr\u003e\u003cimg src=\"./docs/demo-plotter.gif\" width=\"500\"\u003e\u003c/p\u003e\n\n### Auto update\n\n\u003cp align=\"center\"\u003e\u003cbr\u003e\u003cimg src=\"./docs/demo-auto-update.gif\" width=\"500\"\u003e\u003c/p\u003e\n\n[Back to Index](#index)\n\n## Getting Started\n\nFirstly, ensure the following are installed:\n\n- [Node.js](https://nodejs.org) (preferably using `nvm` for version management)\n- [NX CLI](https://nx.dev) (`npm install -g nx`, or you can use `npx nx ...` if you prefer)\n\n### Steps\n\n1. Clone the repository:\n\n```sh\ngit clone https://github.com/robsonos/spie\ncd spie\n```\n\n2. Install dependencies:\n\n```sh\nnpm i\n```\n\n3. Run the application:\n\n```sh\nnpx nx run-many -t serve\n```\n\n### Sample Arduino code\n\nIf you want a minimalistic two way serial example, use the following:\n\n```cpp\n#include \u003cArduino.h\u003e\n\nint period = 1000;\nunsigned long time_now = 0;\n\nvoid setup() {\n  Serial.begin(115200);\n}\n\nvoid loop() {\n  if (Serial.available() \u003e 0)\n    Serial.write(Serial.read());\n\n  if (millis() \u003e time_now + period) {\n    time_now = millis();\n    Serial.print(\"Hello World \");\n    Serial.println(millis());\n  }\n}\n```\n\nFor a example used on the plotter images, check out [spie-firmware](https://github.com/robsonos/spie-firmware).\n\n### Plotter\n\nThe Plotter expects a line feed LF (`\\n`) to separate records. Ensure that there is a linebreak character after the last variable in each record.  \nYou can use different delimiters to separate variables within a record: space (` `), tab (`\\t`), or comma (`,`).  \nFor labeled data, the plotter can interpret variables in the format `\u003clabel\u003e:\u003cvalue\u003e`.  \nThe Plotter supports parsing single and multiple variables in each record, handles duplicates for the same\nvariable label, and correctly groups the data under their respective labels.\n\nExamples:\n\nSingle variable: `1\\n`, `2\\n`  \nMultiple variables: `1,2\\n`, `3,4\\n`  \nMultiple labeled variables: `temp1:1,temp2:2\\n`, `temp1:3,temp2:4\\n`\n\n[Back to Index](#index)\n\n## NX tasks\n\nLearn more about NX in this [Angular Monorepo tutorial](https://nx.dev/getting-started/tutorials/angular-monorepo-tutorial?utm_source=nx_project\u0026utm_medium=readme\u0026utm_campaign=nx_projects).\nHere are the most commonly used NX tasks:\n\n- Serve the applications:\n\n```sh\nnpx nx run-many -t serve\n```\n\n- Lint the code:\n\n```sh\nnpx nx run-many -t lint\n```\n\n- Run unit tests:\n\n```sh\nnpx nx run-many -t test\n```\n\n- Run e2e tests:\n\n```sh\nnpx nx run-many -t e2e\n```\n\n- Build the applications (development):\n\n```sh\nnpx nx run-many -t build\n\n```\n\n- Build the applications (production):\n\n```sh\nnpx nx run-many -t build --prod\n```\n\n- Build and generate unpacked executables:\n\n\u003e [!WARNING]\n\u003e Build the applications first\n\n```sh\nnpx nx run spie:package\n```\n\nOutput files are located in `dist\\packages`\n\n- Build and generate the executables:\n\n\u003e [!WARNING]\n\u003e Build the applications first\n\n```sh\nnpx nx run spie:make\n```\n\nOutput files are located in `dist\\executables`\n\n[Back to Index](#index)\n\n## CD/CI/Release workflow\n\nThere 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:\n\n- `dev`: holds the development code. Pushes to this will trigger the `CI workflow`, test your code, and create a PR to merge it into `main`.\n- `main`: holds the code for the latest release. Pushes to this will trigger the `CD workflow` and create a new github release and tag. You should never need to push commits to `main`; use `dev` and create a PR instead. The code on this branch should always come from merges from `dev`.\n- Once a new release is done, the `Release` workflow will be triggered to build and add the binaries to the release.\n- If you need to maintain more release channels, like `main` is at `v3.x.x` but you need to support `v1.x.x`, I would recommend using a similar approach:\n  - `main` for `v3.x.x`\n  - `main/v1` for `v1.x.x`\n  - `dev` for `v3.x.x` development\n  - `dev/v1` for `v1.x.x` development\n- I may look into exemplifying the above and `pre-releases` in the feature\n\n### act\n\nYou can use [act](https://github.com/nektos/act) to test workflows locally. Read more about `act` [here](https://nektosact.com/). Also, check out [.actrc](.actrc)\n\n- CI\n\n```shell\nact push -W .github/workflows/ci.yml\n```\n\n- CD\n\n```shell\nact push -W .github/workflows/cd.yml\n```\n\n- Release\n\n```shell\nact release -W .github/workflows/release.yml -e  event.json\n```\n\nSample `event.json`\n\n```json\n{\n  \"action\": \"created\",\n  \"release\": {\n    \"name\": \"v1.0.0\",\n    \"tag_name\": \"1.0.0\"\n  }\n}\n```\n\n[Back to Index](#index)\n\n## Troubleshooting\n\n- 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](https://github.com/serialport/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](https://serialport.io/docs/api-parsers-overview) available.\n- 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`.\n- `macOS` application must be signed in order for auto updating to work. See [electron-builder Auto Update](https://www.electron.build/auto-update) for more details.\n\n[Back to Index](#index)\n\n## Contributors\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\n[Back to Index](#index)\n\n\u003c!-- TODO:\n- repo:\n\t- code coverage badge\n\t- pre-release\n\t- protect main branch\n- spie-ui\n\t- tour\n\t- stop/play button logic\n  - settings page\n    - dark mode\n    - i18n\n\t  - show current version\n\t  - OSS licenses\n- spie\n\t- Logger: libs/logger/src/lib/serializers/serialize-dev-log.ts, https://www.npmjs.com/package/electron-log\n\t- better error messages\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobsonos%2Fspie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobsonos%2Fspie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobsonos%2Fspie/lists"}