From 985937c22797679a796e0fc56848731e5bacb4c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Feb 2026 02:25:04 +0000 Subject: [PATCH 01/20] Bump tracing-subscriber from 0.3.20 to 0.3.22 Bumps [tracing-subscriber](https://github.com/tokio-rs/tracing) from 0.3.20 to 0.3.22. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.20...tracing-subscriber-0.3.22) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.22 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- server/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9aac6b93..513217d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2880,9 +2880,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "chrono", "matchers", diff --git a/server/Cargo.toml b/server/Cargo.toml index 3504986c..373054ab 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -38,7 +38,7 @@ serialport = "4.7.3" #tracing tracing = { version = "0.1.44", features = ["attributes"] } tracing-journald = { version = "0.3.1", optional = true } -tracing-subscriber = { version = "0.3.20", features = [ +tracing-subscriber = { version = "0.3.22", features = [ "env-filter", "chrono", "registry", From bef3389874822ad0a183b310a49b88c5a481b487 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Feb 2026 02:25:36 +0000 Subject: [PATCH 02/20] Bump euclid from 0.22.11 to 0.22.13 Bumps [euclid](https://github.com/servo/euclid) from 0.22.11 to 0.22.13. - [Release notes](https://github.com/servo/euclid/releases) - [Commits](https://github.com/servo/euclid/commits) --- updated-dependencies: - dependency-name: euclid dependency-version: 0.22.13 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- machines/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9aac6b93..713ccffd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1019,9 +1019,9 @@ dependencies = [ [[package]] name = "euclid" -version = "0.22.11" +version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +checksum = "df61bf483e837f88d5c2291dcf55c67be7e676b3a51acc48db3a7b163b91ed63" dependencies = [ "num-traits", ] diff --git a/machines/Cargo.toml b/machines/Cargo.toml index 50634fea..bbb39197 100644 --- a/machines/Cargo.toml +++ b/machines/Cargo.toml @@ -15,7 +15,7 @@ anyhow = "1.0.100" bitvec = "1.0.1" lazy_static = "1.5.0" -euclid = "0.22.11" +euclid = "0.22.13" # concurrency smol = "2.0.2" From d19af0923cf0ef313a5273092ebe58de5290c03d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 12:37:25 +0000 Subject: [PATCH 03/20] Bump axum from 0.8.7 to 0.8.8 Bumps [axum](https://github.com/tokio-rs/axum) from 0.8.7 to 0.8.8. - [Release notes](https://github.com/tokio-rs/axum/releases) - [Changelog](https://github.com/tokio-rs/axum/blob/main/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/axum/compare/axum-v0.8.7...axum-v0.8.8) --- updated-dependencies: - dependency-name: axum dependency-version: 0.8.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- control-core/Cargo.toml | 2 +- server/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d4fcca9..5d2230b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,9 +232,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" dependencies = [ "axum-core", "axum-macros", diff --git a/control-core/Cargo.toml b/control-core/Cargo.toml index ecb72df0..21203230 100644 --- a/control-core/Cargo.toml +++ b/control-core/Cargo.toml @@ -9,7 +9,7 @@ workspace = true [dependencies] anyhow = "1.0.100" -axum = "0.8.6" +axum = "0.8.8" ethercat_hal = { path = "../ethercat-hal" } units = { path = "../units" } diff --git a/server/Cargo.toml b/server/Cargo.toml index f558d10e..4e32ff85 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,7 +30,7 @@ regex = "1.11.3" serde_json = "1.0.143" socketioxide = { version = "0.17.2", features = ["msgpack"] } tower-http = { version = "0.6.6", features = ["cors", "trace", "fs"] } -axum = { version = "0.8.6", features = ["macros"] } +axum = { version = "0.8.8", features = ["macros"] } # serial serialport = "4.7.3" From 8095222cad766a2d0e3fe7aa341e1243e467f3ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 12:37:25 +0000 Subject: [PATCH 04/20] Bump syn from 2.0.111 to 2.0.114 Bumps [syn](https://github.com/dtolnay/syn) from 2.0.111 to 2.0.114. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.111...2.0.114) --- updated-dependencies: - dependency-name: syn dependency-version: 2.0.114 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d4fcca9..f99425d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,7 +204,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -221,7 +221,7 @@ checksum = "99e1aca718ea7b89985790c94aad72d77533063fe00bc497bb79a7c2dae6a661" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -291,7 +291,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -539,7 +539,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -682,7 +682,7 @@ dependencies = [ "deluxe-macros", "once_cell", "proc-macro2", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -695,7 +695,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -710,7 +710,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -721,7 +721,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -962,7 +962,7 @@ dependencies = [ "deluxe", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1011,7 +1011,7 @@ dependencies = [ "criterion", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1875,7 +1875,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1905,7 +1905,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2218,7 +2218,7 @@ checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2248,7 +2248,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2571,9 +2571,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -2625,7 +2625,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2685,7 +2685,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2847,7 +2847,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3078,7 +3078,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "wasm-bindgen-shared", ] @@ -3143,7 +3143,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3154,7 +3154,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3430,5 +3430,5 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] From ae2d0fa8b1e86bb580e687daf10d75b1b4dd8a67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 19:43:19 +0000 Subject: [PATCH 05/20] Bump bytes from 1.11.0 to 1.11.1 Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.11.0 to 1.11.1. - [Release notes](https://github.com/tokio-rs/bytes/releases) - [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/bytes/compare/v1.11.0...v1.11.1) --- updated-dependencies: - dependency-name: bytes dependency-version: 1.11.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d4fcca9..84bf46fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -390,9 +390,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] From 153a719d6468269b7c1b965abeea51dac930f587 Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:56:06 +0100 Subject: [PATCH 06/20] remove Git hooks and pre-commit script --- hooks/README.md | 13 ------------- hooks/pre-commit | 49 ------------------------------------------------ 2 files changed, 62 deletions(-) delete mode 100644 hooks/README.md delete mode 100755 hooks/pre-commit diff --git a/hooks/README.md b/hooks/README.md deleted file mode 100644 index 3d2296a1..00000000 --- a/hooks/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Git Hooks - -This directory contains Git hooks for the project. - -## Installation - -To install the hooks, run the following command from the repository root: - -```bash -# Copy the pre-commit hook to your local .git/hooks directory -cp hooks/pre-commit .git/hooks/pre-commit -chmod +x .git/hooks/pre-commit -``` \ No newline at end of file diff --git a/hooks/pre-commit b/hooks/pre-commit deleted file mode 100755 index ceb5b0d6..00000000 --- a/hooks/pre-commit +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# Pre-commit hook to generate Rust documentation -# -# This hook runs the rustdoc.sh script to update documentation -# before each commit. - -echo "Running rustdoc generation..." - -# Get the repository root -REPO_ROOT="$(git rev-parse --show-toplevel)" - -# iteralte all directories thst contain a Cargo.toml file -for dir in $(find "$REPO_ROOT" -name "Cargo.toml" -exec dirname {} \;); do - echo "Generating documentation in $dir" - - # cargotoml conatains workspace members, skip this directory - # HAS_MEMBERS=$(grep -c '\[workspace\]' "$dir/Cargo.toml") - # if [ "$HAS_MEMBERS" -gt 0 ]; then - # echo "Skipping workspace directory $dir" - # continue - # fi - - # get package name from Cargo.toml using cargo metadata - PACKAGE_NAME=$(cargo metadata --format-version 1 --no-deps --manifest-path "$dir/Cargo.toml" | jq -r '.packages[0].name') - if [ -z "$PACKAGE_NAME" ]; then - echo "Could not determine package name for $dir" - continue - fi - - # go into the directory - cd "$dir" || continue - - # generate the documentation using rustdoc-md - cargo install rustdoc-md --git https://github.com/qitechgmbh/rustdoc-md --rev 6dc34f9c9d878799d9c1b4f2d2bcbb1f2757ede7 - RUSTC_BOOTSTRAP=1 RUSTDOCFLAGS="-Z unstable-options --output-format json" cargo doc --no-deps - rustdoc-md --path "${REPO_ROOT}/target/doc/${PACKAGE_NAME}.json" --output ./rustdoc.md - - # stage the generated documentation file - git add "rustdoc.md" - - # go back to the repository root - cd "$REPO_ROOT" || exit -done - -git rm --cached rustdoc.md 2>/dev/null -rm rustdoc.md - -exit 0 From 310ac42a8818d591ee42c3e6df4c74a23ab7e393 Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:57:35 +0100 Subject: [PATCH 07/20] Update issue templates Add issue templates for better feature requests or bug reports. --- .github/ISSUE_TEMPLATE/blank.md | 10 ++++++ .github/ISSUE_TEMPLATE/bug_report.md | 39 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 33 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/blank.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/blank.md b/.github/ISSUE_TEMPLATE/blank.md new file mode 100644 index 00000000..a89b0f7f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/blank.md @@ -0,0 +1,10 @@ +--- +name: Blank +about: Create a general issue that doesn't fit bug reports or feature requests +title: '' +labels: '' +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..d98f78e0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,39 @@ +--- +name: Bug report +about: Create a report to help us improve +title: 'BUG: ' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Navigate to '...' +2. Select/Press '....' +3. Execute operation '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots/Photos** +If applicable, add screenshots from the HMI display or photos of the machine screen to help explain your problem. + +**Machine Information (please complete the following):** + - Machine Type: [Winder2, Laser, Aquapath...] + - Control Software Version: [e.g. 2.4.1] + +**Device Information (if issue occurs on external device):** + - Device Type: [e.g. Tablet, PLC, Remote Control Panel] + - OS: [e.g. Windows 10, Linux, etc.] + - Connection Type: [e.g. Ethernet, USB] + +**Error Messages/Codes** +If applicable, provide exact error codes or messages displayed or found in the troubleshooting terminal. + +**Additional context** +Add any other context about the problem here (e.g., recent software updates, environmental factors). diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..99b5d09a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,33 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: 'Feat:' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. During operation, I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions, workarounds, or features you've considered. + +**Use Case/Application:** + - Machine Type(s): [e.g. All machines, Winder, Aquapath, ...] + - Frequency of Use: [e.g. Daily, During setup, Occasionally] + +**Expected Benefits:** + - Efficiency Improvement: [e.g. Reduces setup time by X minutes, Eliminates manual steps] + - Safety Enhancement: [e.g. Prevents operator error, Adds safety checks] + - Production Impact: [e.g. Increases throughput, Reduces downtime, Improves quality] + - User Experience: [e.g. Simplifies workflow, Reduces training time] + +**Mockups/Sketches** +If applicable, add sketches, mockups, or photos showing how the feature would appear on the HMI display or integrate with the machine. + +**Additional context** +Add any other context, industry standards, or examples from other control systems about the feature request here. From 2d98d369e1ad8f9214ed28ab5f807734ab61129e Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:04:29 +0100 Subject: [PATCH 08/20] Update .github/ISSUE_TEMPLATE/feature_request.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 99b5d09a..a352136f 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,7 +1,7 @@ --- name: Feature request about: Suggest an idea for this project -title: 'Feat:' +title: 'Feat: ' labels: '' assignees: '' From 7681dae32c66d66c695b65e32b4f0e49b2eefe38 Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:40:58 +0100 Subject: [PATCH 09/20] feat: automate npmDepsHash updates for Electron - Add GitHub Actions workflow to automatically calculate and update npmDepsHash - Workflow triggers on package-lock.json changes in PRs - Uses nix prefetch-npm-deps to calculate correct hash - Automatically commits hash updates to the PR - Supports manual triggering via workflow_dispatch --- .github/workflows/update-npm-hash.yml | 80 +++++++++++++++++++++++++++ electron/package-lock.json | 4 +- electron/package.json | 4 +- nixos/packages/electron.nix | 2 +- 4 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/update-npm-hash.yml diff --git a/.github/workflows/update-npm-hash.yml b/.github/workflows/update-npm-hash.yml new file mode 100644 index 00000000..cbf4b52c --- /dev/null +++ b/.github/workflows/update-npm-hash.yml @@ -0,0 +1,80 @@ +name: Update npm deps hash + +on: + pull_request: + paths: + - 'electron/package-lock.json' + - 'electron/package.json' + workflow_dispatch: + +env: + NIX_PATH: nixpkgs=channel:nixos-25.05 + +permissions: + contents: write + pull-requests: write + actions: write + +jobs: + update-hash: + runs-on: ubuntu-latest + if: github.event.pull_request.head.repo.full_name == github.repository + + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install Nix + uses: nixbuild/nix-quick-install-action@v34 + with: + nix_conf: | + keep-env-derivations = true + keep-outputs = true + + - name: Calculate new npm deps hash + id: calc-hash + run: | + # Calculate the hash using nix run with nixpkgs + NEW_HASH=$(nix run 'nixpkgs#prefetch-npm-deps' electron/package-lock.json) + echo "hash=$NEW_HASH" >> $GITHUB_OUTPUT + echo "Calculated hash: $NEW_HASH" + + - name: Update npmDepsHash in electron.nix + run: | + NEW_HASH="${{ steps.calc-hash.outputs.hash }}" + sed -i "s|npmDepsHash = \".*\";|npmDepsHash = \"$NEW_HASH\";|" nixos/packages/electron.nix + + - name: Check if hash changed + id: check-changes + run: | + if git diff --quiet nixos/packages/electron.nix; then + echo "changed=false" >> $GITHUB_OUTPUT + echo "No changes needed - hash is already correct" + else + echo "changed=true" >> $GITHUB_OUTPUT + echo "Hash updated in electron.nix" + fi + + - name: Commit and push if changed + if: steps.check-changes.outputs.changed == 'true' + run: | + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git add nixos/packages/electron.nix + git commit -m "chore: update npmDepsHash to ${{ steps.calc-hash.outputs.hash }}" + git push + + - name: Comment on PR + if: steps.check-changes.outputs.changed == 'true' + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Automatically updated `npmDepsHash` to `${{ steps.calc-hash.outputs.hash }}`\n\n**Next step:** Trigger the checks by pushing an empty commit:\n```bash\ngit commit --allow-empty -m "trigger ci" && git push\n```' + }) diff --git a/electron/package-lock.json b/electron/package-lock.json index d3ab8f9a..80b01511 100644 --- a/electron/package-lock.json +++ b/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "qitech-control-electron", - "version": "1.0.0", + "version": "2.4.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "qitech-control-electron", - "version": "1.0.0", + "version": "2.4.1", "dependencies": { "@hookform/resolvers": "^5.2.2", "@icons-pack/react-simple-icons": "^11.2.0", diff --git a/electron/package.json b/electron/package.json index 521cb0ce..9f5c9bd2 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,8 +1,8 @@ { "name": "qitech-control-electron", "productName": "QiTech Control", - "version": "1.0.0", - "description": "", + "version": "2.4.1", + "description": "Next Generation Machine Interface ", "main": ".vite/build/main.js", "private": true, "scripts": { diff --git a/nixos/packages/electron.nix b/nixos/packages/electron.nix index 7ab0ac75..250f2698 100644 --- a/nixos/packages/electron.nix +++ b/nixos/packages/electron.nix @@ -10,7 +10,7 @@ buildNpmPackage rec { ELECTRON_SKIP_BINARY_DOWNLOAD = 1; makeCacheWritable = true; - npmDepsHash = "sha256-XFDCYY4/9GKssEnGhnrmBT3kZ/qTR2XPD+ofR/TcQ+k="; + npmDepsHash = "sha256-rnaAsSkoTRoBgLCTF8ZFpi7uUQ+8W+u3qoMxsptX6NU="; npmFlags = [ "--no-audit" "--no-fund" ]; installPhase = '' From bae1de3c54134d8cc6cff04027a1991b63ce8c7e Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:52:33 +0100 Subject: [PATCH 10/20] Remove .gitattributes and .gitmodules files --- .gitattributes | 3 --- .gitmodules | 0 2 files changed, 3 deletions(-) delete mode 100644 .gitattributes delete mode 100644 .gitmodules diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 399858af..00000000 --- a/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -.png filter=lfs diff=lfs merge=lfs -text -.jpg filter=lfs diff=lfs merge=lfs -text -.jpeg filter=lfs diff=lfs merge=lfs -text diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29b..00000000 From 1d1eeb3d487262248441f444cc19d8680a091b6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:06:09 +0000 Subject: [PATCH 11/20] Bump serde_json from 1.0.145 to 1.0.149 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.145 to 1.0.149. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.145...v1.0.149) --- updated-dependencies: - dependency-name: serde_json dependency-version: 1.0.149 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 +++++++++--- machines/Cargo.toml | 2 +- server/Cargo.toml | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb04865f..31974572 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2253,15 +2253,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -3432,3 +3432,9 @@ dependencies = [ "quote", "syn 2.0.111", ] + +[[package]] +name = "zmij" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445" diff --git a/machines/Cargo.toml b/machines/Cargo.toml index 8ea8f4fe..9a08a68b 100644 --- a/machines/Cargo.toml +++ b/machines/Cargo.toml @@ -21,7 +21,7 @@ euclid = "0.22.13" smol = "2.0.2" # web -serde_json = "1.0.143" +serde_json = "1.0.149" socketioxide = { version = "0.17.2", features = ["msgpack"] } # serial diff --git a/server/Cargo.toml b/server/Cargo.toml index d54e9ff6..09df666f 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -27,7 +27,7 @@ tokio = { version = "1.45.1", features = ["rt-multi-thread"] } regex = "1.11.3" # web -serde_json = "1.0.143" +serde_json = "1.0.149" socketioxide = { version = "0.17.2", features = ["msgpack"] } tower-http = { version = "0.6.6", features = ["cors", "trace", "fs"] } axum = { version = "0.8.8", features = ["macros"] } From bc8cc5dd3db6175cd4fa394c42ed142c3f1a2485 Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:18:19 +0100 Subject: [PATCH 12/20] Update README.md to enhance documentation structure and clarity --- README.md | 126 +++++++++++++++++++----------------------------------- 1 file changed, 43 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 14acc03f..9ab0cf60 100644 --- a/README.md +++ b/README.md @@ -8,103 +8,63 @@ It frees developers from proprietary, license-heavy PLC ecosystems and rigid "po QiTech Control combines the modularity and reliability of standard EtherCAT terminals (e.g., WAGO, Beckhoff) with the power of a modern Rust & React stack. +## Documentation + +**[View Full Documentation Wiki](https://github.com/qitechgmbh/control/wiki)** + +- [Getting Started](https://github.com/qitechgmbh/control/wiki/Getting-Started) +- [Architecture Overview](https://github.com/qitechgmbh/control/wiki/Architecture-Overview) +- [EtherCAT Basics](https://github.com/qitechgmbh/control/wiki/Ethercat-Basics) +- [Device Examples](https://github.com/qitechgmbh/control/wiki#-device-examples) +- [REST API Reference](https://github.com/qitechgmbh/control/wiki/Rest-Api) + +## Videos [![](https://img.youtube.com/vi/KI3YeBwfV-s/maxresdefault.jpg)](https://www.youtube.com/watch?v=KI3YeBwfV-s) -*Click here to watch a video demo of our software.* +*Software demo* [![](https://img.youtube.com/vi/55egCAkQgyM/maxresdefault.jpg)](https://youtu.be/55egCAkQgyM) -*Click here to watch a full explainer Video of our Software.* +*Full explainer* -# Repo Structure +## Repository Structure -**Frontend** +- **`/electron`** - React + Electron frontend +- **`/server`** - Rust backend implementing machine logic +- **`/ethercat-hal`** - Hardware abstraction layer for EtherCAT devices +- **`/control-core`** - Core control logic +- **`/nixos`** - Custom Linux OS with realtime kernel -- `/electron`: Frontend code for the control software built with React and Electron. +## Technology Stack -**Backend** +**Backend:** Rust with [Ethercrab](https://github.com/ethercrab-rs/ethercrab) for EtherCAT, [SocketIO](https://socket.io/) for real-time communication, [axum](https://docs.rs/axum/latest/axum/) for REST API -- `/server`: Glue between Beckhoff and Electron. Implements machine logic. -- `/ethercat-hal`: Hardware abstraction layer for Beckhoff (and possibly other EtherCat) devices and protocols. -- `/ethercat-hal-derive`: Macros for `ethercat-hal` -- `/control-core`: Core control logic for the server. - -**Operating System** - -- `/nixos`: Custom Linux with realtime kernel & preconfigured for touchscreens. - -**Other** - -- `/docs`: Documentation for the project. - -# Technology Choices - -## Backend - -To interface with Beckhoff and other EtherCAT devices we need an EtherCAT master software. Possibilities are [PySOEM](https://github.com/bnjmnp/pysoem) (Python), [SOEM](https://github.com/OpenEtherCATsociety/SOEM) (C) and [Ethercrab](https://github.com/ethercrab-rs/ethercrab) (Rust). For realtime operation only C and Rust are suitable. We chose Rust because of safety and confidence in the written code. - -[SocketIO](https://socket.io/) was chosen for performant event driven communication from the backend to the server. But we still use REST with [axum](https://docs.rs/axum/latest/axum/) for the communication thet benefits from the request/response model. - -We use [Smol](https://github.com/smol-rs/smol) for EtherCAT IO in the control loop for it's performance and [Tokio](https://tokio.rs/) for server IO because of it's ecosystem and maturity. - -## Frontend - -We could combine the code of the frontend and backend using [Doxius](https://dioxuslabs.com/) but it lacks good Linux support. We chose [Electron](https://www.electronjs.org/) with [React](https://react.dev/) for it's maturity and ecosystem. For the UI we use [Shadcn](https://ui.shadcn.com/) components and [Tailwind](https://tailwindcss.com/) for styling. For routing we use [TanStack Router](https://tanstack.com/router/v1). - -# Dev Setup - -[Developer Documentation](./docs/developer-docs/) - -[API Documentation](https://github.com/qitechgmbh/control/blob/master/docs/rest-api.md) - --> Backend -- Rust stable 1.86^ toolchain (install via [rustup](https://rustup.rs/)) -- `rust-analyzer` extension for VSCode -- Set your interface in `server/src/ethercat/init.rs` like `en10` -- Connect a Beckhoff EK1100 to your interface -- run `cd server && cargo run` to start the server (localhost:3001) - --> Frontend -- nodejs and npm installed -- run `cd electron && npm i && npm run start` to start the frontend +**Frontend:** [Electron](https://www.electronjs.org/) + [React](https://react.dev/) with [Shadcn](https://ui.shadcn.com/) components and [Tailwind](https://tailwindcss.com/) styling -## Minimal Hardware Examples +## Hardware Examples -For complete step-by-step tutorials on setting up your first hardware, including wiring diagrams and software configuration, see the [Getting Started Guide](./docs/developer-docs/getting-started.md#minimal-hardware-examples). +QiTech Control supports a wide range of EtherCAT hardware from WAGO and Beckhoff. We provide complete step-by-step tutorials with wiring diagrams and software configuration for many common modules. -| Example | Vendor | Hardware | Description | How-To Video | Docs | -| :----------------- | :------- | :------------ | :-------------------------------------- | :----------- | :------------------------------------------------------------ | -| **Digital Input** | WAGO | 750-402 | 4-Channel Digital Input | [ ] | [Docs](./docs/developer-docs/minimal-example-wago750-402.md) | -| **Digital Output** | WAGO | 750-753 | 8-Channel Digital Output | [ ] | - | -| **Analog Input** | WAGO | 750-455 | 4-Channel Analog Input | [ ] | [Docs](./docs/developer-docs/minimal-example-wago-750-455.md)| -| **Analog Output** | WAGO | 750-553 | 4-Channel Analog Output | [ ] | - | -| **Serial Comms** | WAGO | 750-652 | RS-485 Modbus Module | [ ] | - | -| **Stepper Drive** | WAGO | 750-67x | Stepper Controller | [ ] | - | -| **Power Supply** | WAGO | 2787-214 | Power Supply Unit | [ ] | - | -| **LED Control** | Beckhoff | EL2004 | Digital output control (simplest setup) | [ ] | [Docs](./docs/developer-docs/minimal-example-el2004.md) | -| **Analog Input** | Beckhoff | EL3021 | Reading analog current measurements | [ ] | [Docs](./docs/developer-docs/minimal-example-el3021.md) | +**[View all hardware examples and tutorials on the wiki](https://github.com/qitechgmbh/control/wiki/Hardware-Examples)** -# QiTech Machines +Quick links to popular examples: +- [EL2004 - LED Control](https://github.com/qitechgmbh/control/wiki/Minimal-Example-El2004) (simplest setup for beginners) +- [EL3021 - Analog Input](https://github.com/qitechgmbh/control/wiki/Minimal-Example-El3021) +- [EL7031 - Stepper Motor Control](https://github.com/qitechgmbh/control/wiki/Minimal-Example-El7031-Motor) +- [WAGO 750-402 - Digital Input](https://github.com/qitechgmbh/control/wiki/Minimal-Example-Wago750-402) +- [WAGO 750-455 - Analog Input](https://github.com/qitechgmbh/control/wiki/Minimal-Example-Wago-750-455) -| Machine Name | Description | Machine ID | Implemented | Video | Docs | -| :---------------- | :-------------------------- | :--------- | :---------- | :-------------------------------------------------------------- | :------------------------------------ | -| Winder V1 | Winding Filaments & Similar | 1 | Legacy | [Video](https://youtu.be/4aE4cFhioKA?si=Xdj_LVnFrAYWnLm6) | - | -| Winder V2 | Winding Filaments & Similar | 2 | Yes | [Video](https://youtu.be/f2kzh6kpQWE?si=HEYcLOaC9gWSp2Wo) | - | -| XL Winder V1 | Large Scale Winder | 3 | Yes | [Video](https://youtu.be/ynI6ioWIQQY?si=4EDVKXbgIqrvGGtY) | - | -| Buffer V1 | Filament buffering system | 4 | In Progress | [Video](https://youtu.be/VR5mEdZDPA0?si=eip7dQXU4zaXK7Ev) | - | -| Extruder V1 | Single Screw Extruder | 5 | Legacy | [Video](https://youtu.be/gchoG-yGczI?si=bEM4daf5eOVaU5_2) | - | -| Extruder V2 | Single Screw Extruder | 6 | Yes | [Video](https://youtu.be/mexRYGDNWa4?si=h7JBz_XKMwKLPenG) | - | -| Waterway V1 | Filament Water Cooling | 7 | In Progress | [Video](https://youtu.be/_T5z1J8bl_k?si=uOC1hIQ1EAP0cHIF) | - | -| Laser V1 | Diameter Measuring Laser | 8 | Yes | [Video](https://youtu.be/WDM34lj4afM?si=MZzUKkHCrzH4P0aA) | [Docs](./docs/machines/laser-DRE.md) | -| 2-Axis-Laser V1 | Dual Axis Laser | 9 | Yes | [Video](https://youtu.be/WDM34lj4afM?si=MZzUKkHCrzH4P0aA) | - | -| Mock | Mock Machine for Testing | 10 | Yes | | - | -| Extruder V3 | Single Screw Extruder | 11 | Yes | [Video](https://youtu.be/ipHHuPzCvn4?si=hkZ1b93rVuwDxhFD) | - | -| Mini Schredder V1 | mini plastic crusher | 12 | Legacy | [Video](https://youtu.be/m8NplNqdu2Q?si=x6zjDktJtpbSMSmu) | - | -| Pro Schredder V1 | large plastic crusher | 13 | Legacy | [Video](https://youtu.be/pSaVMqp06pU?si=y61enutRpxKscBm4) | - | -| Dryer V1 | polymer dryer | 14 | Reserved | [Video](https://youtu.be/6hdmUUAdZp0?si=eKOW1WlgkqTpnfdS) | - | -| Pelletizier V1 | Filament chopper | 15 | Reserved | | - | +## QiTech Machines -# Current Restructuring Efforts +QiTech Control powers 10+ production machines for filament extrusion, winding, measurement, and material processing. -[![](https://img.youtube.com/vi/UlbnSVIhfLI/maxresdefault.jpg)](https://www.youtube.com/live/UlbnSVIhfLI?si=ZTotC5B7gd87tUim) -*Video: Live stream of software dev meeting* +**[View complete machine catalog on the wiki](https://github.com/qitechgmbh/control/wiki/QiTech-Machines)** + + +## Contributing + +This is an open-source project. Contributions are welcome! Please see the [wiki](https://github.com/qitechgmbh/control/wiki) for development guidelines. + +## License + +See [LICENSE](LICENSE) file for details. From dec342498c29555a1c8b33d5c49cf694e40350dd Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:21:06 +0100 Subject: [PATCH 13/20] Fix link to Device Examples in README.md for improved navigation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ab0cf60..678bad35 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ QiTech Control combines the modularity and reliability of standard EtherCAT term - [Getting Started](https://github.com/qitechgmbh/control/wiki/Getting-Started) - [Architecture Overview](https://github.com/qitechgmbh/control/wiki/Architecture-Overview) - [EtherCAT Basics](https://github.com/qitechgmbh/control/wiki/Ethercat-Basics) -- [Device Examples](https://github.com/qitechgmbh/control/wiki#-device-examples) +- [Device Examples](https://github.com/qitechgmbh/control/wiki/Hardware-Examples) - [REST API Reference](https://github.com/qitechgmbh/control/wiki/Rest-Api) ## Videos From 1a3c26b78940fe314c0db6adc8cc74645048d75d Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 18:30:07 +0100 Subject: [PATCH 14/20] Update issue templates --- .github/ISSUE_TEMPLATE/blank.md | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/blank.md diff --git a/.github/ISSUE_TEMPLATE/blank.md b/.github/ISSUE_TEMPLATE/blank.md deleted file mode 100644 index a89b0f7f..00000000 --- a/.github/ISSUE_TEMPLATE/blank.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Blank -about: Create a general issue that doesn't fit bug reports or feature requests -title: '' -labels: '' -assignees: '' - ---- - - From f67f098ff3ebf6db40d1e5338095836b18c057df Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 19:30:21 +0100 Subject: [PATCH 15/20] better wording --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 678bad35..e75858dd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # QiTech Control -QiTech Control is an open-source framework designed to bring modern software paradigms to certified industrial hardware. +QiTech Control is an open-source framework designed to bring modern software development practices to certified industrial hardware. It frees developers from proprietary, license-heavy PLC ecosystems and rigid "point-and-click" workflows that are no longer adequate for today's complex automation challenges. From b6263e90d671be18f974d8d54c8ef3f1bf45689c Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 19:32:33 +0100 Subject: [PATCH 16/20] Refactor video section in README.md for improved layout and clarity --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e75858dd..16acc3e2 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,9 @@ QiTech Control combines the modularity and reliability of standard EtherCAT term ## Videos -[![](https://img.youtube.com/vi/KI3YeBwfV-s/maxresdefault.jpg)](https://www.youtube.com/watch?v=KI3YeBwfV-s) -*Software demo* - -[![](https://img.youtube.com/vi/55egCAkQgyM/maxresdefault.jpg)](https://youtu.be/55egCAkQgyM) -*Full explainer* +| Software Demo | Full Explainer | +|---------------|----------------| +| [![](https://img.youtube.com/vi/KI3YeBwfV-s/maxresdefault.jpg)](https://www.youtube.com/watch?v=KI3YeBwfV-s) | [![](https://img.youtube.com/vi/55egCAkQgyM/maxresdefault.jpg)](https://youtu.be/55egCAkQgyM) | ## Repository Structure From 579ef0d2e27f62fa77330e1f18c61741880faed7 Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Wed, 4 Feb 2026 19:39:34 +0100 Subject: [PATCH 17/20] Enhance video section in README.md with descriptive captions for better user engagement --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16acc3e2..cb92a47d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ QiTech Control combines the modularity and reliability of standard EtherCAT term | Software Demo | Full Explainer | |---------------|----------------| -| [![](https://img.youtube.com/vi/KI3YeBwfV-s/maxresdefault.jpg)](https://www.youtube.com/watch?v=KI3YeBwfV-s) | [![](https://img.youtube.com/vi/55egCAkQgyM/maxresdefault.jpg)](https://youtu.be/55egCAkQgyM) | +| [![](https://img.youtube.com/vi/KI3YeBwfV-s/maxresdefault.jpg)](https://www.youtube.com/watch?v=KI3YeBwfV-s)
*Click to watch a demo of the control software in action* | [![](https://img.youtube.com/vi/55egCAkQgyM/maxresdefault.jpg)](https://youtu.be/55egCAkQgyM)
*Click to watch a complete overview of QiTech Control* | ## Repository Structure From 8c32ce2a2bd7a069c3e76058e44dc63ac248d6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20Kr=C3=A4mer?= <93094049+kraemr@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:52:56 +0100 Subject: [PATCH 18/20] loop now uses Different Cycle time when development-build is set (#1112) * loop now uses Different Cycle time when development-build is set * fixed formatting * hid stop_dnsmasq import behind feature flag * added feature gate for start_dnsmasq in main --- ethercat-hal/src/devices/el5152.rs | 1 + server/src/ethercat/init.rs | 28 ++-------------- server/src/ethercat/setup.rs | 39 +++++++++++----------- server/src/loop.rs | 2 -- server/src/main.rs | 52 ++++++++++++++++-------------- 5 files changed, 52 insertions(+), 70 deletions(-) diff --git a/ethercat-hal/src/devices/el5152.rs b/ethercat-hal/src/devices/el5152.rs index eac5f6fa..66797d39 100644 --- a/ethercat-hal/src/devices/el5152.rs +++ b/ethercat-hal/src/devices/el5152.rs @@ -303,6 +303,7 @@ impl EL5152ChannelConfiguration { device .sdo_write(base_index, 0x11, self.frequency_window) .await?; + device .sdo_write(base_index, 0x13, self.frequency_scaling) .await?; diff --git a/server/src/ethercat/init.rs b/server/src/ethercat/init.rs index 1ecce41e..1c5c5cc1 100644 --- a/server/src/ethercat/init.rs +++ b/server/src/ethercat/init.rs @@ -1,12 +1,7 @@ +use crate::metrics::io::set_ethercat_iface; use control_core::ethercat::interface_discovery::discover_ethercat_interface; use smol::Timer; -use std::{sync::Arc, time::Duration}; - -use crate::{ - app_state::SharedState, - ethercat::{ethercat_discovery_info::send_ethercat_found, setup::setup_loop}, - metrics::io::set_ethercat_iface, -}; +use std::time::Duration; pub async fn find_ethercat_interface() -> String { loop { @@ -23,22 +18,3 @@ pub async fn find_ethercat_interface() -> String { } } } - -pub async fn start_interface_discovery(app_state: Arc) { - let interface = find_ethercat_interface().await; - - tracing::info!("Calling setup_loop"); - let res = setup_loop(&interface, app_state.clone()).await; - match res { - Ok(_) => tracing::info!("Successfully initialized EtherCAT network"), - Err(e) => { - tracing::error!( - "[{}::main] Failed to initialize EtherCAT network \n{:?}", - module_path!(), - e - ); - } - } - - send_ethercat_found(app_state, &interface).await; -} diff --git a/server/src/ethercat/setup.rs b/server/src/ethercat/setup.rs index f3dd3678..e97acc56 100644 --- a/server/src/ethercat/setup.rs +++ b/server/src/ethercat/setup.rs @@ -24,7 +24,9 @@ use smol::stream::StreamExt; use ta::Next; use ta::indicators::ExponentialMovingAverage; +#[cfg(not(feature = "development-build"))] use crate::utils::stop_dnsmasq; + use ethercrab::std::ethercat_now; use ethercrab::{ DcSync, MainDevice, MainDeviceConfig, PduStorage, RegisterAddress, RetryBehaviour, @@ -178,17 +180,20 @@ pub async fn set_ethercat_devices, ) -> Result { tracing::info!("Starting Ethercat PDU loop"); - const TICK_INTERVAL: Duration = Duration::from_micros(700); - let res = stop_dnsmasq(); - match res { - Ok(_) => (), - Err(e) => tracing::error!("Failed to stop dnsmasq: {:?}", e), - }; - // Small Timeout to ensure interfaces get released - smol::Timer::after(Duration::from_millis(1500)).await; + #[cfg(not(feature = "development-build"))] + { + let res = stop_dnsmasq(); + match res { + Ok(_) => tracing::info!("Stopped dnsmasq"), + Err(e) => tracing::error!("Failed to stop dnsmasq: {:?}", e), + }; + // Small Timeout to ensure interfaces get released + smol::Timer::after(Duration::from_millis(1500)).await; + } // Setup ethercrab tx/rx task let pdu_storage = Box::leak(Box::new(PduStorage::::new())); @@ -237,7 +242,7 @@ pub async fn setup_loop( pdu, Timeouts { // Default 5000ms - state_transition: Duration::from_millis(5000), + state_transition: Duration::from_millis(10000), // Default 30_000us pdu: Duration::from_micros(30_000), // Default 10ms @@ -287,11 +292,6 @@ pub async fn setup_loop( }; for mut subdevice in group_preop.iter_mut(&maindevice) { - println!( - "subdevice {} {:X?}", - subdevice.name(), - subdevice.configured_address() - ); if subdevice.name() == "EL4002" { // Sync mode 01 = SM Synchronous, says it does dc but actually doesnt, thx? subdevice @@ -308,7 +308,7 @@ pub async fn setup_loop( .expect("Set sync mode"); subdevice - .sdo_write(0x1c32, 0x02, TICK_INTERVAL.as_nanos() as u32) + .sdo_write(0x1c32, 0x02, cycle_target.as_nanos() as u32) .await .expect("Set cycle time"); @@ -472,14 +472,17 @@ pub async fn setup_loop( .await?; // Avoid potential Sdo write Contention on the bus, by just waiting a bit + // Timeout is not enough ... or rather a monstrous timeout would be required for all of the sdo writes we do ... + // TODO: Keep small timeout here and add Complete Access configuration for the stepper terminals and complex trerminals like (el5152) smol::Timer::after(Duration::from_millis(4000)).await; + let mut now = Instant::now(); let start = Instant::now(); let mut averages = Vec::new(); for _ in 0..group_preop.len() { averages.push(ExponentialMovingAverage::new(64).unwrap()); } - let mut tick_interval = smol::Timer::interval(TICK_INTERVAL); + let mut tick_interval = smol::Timer::interval(cycle_target); tracing::info!("Moving into PRE-OP with PDI"); let group = group_preop.into_pre_op_pdi(&maindevice).await?; @@ -537,9 +540,9 @@ pub async fn setup_loop( // Start SYNC0 100ms in the future start_delay: Duration::from_millis(100), // SYNC0 period should be the same as the process data loop in most cases - sync0_period: TICK_INTERVAL, + sync0_period: cycle_target, // Send process data half way through cycle - sync0_shift: TICK_INTERVAL / 2, + sync0_shift: cycle_target / 2, }, ) .await?; diff --git a/server/src/loop.rs b/server/src/loop.rs index ca709283..4ece463b 100644 --- a/server/src/loop.rs +++ b/server/src/loop.rs @@ -90,7 +90,6 @@ pub fn start_loop_thread( match msg { HotThreadMessage::NoMsg => {} HotThreadMessage::AddEtherCatSetup(ethercat_setup) => { - println!("EthercatSetup: {:?}", ethercat_setup.devices); rt_loop_inputs.ethercat_setup = Some(Box::new(ethercat_setup)); } HotThreadMessage::WriteMachineDeviceInfo(info_request) => { @@ -115,7 +114,6 @@ pub fn start_loop_thread( .retain(|m| m.get_machine_identification_unique() != unique_id); } HotThreadMessage::AddMachines(machine_vec) => { - tracing::info!("received machines{:?}", machine_vec); for new_machine in machine_vec { let id = new_machine.get_machine_identification_unique(); if !rt_loop_inputs diff --git a/server/src/main.rs b/server/src/main.rs index da44e3f3..a7e009ba 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -37,6 +37,12 @@ use smol::{ use socketioxide::extract::SocketRef; use std::{collections::HashMap, sync::Arc, time::Duration}; +#[cfg(feature = "development-build")] +const CYCLE_TARGET_TIME: Duration = Duration::from_micros(2000); + +#[cfg(not(feature = "development-build"))] +const CYCLE_TARGET_TIME: Duration = Duration::from_micros(700); + #[cfg(feature = "mock-machine")] use mock_init::init_mock; @@ -128,10 +134,8 @@ pub async fn add_serial_device( pub async fn start_serial_discovery(app_state: Arc) { loop { let devices = SerialDetection::detect_devices(); - // This allows detection of disconnected devices handle_serial_device_hotplug(app_state.clone(), devices).await; - smol::Timer::after(Duration::from_secs(1)).await; } } @@ -143,33 +147,34 @@ pub async fn start_interface_discovery( let interface = find_ethercat_interface().await; tracing::info!("Inferface found {}, setting up EtherCAT loop", interface); set_ethercat_iface(interface.clone()); - let res = setup_loop(&interface, app_state.clone()).await; + let res = setup_loop(&interface, CYCLE_TARGET_TIME, app_state.clone()).await; match res { Ok(setup) => { let _ = sender.send(HotThreadMessage::AddEtherCatSetup(setup)).await; tracing::info!("Successfully initialized EtherCAT devices"); - { - // Notify client via socketio - let app_state_clone = app_state.clone(); - let main_namespace = &mut app_state_clone - .socketio_setup - .namespaces - .write() - .await - .main_namespace; - let event = EthercatDevicesEventBuilder() - .build(app_state_clone.clone()) - .await; - main_namespace.emit(MainNamespaceEvents::EthercatDevicesEvent(event)); - } + // Notify client via socketio + let app_state_clone = app_state.clone(); + let main_namespace = &mut app_state_clone + .socketio_setup + .namespaces + .write() + .await + .main_namespace; + let event = EthercatDevicesEventBuilder() + .build(app_state_clone.clone()) + .await; + main_namespace.emit(MainNamespaceEvents::EthercatDevicesEvent(event)); - let res = start_dnsmasq(); - match res { - Ok(o) => o, - Err(e) => tracing::error!("Failed to start dnsmasq: {:?}", e), - }; + #[cfg(not(feature = "development-build"))] + { + let res = start_dnsmasq(); + match res { + Ok(o) => o, + Err(e) => tracing::error!("Failed to start dnsmasq: {:?}", e), + }; + } } Err(e) => { tracing::error!( @@ -178,6 +183,7 @@ pub async fn start_interface_discovery( e ); // if this doesnt work, unlucky + #[cfg(not(feature = "development-build"))] let _ = start_dnsmasq(); } } @@ -355,8 +361,6 @@ fn main() { #[cfg(feature = "development-build")] let running = setup_ctrlc_handler(); - const CYCLE_TARGET_TIME: Duration = Duration::from_micros(700); - // for the "hot thread" let (sender, receiver) = smol::channel::unbounded(); let (main_sender, main_receiver) = smol::channel::unbounded(); From 528952238d09322244903a52e5444df77dbd36e9 Mon Sep 17 00:00:00 2001 From: Christian <80114847+TheBest6337@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:54:10 +0100 Subject: [PATCH 19/20] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index d98f78e0..78e024c7 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -26,6 +26,7 @@ If applicable, add screenshots from the HMI display or photos of the machine scr **Machine Information (please complete the following):** - Machine Type: [Winder2, Laser, Aquapath...] - Control Software Version: [e.g. 2.4.1] + - Settings: [e.g. Different Gear Ratios, PID Settings, …] **Device Information (if issue occurs on external device):** - Device Type: [e.g. Tablet, PLC, Remote Control Panel] From 0b30ae9a85d44f37791f1a7e1cc733e0f240ba87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20Kr=C3=A4mer?= <93094049+kraemr@users.noreply.github.com> Date: Thu, 5 Feb 2026 17:34:48 +0100 Subject: [PATCH 20/20] =?UTF-8?q?removed=20excessive=20logging,=20simplifi?= =?UTF-8?q?ed=20socketio=20task=20with=20actual=20error=20printed=20?= =?UTF-8?q?=E2=80=A6=20(#1122)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * removed excessive logging, simplified socketio task with actual error message * fixed formatting --- server/src/main.rs | 17 +++--------- server/src/socketio/queue.rs | 50 ++++++++++-------------------------- 2 files changed, 17 insertions(+), 50 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index a7e009ba..852c6813 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -15,9 +15,11 @@ use machines::{ serial::{devices::laser::Laser, init::SerialDetection}, winder2::api::GenericEvent, }; -use socketio::main_namespace::{ - MainNamespaceEvents, ethercat_devices_event::EthercatDevicesEventBuilder, +use socketio::{ + main_namespace::{MainNamespaceEvents, ethercat_devices_event::EthercatDevicesEventBuilder}, + queue::start_socketio_queue, }; + #[cfg(feature = "development-build")] use std::sync::atomic::{AtomicBool, Ordering}; use utils::start_dnsmasq; @@ -52,7 +54,6 @@ use crate::{ setup::setup_loop, }, modbus_tcp::start_modbus_tcp_discovery, - socketio::queue::socketio_queue_worker, }; #[cfg(feature = "mock-machine")] @@ -323,15 +324,6 @@ async fn handle_async_requests(recv: Receiver, shared_state: tracing::warn!("Async handler task finished"); } -pub async fn start_socketio_queue(app_state: Arc) { - let app_state = app_state.as_ref(); - loop { - let res = socketio_queue_worker(app_state).await; - tracing::error!("SocketIO task finished, but should never finish: {:?}", res); - tracing::error!("Restarting SocketIO..."); - } -} - #[cfg(feature = "development-build")] fn setup_ctrlc_handler() -> Arc { let running = Arc::new(AtomicBool::new(true)); @@ -384,7 +376,6 @@ fn main() { #[cfg(not(feature = "mock-machine"))] smol::spawn(start_interface_discovery(app_state.clone(), sender)).detach(); - smol::spawn(start_modbus_tcp_discovery(app_state.clone())).detach(); smol::block_on(async { diff --git a/server/src/socketio/queue.rs b/server/src/socketio/queue.rs index ea654431..4091e598 100644 --- a/server/src/socketio/queue.rs +++ b/server/src/socketio/queue.rs @@ -1,6 +1,6 @@ use crate::app_state::SharedState; -use std::{sync::Arc, time::Instant}; -use tracing::{debug, info, instrument, trace}; +use std::sync::Arc; +use tracing::{error, info, instrument, trace}; /// Send a single event with retry logic #[instrument(skip_all)] @@ -12,7 +12,7 @@ async fn send_event_with_retry( loop { // check if socket is still connected if !socket.connected() { - trace!( + info!( socket_id = ?socket.id, event = %event.name, "Socket disconnected, skipping event" @@ -32,7 +32,7 @@ async fn send_event_with_retry( } Err(e) => match e { socketioxide::SendError::Serialize(serialize_error) => { - trace!( + info!( socket_id = ?socket.id, event = %event.name, error = %serialize_error, @@ -45,7 +45,7 @@ async fn send_event_with_retry( continue; // Retry sending the event } socketioxide::SocketError::Closed => { - trace!( + info!( socket_id = ?socket.id, event = %event.name, "Socket closed, skipping event" @@ -58,40 +58,16 @@ async fn send_event_with_retry( } } -pub async fn socketio_queue_worker(app_state: &SharedState) { - tracing::info!("SocketIO global queue listener started"); - let mut event_count = 0; - let mut batch_start = Instant::now(); - - while let Ok((socket, event)) = app_state.socketio_setup.socket_queue_rx.recv().await { - event_count += 1; - - send_event_with_retry(&socket, &event).await; - - if batch_start.elapsed().as_secs() >= 5 { - let elapsed = batch_start.elapsed(); - if event_count > 0 { - debug!( - "[{}::socketio_queue_worker] Processed {} events in {:.2?} ({:.1} events/s)", - module_path!(), - event_count, - elapsed, - event_count as f64 / elapsed.as_secs_f64(), - ); - } - event_count = 0; - batch_start = Instant::now(); - } - } - - info!("SocketIO global queue listener stopped"); -} - pub async fn start_socketio_queue(app_state: Arc) { let app_state = app_state.as_ref(); loop { - let res = socketio_queue_worker(app_state).await; - tracing::error!("SocketIO task finished, but should never finish: {:?}", res); - tracing::error!("Restarting SocketIO..."); + let res = app_state.socketio_setup.socket_queue_rx.recv().await; + match res { + Ok((socket, event)) => send_event_with_retry(&socket, &event).await, + Err(e) => { + error!("SocketIO global queue listener stopped: {:?}", e); + break; + } + } } }