diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a9631fcd5..4db68f612 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -70,12 +70,10 @@ jobs: PACKAGE_VERSION=`node -e "console.log(require('./src/package.json').version)"` mkdir -p releases/linux ls -al output - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-x86_64.AppImage" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x86_64.AppImage" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-amd64.deb" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-amd64.deb" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-armv7l.AppImage" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.AppImage" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-armv7l.deb" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.deb" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-arm64.AppImage" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64.AppImage" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-arm64.deb" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64.deb" + cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-x86_64.AppImage" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-Linux-Intel-64Bit.AppImage" + cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-amd64.deb" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-Linux-Intel-64Bit.deb" + cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-arm64.AppImage" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-Linux-ARM-64Bit.AppImage" + cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-arm64.deb" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-Linux-ARM-64Bit.deb" ls -al output releases/linux if [[ "$GITHUB_REF_TYPE" == "branch" && "$GITHUB_REF_NAME" == "master" ]]; then yarn github-release delete \ diff --git a/README.md b/README.md index e2b83310c..68c77c603 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,12 @@ Some things that we’re looking to accomplish with this sender: ## 💻 Download [![Github All Releases](https://img.shields.io/github/downloads/Sienci-Labs/gsender/total.svg)]() gSender is available for the following systems and does not yet support headless Pi operation -| ![Windows](https://github.com/EgoistDeveloper/operating-system-logos/blob/master/src/48x48/WIN.png)
Windows (x32) | ![Windows](https://github.com/EgoistDeveloper/operating-system-logos/blob/master/src/48x48/WIN.png)
Windows (x64) | ![Mac](https://github.com/EgoistDeveloper/operating-system-logos/blob/master/src/48x48/MAC.png)
Mac (Intel) | ![Mac](https://github.com/EgoistDeveloper/operating-system-logos/blob/master/src/48x48/MAC.png)
Mac (ARM64) | ![Linux](https://github.com/EgoistDeveloper/operating-system-logos/blob/master/src/48x48/LIN.png)
Linux | ![RasPi](https://github.com/iiiypuk/rpi-icon/blob/master/48.png)
Pi (32) | ![RasPi](https://github.com/iiiypuk/rpi-icon/blob/master/48.png)
Pi (64) | -|-|-|-|-|-|-|- - ``` Available ``` [EXE](https://github.com/Sienci-Labs/gsender/releases/download/v1.2.2/gSender-1.2.2-x32.exe) | ``` Available ``` [EXE](https://github.com/Sienci-Labs/gsender/releases/download/v1.2.2/gSender-1.2.2-x64.exe) | ``` Available ``` [DMG](https://github.com/Sienci-Labs/gsender/releases/download/v1.2.2/gSender-1.2.2.dmg) | ``` Available ``` [DMG](https://github.com/Sienci-Labs/gsender/releases/download/v1.2.2/gSender-1.2.2-arm64.dmg) | ``` Available ``` [DEB](https://github.com/Sienci-Labs/gsender/releases/download/v1.2.2/gSender_1.2.2_amd64.deb) | ``` Available ``` [ApIm](https://github.com/Sienci-Labs/gsender/releases/download/v1.2.2/gSender-1.2.2-armv7l.AppImage)| ``` Available ``` [DEB](https://github.com/Sienci-Labs/gsender/releases/download/v1.2.2/gSender_1.2.2_bullseye.deb) + +| Windows (x64) | Mac (Intel) | Linux (Intel) | Linux (ARM) | Pi (64 bit) | +|-----------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------| +| | | | | | +| ``` Available ``` [EXE](https://github.com/Sienci-Labs/gsender/releases/download/v1.4.1/gSender-1.4.1-Windows-64Bit.exe) | ``` Available ``` [DMG](https://github.com/Sienci-Labs/gsender/releases/download/v1.4.1/gSender-1.4.1-Mac-Intel-64Bit.dmg) | ``` Available ``` [DEB](https://github.com/Sienci-Labs/gsender/releases/download/v1.4.1/gSender-Edge-1.4.1-Linux-Intel-64Bit.deb) | ``` Available ``` [DEB](https://github.com/Sienci-Labs/gsender/releases/download/v1.4.1/gSender-Edge-1.4.1-Linux-ARM-64Bit.deb) | ``` Available ``` [DEB](https://github.com/Sienci-Labs/gsender/releases/download/v1.4.1/gSender-Edge-1.4.1-Linux-PI-64Bit.deb) | + [Check out the latest releases here.](https://github.com/Sienci-Labs/gsender/releases/) @@ -99,7 +102,17 @@ gSender is also designed in a way that it can be run locally on your computer br ## 🕣 Development History -### 1.4.0 (January X, 2024) +### 1.4.1 (January 26, 2024) +- Fix for black screen on application startup in some situations +- Fix for jog buttons on UI not registering click events correctly on some operating systems +- Strip comments sent to controller to prevent buffer overflow and better support Shapeoko +- Fix issue with firmware tool not updating values correctly if settings limited by search bar +- Handle missing file name in recent files +- Updated EEPROM values for travel on multiple Sienci profiles +- Fixed issue with surfacing tool crashing in some situations +- Fixed several bugs with gamepad support + +### 1.4.0 (January 23, 2024) - Added Rotary Mode - gSender is now able to run 2+1 axis files on grbl and 4 axis files on grblHAL - Visualizer updated to support 4 axis rotations diff --git a/_appveyor.yml b/_appveyor.yml deleted file mode 100644 index e5815cee2..000000000 --- a/_appveyor.yml +++ /dev/null @@ -1,548 +0,0 @@ -# https://stefanscherer.github.io/use-appveyor-to-build-multi-arch-docker-image/ - -version: "{build}-{branch}" -branches: - only: - - master - - dev - - /v\d+\.\d+\.\d+/ - - /v\d+\.\d+\.\d+-EDGE/ - -environment: - matrix: - #- job_name: Windows build (x86) - # appveyor_build_worker_image: Visual Studio 2019 - # nodejs_version: "16" - # ARCH: x86 - - job_name: Windows build (x64) - appveyor_build_worker_image: Visual Studio 2019 - nodejs_version: "16" - ARCH: x64 - - job_name: macOS build (x64) - appveyor_build_worker_image: macos - nodejs_version: "16" - ARCH: x64 - #- job_name: macOS build (arm64) - # appveyor_build_worker_image: macos - # nodejs_version: "16" - # ARCH: arm64 - - job_name: Linux build (amd64) - appveyor_build_worker_image: Ubuntu2004 - nodejs_version: "16" - ARCH: amd64 - - job_name: Linux build (arm64) - appveyor_build_worker_image: Ubuntu2004 - nodejs_version: "16" - ARCH: arm64 - global: - GH_TOKEN: - secure: jqBCwY/hOwLqF2LEGxVwiKGJC+YaXDn43WYTfh4d27NSKbWkug09qMdd1EVNtX2/ - GITHUB_TOKEN: - secure: jqBCwY/hOwLqF2LEGxVwiKGJC+YaXDn43WYTfh4d27NSKbWkug09qMdd1EVNtX2/ - -for: - # Linux - - - matrix: - only: - - job_name: Linux build (amd64) - - job_name: Linux build (arm) - - job_name: Linux build (arm64) - fast_finish: true - - init: - - uname -a - - git --version - - git config --global core.autocrlf false - - git config --global user.name "AppVeyor" - - git config --global user.email "appveyor@ci.appveyor.com" - - sh: | - export CI_BRANCH=$APPVEYOR_REPO_BRANCH - export CI_BUILD_NUMBER=$APPVEYOR_BUILD_NUMBER - export CI_COMMIT=$APPVEYOR_REPO_COMMIT - export CI_COMMIT_SHORT=${APPVEYOR_REPO_COMMIT:0:8} - export CI_COMMIT_TIMESTAMP=$APPVEYOR_REPO_COMMIT_TIMESTAMP - export CI_TAG=$APPVEYOR_REPO_TAG_NAME - echo "• ARCH=$ARCH" - echo "• CI_BRANCH=$CI_BRANCH" - echo "• CI_BUILD_NUMBER=$CI_BUILD_NUMBER" - echo "• CI_COMMIT=$CI_COMMIT" - echo "• CI_COMMIT_SHORT=$CI_COMMIT_SHORT" - echo "• CI_COMMIT_TIMESTAMP=$CI_COMMIT_TIMESTAMP" - echo "• CI_TAG=$CI_TAG" - install: - # https://github.com/cfillion/reapack/blob/master/.appveyor.yml - - | - sudo cp -af /etc/apt/sources.list /etc/apt/sources.list.old - sudo sed -i '/arch=/! s/^deb/deb [arch=amd64,i386]/' /etc/apt/sources.list - awk ' - $3 !~ /ubuntu\.com/ { next } - $1 == "deb" { - $2 = "[arch=armhf,arm64]"; - $3 = "http://ports.ubuntu.com/ubuntu-ports/" - } 1' /etc/apt/sources.list | sudo dd of=/etc/apt/sources.list.d/ports.list - diff -uN /etc/apt/sources.list.old /etc/apt/sources.list - cat /etc/apt/sources.list.d/ports.list - - sudo dpkg --print-architecture - - sudo dpkg --add-architecture arm64 - - sudo dpkg --add-architecture armhf - - sudo dpkg --add-architecture i386 - - sudo dpkg --print-foreign-architectures - - sudo apt-get update --allow-releaseinfo-change - - sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick gcc-multilib g++-multilib rpm libudev-dev - - nvm install $nodejs_version - - npm config set loglevel warn - - npm config set scripts-prepend-node-path auto - - npm install -g yarn - - yarn - - build_script: - - sh: | - yarn clean - yarn lint - yarn test - if [[ -z "$CI_TAG" ]]; then - yarn build-latest - else - yarn build - fi - - sh: | - # i386 - if [[ "$ARCH" == "i386" ]]; then - GIT_COMMIT_LOG=`git log -1 --format='%ci %H %s'` - PACKAGE_NAME=`node -e "console.log(require('./src/package.json').name)"` - PACKAGE_VERSION=`node -e "console.log(require('./src/package.json').version)"` - PRODUCT_NAME=gSender - yarn build:linux-ia32 - ls -al output output/* - mkdir -p releases/linux - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}.i686.rpm" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.i686.rpm" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-i386.AppImage" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-i386.AppImage" - cp -af "output/${PACKAGE_NAME}_${PACKAGE_VERSION}_i386.deb" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-i386.deb" - pushd releases/linux - ln -sf ../../output/linux-ia32-unpacked "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-ia32" - tar zcfh "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-ia32.tar.gz" "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-ia32" - rm -f "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-ia32"; - popd - ls -al releases/linux/* - if [[ "$CI_BRANCH" == "master" && -z "$CI_TAG" ]]; then - yarn github-release delete \ - --owner=gSender \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - "*-linux-i386.AppImage" \ - "*-linux-i386.deb" \ - "*-linux.i686.rpm" \ - "*-linux-ia32.tar.gz"; - yarn github-release upload \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - --body="${COMMIT_LOG}" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.i686.rpm" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-i386.AppImage" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-i386.deb" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-ia32.tar.gz"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.i686.rpm"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-i386.AppImage"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-i386.deb"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-ia32.tar.gz"; - fi - fi - - sh: | - # amd64 - if [[ "$ARCH" == "amd64" ]]; then - GIT_COMMIT_LOG=`git log -1 --format='%ci %H %s'` - PACKAGE_NAME=`node -e "console.log(require('./src/package.json').name)"` - PACKAGE_VERSION=`node -e "console.log(require('./src/package.json').version)"` - PRODUCT_NAME=gSender - yarn build:linux-x64 - ls -al output output/* - mkdir -p releases/linux - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}.x86_64.rpm" "releases/linux/gSender-${PACKAGE_VERSION}-Linux-Intel-64Bit.rpm" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}.AppImage" "releases/linux/gSender-${PACKAGE_VERSION}-Linux-Intel-64Bit.AppImage" - cp -af "output/${PACKAGE_NAME}_${PACKAGE_VERSION}_amd64.deb" "releases/linux/gSender-${PACKAGE_VERSION}-Linux-Intel-64Bit.deb" - pushd releases/linux - ln -sf ../../output/linux-unpacked "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x64" - tar zcfh "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x64.tar.gz" "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x64" - rm -f "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x64" - popd - ls -al releases/linux/* - if [[ "$CI_BRANCH" == "master" && -z "$CI_TAG" ]]; then - yarn github-release delete \ - --owner=Sienic \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - "*-Linux-Intel-64Bit.rpm" \ - "*-Linux-Intel-64Bit.AppImage" \ - "*-Linux-Intel-64Bit.deb" \ - "*-linux-x64.tar.gz"; - yarn github-release upload \ - --owner=sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - --body="${GIT_COMMIT_LOG}" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.x86_64.rpm" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x86_64.AppImage" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-amd64.deb" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x64.tar.gz"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.x86_64.rpm"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x86_64.AppImage"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-amd64.deb"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-x64.tar.gz"; - fi - fi - - sh: | - # arm - if [[ "$ARCH" == "arm" ]]; then - GIT_COMMIT_LOG=`git log -1 --format='%ci %H %s'` - PACKAGE_NAME=`node -e "console.log(require('./src/package.json').name)"` - PACKAGE_VERSION=`node -e "console.log(require('./src/package.json').version)"` - PRODUCT_NAME=gSender - yarn build:linux-armv7l - ls -al output output/* - mkdir -p releases/linux - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}.armv7l.rpm" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.armv7l.rpm" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-armv7l.AppImage" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.AppImage" - cp -af "output/${PACKAGE_NAME}_${PACKAGE_VERSION}_armv7l.deb" "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.deb" - pushd releases/linux - ln -sf ../../output/linux-armv7l-unpacked "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l" - tar zcfh "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.tar.gz" "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l" - rm -f "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l" - popd - ls -al releases/linux/* - if [[ "$CI_BRANCH" == "master" && -z "$CI_TAG" ]]; then - yarn github-release delete \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - "*-linux.armv7l.rpm" \ - "*-linux-armv7l.AppImage" \ - "*-linux-armv7l.deb" \ - "*-linux-armv7l.tar.gz"; - yarn github-release upload \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - --body="${GIT_COMMIT_LOG}" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.armv7l.rpm" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.AppImage" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.deb" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.tar.gz"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.armv7l.rpm"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.AppImage"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.deb"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-armv7l.tar.gz"; - fi - fi - - sh: | - # arm64 - if [[ "$ARCH" == "arm64" ]]; then - GIT_COMMIT_LOG=`git log -1 --format='%ci %H %s'` - PACKAGE_NAME=`node -e "console.log(require('./src/package.json').name)"` - PACKAGE_VERSION=`node -e "console.log(require('./src/package.json').version)"` - PRODUCT_NAME=gSender - yarn build:linux-arm64 - ls -al output output/* - mkdir -p releases/linux - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}.arm64.rpm" "releases/linux/gSender-${PACKAGE_VERSION}-Linux-ARM-64Bit.rpm" - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-arm64.AppImage" "releases/linux/gSender-${PACKAGE_VERSION}-Linux-ARM-64Bit.AppImage" - cp -af "output/${PACKAGE_NAME}_${PACKAGE_VERSION}_arm64.deb" "releases/linux/gSender-${PACKAGE_VERSION}-Linux-ARM-64Bit.deb" - pushd releases/linux - ln -sf ../../output/linux-arm64-unpacked "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64" - tar zcfh "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64.tar.gz" "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64" - rm -f "${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64" - popd - ls -al releases/linux/* - if [[ "$CI_BRANCH" == "master" && -z "$CI_TAG" ]]; then - yarn github-release delete \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - "*-linux.arm64.rpm" \ - "*-linux-arm64.AppImage" \ - "*-linux-arm64.deb" \ - "*-linux-arm64.tar.gz"; - yarn github-release upload \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - --body="${GIT_COMMIT_LOG}" \ - "releases/linux/gSender-${PACKAGE_VERSION}-Linux-ARM-64Bit.rpm" \ - "releases/linux/gSender-${PACKAGE_VERSION}-Linux-ARM-64Bit.AppImage" \ - "releases/linux/gSender-${PACKAGE_VERSION}-Linux-ARM-64Bit.deb" \ - "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64.tar.gz"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux.arm64.rpm"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64.AppImage"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64.deb"; - #rm -f "releases/linux/${PACKAGE_NAME}-${PACKAGE_VERSION}-linux-arm64.tar.gz"; - fi - fi - test: off - - # Packaging artifacts - # https://www.appveyor.com/docs/packaging-artifacts - artifacts: - - path: releases/linux/* - - # Publishing artifacts to GitHub Releases - # https://www.appveyor.com/docs/deployment/github - deploy: - - provider: GitHub - auth_token: - secure: jqBCwY/hOwLqF2LEGxVwiKGJC+YaXDn43WYTfh4d27NSKbWkug09qMdd1EVNtX2/ - draft: true - prerelease: false - on: - appveyor_repo_tag: true # deploy on tag push only - nodejs_version: "16" - - # macOS - - - matrix: - only: - - job_name: macOS build (x64) - - job_name: macOS build (arm64) - fast_finish: true - - init: - - uname -a - - git --version - - git config --global core.autocrlf false - - git config --global user.name "AppVeyor" - - git config --global user.email "appveyor@ci.appveyor.com" - - sh: | - export CI_BRANCH=$APPVEYOR_REPO_BRANCH - export CI_BUILD_NUMBER=$APPVEYOR_BUILD_NUMBER - export CI_COMMIT=$APPVEYOR_REPO_COMMIT - export CI_COMMIT_SHORT=${APPVEYOR_REPO_COMMIT:0:8} - export CI_COMMIT_TIMESTAMP=$APPVEYOR_REPO_COMMIT_TIMESTAMP - export CI_TAG=$APPVEYOR_REPO_TAG_NAME - echo "• ARCH=$ARCH" - echo "• CI_BRANCH=$CI_BRANCH" - echo "• CI_BUILD_NUMBER=$CI_BUILD_NUMBER" - echo "• CI_COMMIT=$CI_COMMIT" - echo "• CI_COMMIT_SHORT=$CI_COMMIT_SHORT" - echo "• CI_COMMIT_TIMESTAMP=$CI_COMMIT_TIMESTAMP" - echo "• CI_TAG=$CI_TAG" - install: - - nvm install $nodejs_version - - npm config set loglevel warn - - npm config set scripts-prepend-node-path auto - - npm install -g yarn - - yarn - - build_script: - - sh: | - yarn clean - yarn lint - yarn test - if [[ -z "$CI_TAG" ]]; then - yarn build-latest - else - yarn build - fi - - sh: | - # x64 - if [[ "$ARCH" == "x64" ]]; then - GIT_COMMIT_LOG=`git log -1 --format='%ci %H %s'` - PACKAGE_NAME=`node -e "console.log(require('./src/package.json').name)"` - PACKAGE_VERSION=`node -e "console.log(require('./src/package.json').version)"` - PRODUCT_NAME=gSender - yarn build:macos-x64 - ls -al output output/* - mkdir -p releases/macos - cp -af "output/${PACKAGE_NAME}-${PACKAGE_VERSION}-x64.dmg" "releases/macos/gSender-${PACKAGE_VERSION}-Mac-Intel-64Bit.dmg" - ls -al releases/macos/* - if [[ "$CI_BRANCH" == "master" && -z "$CI_TAG" ]]; then - yarn github-release delete \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - "*-macos.x64.dmg"; - yarn github-release upload \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - --body="${GIT_COMMIT_LOG}" \ - "releases/macos/gSender-${PACKAGE_VERSION}-Mac-Intel-64Bit.dmg"; - #rm -f "releases/macos/${PACKAGE_NAME}-${PACKAGE_VERSION}-macos.x64.dmg"; - fi - fi - - sh: | - # arm64 - if [[ "$ARCH" == "arm64" ]]; then - GIT_COMMIT_LOG=`git log -1 --format='%ci %H %s'` - PACKAGE_NAME=`node -e "console.log(require('./src/package.json').name)"` - PACKAGE_VERSION=`node -e "console.log(require('./src/package.json').version)"` - PRODUCT_NAME=gSender - yarn build:macos-arm64 - ls -al output output/* - mkdir -p releases/macos - cp -af "output/*.dmg" "releases/macos/${PACKAGE_NAME}-${PACKAGE_VERSION}-macos.arm64.dmg" - ls -al releases/macos/* - if [[ "$CI_BRANCH" == "master" && -z "$CI_TAG" ]]; then - yarn github-release delete \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - "*-macos.arm64.dmg"; - yarn github-release upload \ - --owner=Sienci \ - --repo=sender \ - --tag="${CI_BRANCH}" \ - --release-name="${CI_BRANCH}" \ - --body="${GIT_COMMIT_LOG}" \ - "releases/macos/${PACKAGE_NAME}-${PACKAGE_VERSION}-macos.arm64.dmg"; - #rm -f "releases/macos/${PACKAGE_NAME}-${PACKAGE_VERSION}-macos.arm64.dmg"; - fi - fi - test: off - - # Packaging artifacts - # https://www.appveyor.com/docs/packaging-artifacts - artifacts: - - path: releases/macos/* - - # Publishing artifacts to GitHub Releases - # https://www.appveyor.com/docs/deployment/github - deploy: - - provider: GitHub - auth_token: - secure: jqBCwY/hOwLqF2LEGxVwiKGJC+YaXDn43WYTfh4d27NSKbWkug09qMdd1EVNtX2/ - draft: true - prerelease: false - on: - appveyor_repo_tag: true # deploy on tag push only - nodejs_version: "16" - - # Windows - - - matrix: - only: - - job_name: Windows build (x64) - - job_name: Windows build (x86) - fast_finish: true - - init: - - git --version - - git config --global core.autocrlf false - - git config --global user.name "AppVeyor" - - git config --global user.email "appveyor@ci.appveyor.com" - - ps: | - $env:CI_BRANCH = $env:APPVEYOR_REPO_BRANCH - $env:CI_BUILD_NUMBER = $env:APPVEYOR_BUILD_NUMBER - $env:CI_COMMIT = $env:APPVEYOR_REPO_COMMIT - $env:CI_COMMIT_SHORT = ${env:APPVEYOR_REPO_COMMIT}.SubString(0,8) - $env:CI_COMMIT_TIMESTAMP = $env:APPVEYOR_REPO_COMMIT_TIMESTAMP - $env:CI_TAG = $env:APPVEYOR_REPO_TAG_NAME - Write-Host "• ARCH=$env:ARCH" - Write-Host "• CI_BRANCH=$env:CI_BRANCH" - Write-Host "• CI_BUILD_NUMBER=$env:CI_BUILD_NUMBER" - Write-Host "• CI_COMMIT=$env:CI_COMMIT" - Write-Host "• CI_COMMIT_SHORT=$env:CI_COMMIT_SHORT" - Write-Host "• CI_COMMIT_TIMESTAMP=$env:CI_COMMIT_TIMESTAMP" - Write-Host "• CI_TAG=$env:CI_TAG" - install: - - ps: Install-Product node $env:nodejs_version - - npm config set loglevel warn - - npm config set scripts-prepend-node-path auto - - npm config set python C:\Python310 - - npm install -g yarn - - yarn - - build_script: - - ps: | - yarn clean - yarn lint - yarn test - if (-not $env:CI_TAG) { - yarn build-latest - } else { - yarn build - } - - ps: | - if ($env:ARCH -eq "x64") { - $GIT_COMMIT_LOG = git log -1 --format='%ci %H %s' - $PACKAGE_NAME = node -e "console.log(require('./src/package.json').name)" - $PACKAGE_VERSION = node -e "console.log(require('./src/package.json').version)" - $PRODUCT_NAME = "gSender" - mkdir -Force -Path releases\windows - yarn build:windows - Get-ChildItem output - Copy-Item "output\${PACKAGE_NAME}-${PACKAGE_VERSION}-x64.exe" "releases\windows\gSender-${PACKAGE_VERSION}-Windows-64Bit.exe" - Get-ChildItem releases\windows - if ($env:CI_BRANCH -eq "master" -And -not $env:CI_TAG) { - yarn github-release delete ` - --owner=Sienci ` - --repo=sender ` - --tag="${env:CI_BRANCH}-latest" ` - --release-name="${env:CI_BRANCH}" ` - "*-windows-x64.exe" - yarn github-release upload ` - --owner=sienci ` - --repo=sender ` - --tag="${env:CI_BRANCH}-latest" ` - --release-name="${env:CI_BRANCH}" ` - --body="${GIT_COMMIT_LOG}" ` - "releases\windows\gSender-${PACKAGE_VERSION}-Windows-64Bit.exe" - #Remove-Item "releases\windows\${PACKAGE_NAME}-${PACKAGE_VERSION}-windows-x64.exe" - } - } - - ps: | - if ($env:ARCH -eq "x86") { - $GIT_COMMIT_LOG = git log -1 --format='%ci %H %s' - $PACKAGE_NAME = node -e "console.log(require('./src/package.json').name)" - $PACKAGE_VERSION = node -e "console.log(require('./src/package.json').version)" - $PRODUCT_NAME = "gSender" - mkdir -Force -Path releases\windows - yarn build:windows - Get-ChildItem output - Copy-Item "output\${PRODUCT_NAME} Setup ${PACKAGE_VERSION}.exe" "releases\windows\gSender-${PACKAGE_VERSION}-windows-x86.exe" - Get-ChildItem releases\windows - if ($env:CI_BRANCH -eq "master" -And -not $env:CI_TAG) { - yarn github-release delete ` - --owner=Sienci ` - --repo=sender ` - --tag="${env:CI_BRANCH}-latest" ` - --release-name="${env:CI_BRANCH}" ` - "*-windows-x86.exe" - yarn github-release upload ` - --owner=sienci ` - --repo=sender ` - --tag="${env:CI_BRANCH}-latest" ` - --release-name="${env:CI_BRANCH}" ` - --body="${GIT_COMMIT_LOG}" ` - "releases\windows\${PACKAGE_NAME}-${PACKAGE_VERSION}-windows-x86.exe" - #Remove-Item "releases\windows\${PACKAGE_NAME}-${PACKAGE_VERSION}-windows-x86.exe" - } - } - test: off - - # Packaging artifacts - # https://www.appveyor.com/docs/packaging-artifacts - artifacts: - - path: releases\windows\* - - # Publishing artifacts to GitHub Releases - # https://www.appveyor.com/docs/deployment/github - deploy: - - provider: GitHub - auth_token: - secure: jqBCwY/hOwLqF2LEGxVwiKGJC+YaXDn43WYTfh4d27NSKbWkug09qMdd1EVNtX2/ - draft: true - prerelease: false - on: - appveyor_repo_tag: true # deploy on tag push only - nodejs_version: "16" diff --git a/package.json b/package.json index 26dd73c32..1b30927a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gSender", - "version": "1.4.0", + "version": "1.4.1", "description": "Electron sender for GRBL based CNC machines", "author": { "name": "Sienci Labs ", @@ -58,11 +58,11 @@ "build:linux-ia32": "bash -c 'scripts/electron-builder.sh --linux --ia32'", "build:linux-x64": "bash -c 'scripts/electron-builder.sh --linux --x64'", "build:linux-armv7l": "bash -c 'scripts/electron-builder.sh --linux --armv7l'", - "build:linux": "bash -c 'scripts/electron-builder.sh --linux --x64 --arm64 --armv7l'", + "build:linux": "bash -c 'scripts/electron-builder.sh --linux --x64 --arm64'", "build:linux-arm64": "bash -c 'scripts/electron-builder.sh --linux --arm64'", "build:windows-ia32": "bash -c 'scripts/electron-builder.sh --windows --ia32'", "build:windows-x64": "bash -c 'scripts/electron-builder.sh --windows --x64'", - "build:windows": "bash -c 'scripts/electron-builder.sh --windows --ia32 --x64'", + "build:windows": "bash -c 'scripts/electron-builder.sh --windows --x64'", "start": "cross-env ./bin/gsender", "start-electron": "electron ./dist/gsender/main", "watch-dev": "cross-env NODE_ENV=development webpack-cli --watch --config webpack.config.server.development.js", @@ -83,7 +83,7 @@ "artifactName": "${name}-${version}-${arch}.${ext}", "asar": false, "asarUnpack": [], - "productName": "gSender Edge", + "productName": "gSender", "generateUpdatesFilesForAllChannels": true, "npmRebuild": false, "extraResources": [ @@ -411,5 +411,11 @@ "webpack-manifest-plugin": "~2.0.4", "webpack-node-externals": "~1.7.2", "write-file-webpack-plugin": "~4.5.0" + }, + "overrides": { + "@react-pdf/layout": "3.6.4" + }, + "resolutions": { + "@react-pdf/layout": "3.6.4" } } diff --git a/src/app/components/GcodeViewer/index.js b/src/app/components/GcodeViewer/index.js index 0fe6b3d1c..916f1576a 100644 --- a/src/app/components/GcodeViewer/index.js +++ b/src/app/components/GcodeViewer/index.js @@ -11,7 +11,7 @@ import { Container, GcodeContainer } from './styled'; const GcodeViewer = ({ gcode }) => { const handleCopy = throttle(async () => { - await navigator.clipboard.writeText(gcode); + await navigator.clipboard?.writeText(gcode); Toaster.pop({ msg: 'Copied G-code to Clipboard', diff --git a/src/app/containers/Firmware/components/HalSettings/index.jsx b/src/app/containers/Firmware/components/HalSettings/index.jsx index 692612515..5c317e70f 100644 --- a/src/app/containers/Firmware/components/HalSettings/index.jsx +++ b/src/app/containers/Firmware/components/HalSettings/index.jsx @@ -7,12 +7,16 @@ import CategoryTag from 'Containers/Firmware/components/Settings/CategoryTag'; const HalSettings = ({ descriptions }) => { const { settings, setSettings, setSettingsToApply } = useContext(FirmwareContext); - + console.log(settings); const handleSettingsChange = (index) => (value) => { setSettingsToApply(true); setSettings(prev => { + console.log(`index: ${index}`); const updated = [...prev]; + console.log(updated[index]); + updated[index].value = value; + console.log(updated); return updated; }); }; @@ -66,7 +70,7 @@ const HalSettings = ({ descriptions }) => {
- +
diff --git a/src/app/containers/Firmware/components/defaultMachineProfiles.js b/src/app/containers/Firmware/components/defaultMachineProfiles.js index 049a46001..cd3ab49d0 100644 --- a/src/app/containers/Firmware/components/defaultMachineProfiles.js +++ b/src/app/containers/Firmware/components/defaultMachineProfiles.js @@ -472,112 +472,6 @@ export default [ 'laser': false, 'laserOnOutline': false, }, - { - 'id': 59, - 'company': '', - 'name': 'BlueCarve', - 'type': 'Bluey', - 'mm': { - 'width': 750, - 'depth': 750, - 'height': 85 - }, - 'in': { - 'width': 24, - 'depth': 24, - 'height': 3.55 - }, - 'endstops': false, - 'spindle': false, - 'coolant': false, - 'laser': false, - 'laserOnOutline': false, - }, - { - 'id': 55, - 'company': '', - 'name': 'BlueCarve', - 'type': 'Turbo', - 'mm': { - 'width': 750, - 'depth': 750, - 'height': 85 - }, - 'in': { - 'width': 24, - 'depth': 24, - 'height': 3.55 - }, - 'endstops': false, - 'spindle': false, - 'coolant': false, - 'laser': false, - 'laserOnOutline': false, - }, - { - 'id': 56, - 'company': '', - 'name': 'BlueCarve', - 'type': 'Turbo Z Upgrade', - 'mm': { - 'width': 750, - 'depth': 750, - 'height': 85 - }, - 'in': { - 'width': 24, - 'depth': 24, - 'height': 3.55 - }, - 'endstops': false, - 'spindle': false, - 'coolant': false, - 'laser': false, - 'laserOnOutline': false, - }, - { - 'id': 57, - 'company': '', - 'name': 'BlueCarve', - 'type': 'Trax', - 'mm': { - 'width': 750, - 'depth': 750, - 'height': 85 - }, - 'in': { - 'width': 24, - 'depth': 24, - 'height': 3.55 - }, - 'endstops': false, - 'spindle': false, - 'coolant': false, - 'laser': false, - 'laserOnOutline': false, - }, - { - 'id': 58, - 'company': '', - 'name': 'BlueCarve', - 'type': 'Trax Z Upgrade', - 'mm': { - 'width': 750, - 'depth': 750, - 'height': 85 - }, - 'in': { - 'width': 24, - 'depth': 24, - 'height': 3.55 - }, - 'endstops': false, - 'spindle': false, - 'coolant': false, - 'laser': false, - 'laserOnOutline': false, - }, - { 'id': 47, 'company': '', diff --git a/src/app/containers/Firmware/eepromFiles/MK1_48x30.json b/src/app/containers/Firmware/eepromFiles/MK1_48x30.json index 4a89b07ae..f4925d3be 100644 --- a/src/app/containers/Firmware/eepromFiles/MK1_48x30.json +++ b/src/app/containers/Firmware/eepromFiles/MK1_48x30.json @@ -30,7 +30,7 @@ "$120": "750.000", "$121": "750.000", "$122": "500.000", - "$130": "1235.000", - "$131": "812.000", - "$132": "105.000" + "$130": "1230.000", + "$131": "820.000", + "$132": "110.000" } diff --git a/src/app/containers/Firmware/eepromFiles/MK2_12x30.json b/src/app/containers/Firmware/eepromFiles/MK2_12x30.json index 38823f639..f93ff6cae 100644 --- a/src/app/containers/Firmware/eepromFiles/MK2_12x30.json +++ b/src/app/containers/Firmware/eepromFiles/MK2_12x30.json @@ -30,7 +30,7 @@ "$120":"750.000", "$121":"750.000", "$122":"500.000", - "$130":"864.000", - "$131":"304.000", - "$132":"122.000" + "$130":"810.000", + "$131":"355.000", + "$132":"120.000" } diff --git a/src/app/containers/Firmware/eepromFiles/MK2_30x30.json b/src/app/containers/Firmware/eepromFiles/MK2_30x30.json index 9735342b5..217c4660a 100644 --- a/src/app/containers/Firmware/eepromFiles/MK2_30x30.json +++ b/src/app/containers/Firmware/eepromFiles/MK2_30x30.json @@ -30,7 +30,7 @@ "$120":"750.000", "$121":"750.000", "$122":"500.000", - "$130":"816.000", - "$131":"864.000", - "$132":"122.000" -} \ No newline at end of file + "$130":"810.000", + "$131":"855.000", + "$132":"120.000" +} diff --git a/src/app/containers/Firmware/eepromFiles/MK2_48x30.json b/src/app/containers/Firmware/eepromFiles/MK2_48x30.json index 4ac1c0336..435ae5ff8 100644 --- a/src/app/containers/Firmware/eepromFiles/MK2_48x30.json +++ b/src/app/containers/Firmware/eepromFiles/MK2_48x30.json @@ -30,7 +30,7 @@ "$120": "750.000", "$121": "750.000", "$122": "500.000", - "$130": "1276.000", - "$131": "864.000", - "$132": "122.000" + "$130": "1270.000", + "$131": "855.000", + "$132": "120.000" } diff --git a/src/app/containers/Firmware/eepromFiles/Sienci Long Mill12X12.json b/src/app/containers/Firmware/eepromFiles/Sienci Long Mill12X12.json index 12a9eb41e..9786e72ab 100644 --- a/src/app/containers/Firmware/eepromFiles/Sienci Long Mill12X12.json +++ b/src/app/containers/Firmware/eepromFiles/Sienci Long Mill12X12.json @@ -30,7 +30,7 @@ "$120":"750.000", "$121":"750.000", "$122":"500.000", - "$130":"304.000", - "$131":"304.000", - "$132":"105.000" -} \ No newline at end of file + "$130":"285.000", + "$131":"320.000", + "$132":"110.000" +} diff --git a/src/app/containers/Firmware/eepromFiles/Sienci Long Mill12X30.json b/src/app/containers/Firmware/eepromFiles/Sienci Long Mill12X30.json index fbeadd016..1b7791a28 100644 --- a/src/app/containers/Firmware/eepromFiles/Sienci Long Mill12X30.json +++ b/src/app/containers/Firmware/eepromFiles/Sienci Long Mill12X30.json @@ -30,7 +30,7 @@ "$120":"750.000", "$121":"750.000", "$122":"500.000", - "$130":"812.000", - "$131":"304.000", - "$132":"105.000" + "$130":"770.000", + "$131":"320.000", + "$132":"110.000" } diff --git a/src/app/containers/Firmware/eepromFiles/Sienci Long Mill30X30.json b/src/app/containers/Firmware/eepromFiles/Sienci Long Mill30X30.json index 3103cfb9f..ed2cb6cbc 100644 --- a/src/app/containers/Firmware/eepromFiles/Sienci Long Mill30X30.json +++ b/src/app/containers/Firmware/eepromFiles/Sienci Long Mill30X30.json @@ -30,7 +30,7 @@ "$120":"750.000", "$121":"750.000", "$122":"500.000", - "$130":"762.000", - "$131":"812.000", - "$132":"105.000" + "$130":"770.000", + "$131":"820.000", + "$132":"110.000" } diff --git a/src/app/containers/Firmware/index.jsx b/src/app/containers/Firmware/index.jsx index 81ef4b11b..34f036657 100644 --- a/src/app/containers/Firmware/index.jsx +++ b/src/app/containers/Firmware/index.jsx @@ -19,7 +19,7 @@ import styles from './index.styl'; import { collectUserUsageData } from '../../lib/heatmap'; const getFilteredEEPROM = (settings, eeprom = {}, halDescriptions = {}, halGroups = {}) => { - return Object.keys(eeprom).map((setting) => { + return Object.keys(eeprom).map((setting, index) => { const properties = settings.find(obj => { return obj.setting === setting; }); @@ -29,6 +29,7 @@ const getFilteredEEPROM = (settings, eeprom = {}, halDescriptions = {}, halGroup return { ...properties || {}, + globalIndex: index, setting: setting, value: eeprom[setting], ...halData, diff --git a/src/app/containers/Firmware/utils/index.js b/src/app/containers/Firmware/utils/index.js index 85922c3bd..fb8dfa59b 100644 --- a/src/app/containers/Firmware/utils/index.js +++ b/src/app/containers/Firmware/utils/index.js @@ -139,6 +139,8 @@ export const convertValueToArray = (value, possibilities) => { }; export const applyNewSettings = (settings, eeprom, setSettingsToApply) => { + console.log(settings); + let index22 = 200; // index of $22 - default is 200 because we have less eeprom values than that, so it will never be set to this value let index2021 = -1; // index of $20 or $21, whichever comes first let changedSettings = settings @@ -162,9 +164,8 @@ export const applyNewSettings = (settings, eeprom, setSettingsToApply) => { changedSettings[index22] = changedSettings[index2021]; changedSettings[index2021] = setting22; } - + changedSettings.push('$$'); // Add setting refresh to end so tool updates values controller.command('gcode', changedSettings); - controller.command('gcode', '$$'); //Needed so next time wizard is opened changes are reflected setSettingsToApply(false); Toaster.pop({ msg: 'Firmware Settings Updated', diff --git a/src/app/containers/Preferences/About/releases.json b/src/app/containers/Preferences/About/releases.json index 6b2cd94cd..78a73c7e2 100644 --- a/src/app/containers/Preferences/About/releases.json +++ b/src/app/containers/Preferences/About/releases.json @@ -1 +1 @@ -["### 1.4.0 (January X, 2024)","- Added Rotary Mode","- gSender is now able to run 4 axis files on both GRBL and grblHAL","- Visualizer updated to support 4 axis rotations","- A-axis DRO and jogging","- Rotary probing","- Added grblHAL controller support","- Connect to and run jobs as normal on any grblHAL device","- Connect over ethernet where hardware is supported","- New grblHAL specific firmware tool that is dynamically generated based on reported settings","- New UI elements where appropriate to support new functionality such as single axis homing","- Gamepad improvements","- Restructured logic and mapping of buttons to actions","- Add secondary functionality to buttons","- Added joystick MPG mode","- Added lockout button to deactivate gamepad when needed","- Improved job time estimation","- Significantly improved initial time estimation algorithm based on machine acceleration and max speeds","- Mid-job estimation uses initial estimate per line for more accurate remaining duration","- Multi-corner probing - touch off any corner using both standard and auto-zero touchplates","- Added Go To UI button to quickly go to an absolute or relative workspace coordinate","- Clearer distinction on planned lines vs cut lines - planned lines show up as a (customizable) yellow instead of the default cut gray","- Remote mode improvements","- Added QR code for easier navigation to remote address on phone","- Added workflow controls and unit selection to remote mode UI","- Added preference to prompt on Zero to prevent accidentally resetting zero on any axis","- Code block toolchange again supported","- Firmware active modals now displayed in diagnostic tab","- PRB values available to use in macros","- Files are now parsed once per run time","- Fix for DRO precision in some situations","- Improved job stats area - now tracks jobs per com port, more information about each job run and the number of problems encountered","- Maintenance reminders - set up and customize maintenance reminders to prompt tasks after specific run time totals have occured","- Improved alarm and error recording","### 1.2.2 (Jul 6, 2023)","- Fix for overrides leading to gcode errors","- Override value correctly updates with keybind usage","- Using override keybind should now display the override panel","- Multiple tool changes in a single file now display the correct tool in the Wizard","- Controller binds should work with tool change wizard active","- Spindle RPM no longer incorrectly converting units","- Spindle slider now reflects EEPROM values for min and max","- Jog speed properly converts through preferred unit changes","- Larger margin on shortcut printout","- M0 in feeder macros now displays M0 pause dialog","- Added missing outline keybinds","- Unlock keybind should work in more situations where a soft reset was required","### 1.2.1 (Jun 22, 2023)","- Fix for files not loading for some users","- Tool change strategy missing units added","- Controller functionality issues addressed","- Calibration tools calculate correct values based on input","- Surfacing unit conversion on RPM removed","- Laser unit renamed to Power from RPM","- Color theme loading no longer loads non-existent file"] \ No newline at end of file +["### 1.4.1 (January 26, 2024)","- Fix for black screen on application startup in some situations","- Fix for jog buttons on UI not registering click events correctly on some operating systems","- Strip comments sent to controller to prevent buffer overflow and better support Shapeoko","- Fix issue with firmware tool not updating values correctly if settings limited by search bar","- Handle missing file name in recent files","- Updated EEPROM values for travel on multiple Sienci profiles","- Fixed issue with surfacing tool crashing in some situations","- Fixed several bugs with gamepad support","### 1.4.0 (January 23, 2024)","- Added Rotary Mode","- gSender is now able to run 2+1 axis files on grbl and 4 axis files on grblHAL","- Visualizer updated to support 4 axis rotations","- A-axis DRO and jogging","- Rotary probing","- Added grblHAL controller support","- Connect to and run jobs as normal on any grblHAL device","- Connect over ethernet where hardware is supported","- New grblHAL specific firmware tool that is dynamically generated based on reported settings","- New UI elements where appropriate to support new functionality such as single axis homing","- Gamepad improvements","- Restructured logic and mapping of buttons to actions","- Add secondary functionality to buttons","- Added joystick MPG mode","- Added lockout button to deactivate gamepad when needed","- Improved job time estimation","- Significantly improved initial time estimation algorithm based on machine acceleration and max speeds","- Mid-job estimation uses initial estimate per line for more accurate remaining duration","- Multi-corner probing - touch off any corner using both standard and auto-zero touchplates","- Added Go To UI button to quickly go to an absolute or relative workspace coordinate","- Clearer distinction on planned lines vs cut lines - planned lines show up as a (customizable) yellow instead of the default cut gray","- Remote mode improvements","- Added QR code for easier navigation to remote address on phone","- Added workflow controls and unit selection to remote mode UI","- Added preference to prompt on Zero to prevent accidentally resetting zero on any axis","- Code block toolchange again supported","- Firmware active modals now displayed in diagnostic tab","- PRB values available to use in macros","- Files are now parsed once per run time","- Fix for DRO precision in some situations","- Improved job stats area - now tracks jobs per com port, more information about each job run and the number of problems encountered","- Maintenance reminders - set up and customize maintenance reminders to prompt tasks after specific run time totals have occured","- Improved alarm and error recording","### 1.2.2 (Jul 6, 2023)","- Fix for overrides leading to gcode errors","- Override value correctly updates with keybind usage","- Using override keybind should now display the override panel","- Multiple tool changes in a single file now display the correct tool in the Wizard","- Controller binds should work with tool change wizard active","- Spindle RPM no longer incorrectly converting units","- Spindle slider now reflects EEPROM values for min and max","- Jog speed properly converts through preferred unit changes","- Larger margin on shortcut printout","- M0 in feeder macros now displays M0 pause dialog","- Added missing outline keybinds","- Unlock keybind should work in more situations where a soft reset was required"] \ No newline at end of file diff --git a/src/app/containers/Preferences/Preferences.jsx b/src/app/containers/Preferences/Preferences.jsx index 103ae39cd..8da689411 100644 --- a/src/app/containers/Preferences/Preferences.jsx +++ b/src/app/containers/Preferences/Preferences.jsx @@ -824,12 +824,18 @@ class PreferencesPage extends PureComponent { componentDidMount() { controller.command('settings:updated', this.state); this.addControllerEvents(); - gamepad.holdListener(); + + if (gamepad.holdListener) { + gamepad.holdListener(); + } } componentWillUnmount() { - gamepad.unholdListener(); this.removeControllerEvents(); + + if (gamepad.unholdListener) { + gamepad.unholdListener(); + } } componentDidUpdate(prevProps, prevState) { diff --git a/src/app/containers/Preferences/Safety/ErrorLogs/ErrorItem.jsx b/src/app/containers/Preferences/Safety/ErrorLogs/ErrorItem.jsx new file mode 100644 index 000000000..6e29ee17d --- /dev/null +++ b/src/app/containers/Preferences/Safety/ErrorLogs/ErrorItem.jsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { VscError } from 'react-icons/vsc'; +import { BsAlarm } from 'react-icons/bs'; +import { VerticalTimelineElement } from 'react-vertical-timeline-component'; + +import { ALARM } from 'app/constants'; + +import styles from '../../index.styl'; + +const colorCodes = { + ALARM: '#d75f5f', + ERROR: '#ff0000' +}; + +const ErrorItem = ({ log, date, time }) => { + return ( + : } + > + {log.type} - {log.source} + + {`On ${date} at ${time}`} + +

+ {`${log.type} ${log.CODE} - ${log.MESSAGE}`}
+

+ +
+

+ { + log.line && ( + log.source !== 'Console' && log.source !== 'Feeder' ? `Line ${log.lineNumber}: ` : 'Line: ' + ) + } + {log.line} +

+

{log.controller}

+
+
+ ); +}; + +export default ErrorItem; diff --git a/src/app/containers/Preferences/Safety/ErrorLogs/ErrorLog.js b/src/app/containers/Preferences/Safety/ErrorLogs/ErrorLog.js index 124aefa7a..6e60c91a1 100644 --- a/src/app/containers/Preferences/Safety/ErrorLogs/ErrorLog.js +++ b/src/app/containers/Preferences/Safety/ErrorLogs/ErrorLog.js @@ -1,28 +1,22 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { VerticalTimeline, VerticalTimelineElement } from 'react-vertical-timeline-component'; + import 'react-vertical-timeline-component/style.min.css'; -import { VscError } from 'react-icons/vsc'; -import { BsAlarm } from 'react-icons/bs'; -import uniqueID from 'lodash/uniqueId'; -import styles from '../../index.styl'; + import api from 'app/api'; -import { ALARM } from '../../../../constants'; -import { convertISOStringToDateAndTime } from '../../../../lib/datetime'; + +import LogList from './LogList'; +import styles from '../../index.styl'; const ErrorLog = () => { const [logs, setLogs] = useState([]); - const colorCodes = { - ALARM: '#d75f5f', - ERROR: '#ff0000' - }; - useEffect(() => { const fetchLogs = async () => { const res = await api.alarmList.fetch(); const { list } = res.body; - setLogs(list || []); + + setLogs(list.reverse() || []); }; fetchLogs(); }, []); @@ -32,48 +26,9 @@ const ErrorLog = () => {
{ `Errors and Alarms (${logs.length})`}
+
- { logs.length !== 0 - ? ( - - { - logs.map((log, index) => { - const [date, time] = convertISOStringToDateAndTime(log.time); - return ( - : } - key={uniqueID()} - > - {log.type} - {log.source} - - {`On ${date} at ${time}`} - -

- {`${log.type} ${log.CODE} - ${log.MESSAGE}`}
- { - log.line && ( - log.source !== 'Console' && log.source !== 'Feeder' ? `Line ${log.lineNumber}: ` : 'Line: ' - ) - } - {log.line} -

-
- ); - }).reverse() - } -
- ) - : ( -
- No history of alarms or errors -
- ) - } +
); diff --git a/src/app/containers/Preferences/Safety/ErrorLogs/LogList.jsx b/src/app/containers/Preferences/Safety/ErrorLogs/LogList.jsx new file mode 100644 index 000000000..fa8fc5c74 --- /dev/null +++ b/src/app/containers/Preferences/Safety/ErrorLogs/LogList.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { VerticalTimeline } from 'react-vertical-timeline-component'; +import uniqueID from 'lodash/uniqueId'; + +import ErrorItem from './ErrorItem'; +import { convertISOStringToDateAndTime } from '../../../../lib/datetime'; + +import styles from '../../index.styl'; + +const LogList = ({ logs }) => { + if (!logs || logs?.length === 0) { + return ( +
+ No history of alarms or errors +
+ ); + } + + return ( + + { + logs.map((log) => { + const [date, time] = convertISOStringToDateAndTime(log.time); + + const key = uniqueID(); + + return ( + + ); + }) + } + + ); +}; + +export default LogList; diff --git a/src/app/containers/Preferences/Shortcuts/Gamepad/JoystickOptions.js b/src/app/containers/Preferences/Shortcuts/Gamepad/JoystickOptions.js index b308d60f4..f541d651a 100644 --- a/src/app/containers/Preferences/Shortcuts/Gamepad/JoystickOptions.js +++ b/src/app/containers/Preferences/Shortcuts/Gamepad/JoystickOptions.js @@ -1,6 +1,6 @@ import React, { useContext } from 'react'; import Select from 'react-select'; -import { cloneDeep, set } from 'lodash'; +import { cloneDeep, set, get } from 'lodash'; import { Checkbox } from 'app/components/Checkbox'; import Tooltip from 'app/components/TooltipCustom/ToolTip'; @@ -53,11 +53,13 @@ const JoystickOptions = () => { const { joystickOptions: { stick1, stick2, zeroThreshold = 15, movementDistanceOverride = 100 } } = profile; - const stick1PrimaryActionIsUsingMPG = stick1.mpgMode.primaryAction !== null; - const stick1SecondaryActionIsUsingMPG = stick1.mpgMode.secondaryAction !== null; + const stick1PrimaryActionIsUsingMPG = get(stick1, 'mpgMode.primaryAction', null) !== null; + const stick1SecondaryActionIsUsingMPG = get(stick1, 'mpgMode.secondaryAction', null) !== null; - const stick2PrimaryActionIsUsingMPG = stick2.mpgMode.primaryAction !== null; - const stick2SecondaryActionIsUsingMPG = stick2.mpgMode.secondaryAction !== null; + const stick2PrimaryActionIsUsingMPG = get(stick2, 'mpgMode.primaryAction', null) !== null; + const stick2SecondaryActionIsUsingMPG = get(stick2, 'mpgMode.secondaryAction', null) !== null; + + const isHoldingModifierButton = buttons[profile.modifier?.button]?.pressed; const selectOverrideStyle = { valueContainer: provided => ({ ...provided, padding: 2, justifyContent: 'center' }), @@ -72,8 +74,6 @@ const JoystickOptions = () => { indicatorSeparator: (provided) => ({ ...provided, backgroundColor: 'white' }), }; - const isHoldingModifierButton = buttons[profile.modifier?.button]?.pressed; - return (
@@ -343,7 +343,7 @@ const JoystickOptions = () => {
Movement Distance Override
handleChange('movementDistanceOverride', Number(e.target.value))} className={styles['joystick-option-input']} units="%" diff --git a/src/app/containers/Preferences/SpindleLaser/Laser.js b/src/app/containers/Preferences/SpindleLaser/Laser.js index f869ca4f7..8faadb223 100644 --- a/src/app/containers/Preferences/SpindleLaser/Laser.js +++ b/src/app/containers/Preferences/SpindleLaser/Laser.js @@ -35,6 +35,7 @@ const Laser = ({ state, actions }) => {
+

Note that these values will not be applied to EEPROM until the next time laser mode is toggled.

{ const serializedFile = new File([gcode], 'surfacing.gcode'); - pubsub.publish('visualizer:load', gcode, serializedFile.size, serializedFile.originalname, VISUALIZER_SECONDARY); + const payload = { + content: gcode, + size: serializedFile.size, + name: serializedFile.name, + visualizer: VISUALIZER_SECONDARY + }; + + pubsub.publish('visualizer:load', payload); setGcode(gcode); }; @@ -154,7 +161,12 @@ const Surfacing = ({ onClose, showTitle, isDisabled }) => {

- setCurrentTab(index)} /> + setCurrentTab(index)} + mountAllTabs + />
diff --git a/src/app/containers/Surfacing/components/TabArea.js b/src/app/containers/Surfacing/components/TabArea.js index c2cf69d1d..d1cb427f6 100644 --- a/src/app/containers/Surfacing/components/TabArea.js +++ b/src/app/containers/Surfacing/components/TabArea.js @@ -5,7 +5,7 @@ import TabbedWidget from 'app/components/TabbedWidget'; import { SURFACING_VISUALIZER_CONTAINER_ID } from 'app/constants'; -const TabArea = ({ tabs, currentTab, onTabChange }) => { +const TabArea = ({ tabs, currentTab, onTabChange, mountAllTabs = false }) => { return ( { { tabs.map((tab, index) => { const active = index === currentTab; + + if (mountAllTabs) { + return ( + + {tab.component} + + ); + } + return ( {active && tab.component} diff --git a/src/app/index.jsx b/src/app/index.jsx index e58b5d2f5..d0a61c2fc 100644 --- a/src/app/index.jsx +++ b/src/app/index.jsx @@ -62,6 +62,8 @@ import ModalTemplate from './components/ModalTemplate'; import Modal from './components/Modal'; import Space from './components/Space'; import PopUpWidget from './containers/PopUpWidget'; +import pkg from '../package.json'; + import './styles/vendor.styl'; import './styles/app.styl'; @@ -72,6 +74,7 @@ if (process.env.NODE_ENV === 'production') { new Sentry.BrowserTracing(), new Sentry.Replay() ], + release: pkg.version }); } diff --git a/src/app/lib/GCodeVirtualizer.js b/src/app/lib/GCodeVirtualizer.js index bdb0c4786..f225fc9fe 100644 --- a/src/app/lib/GCodeVirtualizer.js +++ b/src/app/lib/GCodeVirtualizer.js @@ -353,7 +353,8 @@ class GCodeVirtualizer extends EventEmitter { const v2 = { x: this.translateX(params.X), y: this.translateY(params.Y), - z: this.translateZ(params.Z) + z: this.translateZ(params.Z), + a: this.translateA(params.A), }; const v0 = { // fixed point x: this.translateI(params.I), @@ -437,7 +438,8 @@ class GCodeVirtualizer extends EventEmitter { const v2 = { x: this.translateX(params.X), y: this.translateY(params.Y), - z: this.translateZ(params.Z) + z: this.translateZ(params.Z), + a: this.translateA(params.A), }; const v0 = { // fixed point x: this.translateI(params.I), diff --git a/src/app/lib/controller.js b/src/app/lib/controller.js index 63f75543e..7c5e02ce0 100644 --- a/src/app/lib/controller.js +++ b/src/app/lib/controller.js @@ -115,6 +115,7 @@ class Controller { //A-Axis A.K.A Rotary-Axis events 'rotaryAxis:updateState': [], + 'updateRotaryMode': [], 'connection:new': [], 'requestEstimateData': [], diff --git a/src/app/lib/datetime.js b/src/app/lib/datetime.js index f3244c9dd..d2bb991d3 100644 --- a/src/app/lib/datetime.js +++ b/src/app/lib/datetime.js @@ -21,6 +21,8 @@ * */ +import moment from 'moment'; + // solution found here: https://stackoverflow.com/a/59948911 export const convertMillisecondsToTimeStamp = (milliseconds) => { if (milliseconds) { @@ -45,8 +47,14 @@ export const convertSecondsToTimeStamp = (seconds, startTime) => { }; export const convertISOStringToDateAndTime = (ISOString) => { - const dateTime = new Date(ISOString); - const date = `${String(dateTime.getFullYear())}-${String(dateTime.getMonth()).padStart(2, 0)}-${String(dateTime.getDate()).padStart(2, 0)}`; - const time = `${String(dateTime.getHours()).padStart(2, 0)}:${String(dateTime.getMinutes()).padStart(2, 0)}:${String(dateTime.getSeconds()).padStart(2, 0)}`; + const dateFromString = moment(ISOString); + + if (!dateFromString.isValid()) { + return ['-', '-']; + } + + const date = dateFromString.format('YYYY-MM-DD'); + const time = dateFromString.format('HH:mm:ss'); + return [date, time]; }; diff --git a/src/app/lib/diagnostics.js b/src/app/lib/diagnostics.js index d4698b8fe..372e124b4 100644 --- a/src/app/lib/diagnostics.js +++ b/src/app/lib/diagnostics.js @@ -64,7 +64,8 @@ const styles = StyleSheet.create({ fontFamily: 'Helvetica-Bold' }, lineWrapper: { - marginTop: 6 + marginTop: 6, + marginBottom: 6 }, textBold: { fontSize: 12, @@ -569,7 +570,8 @@ function generateSupportFile() { {'    ' + log.MESSAGE + '\n'} - {'    Input:' + log.line + '\n'} + {'    Input: ' + log.line} + {'    Controller: ' + log.controller} ); @@ -595,7 +597,8 @@ function generateSupportFile() { {'    ' + log.MESSAGE + '\n'} - {'    Input: ' + log.line + '\n'} + {'    Input: ' + log.line} + {'    Controller: ' + log.controller} ); diff --git a/src/app/lib/gamepad/index.js b/src/app/lib/gamepad/index.js index 62a3ab89d..7e2b26ec3 100644 --- a/src/app/lib/gamepad/index.js +++ b/src/app/lib/gamepad/index.js @@ -121,6 +121,10 @@ export const checkButtonHold = (buttonType, currentProfile) => { const currentGamepad = gamepads.find(gamepad => currentProfile.id.includes(gamepad?.id)); + if (!currentGamepad) { + return false; + } + const isHoldingButton = currentGamepad.buttons[currentProfile[buttonType]?.button]?.pressed; return isHoldingButton; @@ -141,9 +145,9 @@ export const onGamepadButtonPress = ({ detail }) => { return null; } - const foundAction = currentProfile.buttons.find(({ value }) => value === button); + const foundAction = currentProfile.buttons?.find(({ value }) => value === button); - if (!detail.pressed && foundAction.primaryAction?.includes('JOG') || foundAction.secondaryAction?.includes('JOG')) { + if (!detail.pressed && foundAction?.primaryAction?.includes('JOG') || foundAction.secondaryAction?.includes('JOG')) { return 'STOP_JOG'; } diff --git a/src/app/lib/rotary.js b/src/app/lib/rotary.js index 4965490d0..36a13be27 100644 --- a/src/app/lib/rotary.js +++ b/src/app/lib/rotary.js @@ -10,6 +10,8 @@ import { ROTARY_MODE_FIRMWARE_SETTINGS, ROTARY_TOGGLE_MACRO, DEFAULT_FIRMWARE_SETTINGS, + GRBL, + GRBLHAL } from 'app/constants'; import { Confirm } from 'app/components/ConfirmationDialog/ConfirmationDialogLib'; import { Toaster, TOASTER_INFO } from 'app/lib/toaster/ToasterLib'; @@ -23,17 +25,34 @@ export const updateWorkspaceMode = (mode = WORKSPACE_MODE.DEFAULT) => { switch (mode) { case DEFAULT: { - const defaultFirmwareSettings = store.get('workspace.rotaryAxis.defaultFirmwareSettings', DEFAULT_FIRMWARE_SETTINGS); + if (firmwareType === GRBL) { + const defaultFirmwareSettings = store.get('workspace.rotaryAxis.defaultFirmwareSettings', DEFAULT_FIRMWARE_SETTINGS); - const defaultFirmwareSettingsArr = Object.entries(defaultFirmwareSettings).map(([key, value]) => `${key}=${value}`); + const defaultFirmwareSettingsArr = Object.entries(defaultFirmwareSettings).map(([key, value]) => `${key}=${value}`); - controller.command('gcode', [...defaultFirmwareSettingsArr, '$$', ROTARY_TOGGLE_MACRO]); + controller.command('gcode', [...defaultFirmwareSettingsArr, '$$', ROTARY_TOGGLE_MACRO]); + } else if (firmwareType === GRBLHAL) { + // switch A and Y axis settings back + const newAAxisSettings = [ + `$103=${get(reduxStore.getState(), 'controller.settings.settings.$101')}`, + `$113=${get(reduxStore.getState(), 'controller.settings.settings.$111')}`, + `$123=${get(reduxStore.getState(), 'controller.settings.settings.$121')}` + ]; + const newYAxisSettings = [ + `$101=${get(reduxStore.getState(), 'controller.settings.settings.$103')}`, + `$111=${get(reduxStore.getState(), 'controller.settings.settings.$113')}`, + `$121=${get(reduxStore.getState(), 'controller.settings.settings.$123')}` + ]; + + // zero y and enable rotary + controller.command('gcode', ['G10 L20 P1 Y0', ...newAAxisSettings, ...newYAxisSettings, '$$', ROTARY_TOGGLE_MACRO]); + } return; } case ROTARY: { // We only need to update the firmware settings on grbl machines - if (firmwareType === 'Grbl') { + if (firmwareType === GRBL) { // Convert to array to send to the controller, will look something like this: ["$101=26.667", ...] const rotaryFirmwareSettingsArr = Object.entries(rotaryFirmwareSettings).map(([key, value]) => `${key}=${value}`); @@ -76,6 +95,59 @@ export const updateWorkspaceMode = (mode = WORKSPACE_MODE.DEFAULT) => { store.replace('workspace.mode', WORKSPACE_MODE.DEFAULT); } }); + } else if (firmwareType === GRBLHAL) { + Confirm({ + title: 'Enable Rotary Mode', + cancelLabel: 'Cancel', + confirmLabel: 'OK', + content: ( +
+

Enabling rotary mode will perform the following actions:

+ +
    +
  1. Zero the Y-Axis in it's current position
  2. +
  3. + Switch these A and Y axis settings: + +
      +
    • $101 and $103 (travel resolution)
    • +
    • $111 and $113 (maximum rate)
    • +
    • $121 and $123 (acceleration)
    • +
    • $131 and $133 (travel amount)
    • +
    +
  4. +
+
+ ), + onConfirm: () => { + // switch A and Y axis settings, will look something like this: ["$101=26.667", ...] + const newAAxisSettings = [ + `$103=${get(reduxStore.getState(), 'controller.settings.settings.$101')}`, + `$113=${get(reduxStore.getState(), 'controller.settings.settings.$111')}`, + `$123=${get(reduxStore.getState(), 'controller.settings.settings.$121')}`, + `$133=${get(reduxStore.getState(), 'controller.settings.settings.$131')}` + ]; + const newYAxisSettings = [ + `$101=${get(reduxStore.getState(), 'controller.settings.settings.$103')}`, + `$111=${get(reduxStore.getState(), 'controller.settings.settings.$113')}`, + `$121=${get(reduxStore.getState(), 'controller.settings.settings.$123')}`, + `$131=${get(reduxStore.getState(), 'controller.settings.settings.$133')}` + ]; + + // zero y and enable rotary + controller.command('gcode', ['G10 L20 P1 Y0', ...newAAxisSettings, ...newYAxisSettings, '$$', ROTARY_TOGGLE_MACRO]); + + pubsub.publish('visualizer:updateposition', { y: 0 }); + + Toaster.pop({ + msg: 'Rotary Mode Enabled', + type: TOASTER_INFO, + }); + }, + onClose: () => { + store.replace('workspace.mode', WORKSPACE_MODE.DEFAULT); + } + }); } return; diff --git a/src/app/sagas/controllerSagas.js b/src/app/sagas/controllerSagas.js index d409d622b..3b8c92521 100644 --- a/src/app/sagas/controllerSagas.js +++ b/src/app/sagas/controllerSagas.js @@ -1,3 +1,4 @@ +/* eslint-disable max-lines-per-function */ /* * Copyright (C) 2021 Sienci Labs Inc. * @@ -552,7 +553,7 @@ export function* initialize() { }); // for when you don't want to send file to backend - pubsub.subscribe('visualizer:load', (msg, content, size, name, visualizer) => { + pubsub.subscribe('visualizer:load', (_, { content, size, name, visualizer }) => { parseGCode(content, size, name, visualizer); }); diff --git a/src/app/store/index.js b/src/app/store/index.js index 8a6d9fb5d..357a7feea 100644 --- a/src/app/store/index.js +++ b/src/app/store/index.js @@ -24,7 +24,7 @@ if (isElectron()) { const path = window.require('path'); // Require the path module within Electron userData = { - path: path.join(app.getPath('userData'), 'preferences.json') + path: path.join(app.getPath('userData'), 'gsender-0.5.6.json') }; } @@ -309,6 +309,12 @@ const migrateStore = () => { } } + // Reset machine profile to default selection for 1.4.1 to prevent ID overlaps + if (semver.lt(cnc.version, '1.4.1')) { + const defaultMachineProfile = get(defaultState, 'workspace.machineProfiles'); + store.set('workspace.machineProfile', defaultMachineProfile); + } + if (semver.lt(cnc.version, '1.2.4') || semver.lt(cnc.version, '1.2.4-EDGE')) { const currentCommandKeys = store.get('commandKeys'); let newCommandKeysList = {}; diff --git a/src/app/widgets/Console/Terminal.jsx b/src/app/widgets/Console/Terminal.jsx index b51bbb1a2..d3dd15faf 100644 --- a/src/app/widgets/Console/Terminal.jsx +++ b/src/app/widgets/Console/Terminal.jsx @@ -99,7 +99,7 @@ class TerminalWrapper extends PureComponent { // Ctrl-C copy - ctrl + c on windows/linux, meta-c on mac if ((event.ctrlKey || event.metaKey) && (event.code === 'KeyC')) { - await navigator.clipboard.writeText(line); + await navigator.clipboard?.writeText(line); return; } }; @@ -286,10 +286,9 @@ class TerminalWrapper extends PureComponent { if (isElectron()) { window.ipcRenderer.send('clipboard', text); } else { - await navigator.clipboard.writeText(text); + await navigator.clipboard?.writeText(text); } - Toaster.pop({ msg: `Copied Last ${selection.length} Lines from the Terminal to Clipboard`, type: TOASTER_INFO diff --git a/src/app/widgets/JogControl/Axes.jsx b/src/app/widgets/JogControl/Axes.jsx index ebd2d4902..6999ca462 100644 --- a/src/app/widgets/JogControl/Axes.jsx +++ b/src/app/widgets/JogControl/Axes.jsx @@ -43,7 +43,6 @@ const Axes = (props) => { activeState={state.activeState} selectedSpeed={state.selectedSpeed} canJog={state.canJog} - firmwareType={state.type} /> ); @@ -62,7 +61,6 @@ const Axes = (props) => { activeState={state.activeState} selectedSpeed={state.selectedSpeed} canJog={state.canJog} - firmwareType={state.type} /> diff --git a/src/app/widgets/JogControl/Dockerfile b/src/app/widgets/JogControl/Dockerfile new file mode 100644 index 000000000..a61b152a7 --- /dev/null +++ b/src/app/widgets/JogControl/Dockerfile @@ -0,0 +1,4 @@ +FROM ubuntu:latest +LABEL authors="kevin" + +ENTRYPOINT ["top", "-b"] diff --git a/src/app/widgets/JogControl/JoystickLoop.js b/src/app/widgets/JogControl/JoystickLoop.js index 18864e7c2..edb7e10f6 100644 --- a/src/app/widgets/JogControl/JoystickLoop.js +++ b/src/app/widgets/JogControl/JoystickLoop.js @@ -1,5 +1,4 @@ -/* eslint-disable no-unused-vars */ -import { throttle, inRange } from 'lodash'; +import { throttle, inRange, get } from 'lodash'; import gamepad, { checkButtonHold } from 'app/lib/gamepad'; import controller from 'app/lib/controller'; @@ -39,6 +38,10 @@ export class JoystickLoop { _getCurrentGamepad = () => { const currentHandler = gamepad.handlers.find(handler => this.gamepadProfile.id.includes(handler?.gamepad?.id)); + if (!currentHandler) { + throw new Error('Could not find current gamepad'); + } + return currentHandler?.gamepad; } @@ -212,8 +215,9 @@ export class JoystickLoop { const axesValues = currentGamepad?.axes; - const lockoutButton = this.gamepadProfile.lockout.button; - const isHoldingLockoutButton = currentGamepad.buttons?.[lockoutButton]?.pressed; + const movementDistanceOverride = get(this.gamepad, 'joystickOptions.movementDistanceOverride', 100); + const lockoutButton = get(this.gamepadProfile, 'lockout.button'); + const isHoldingLockoutButton = get(currentGamepad.buttons, `${lockoutButton}.pressed`, false); const thumbsticksAreIdle = checkThumbsticskAreIdle(axesValues, this.gamepadProfile); @@ -243,6 +247,14 @@ export class JoystickLoop { return acc; }, {}); + const updatedAxesWithOverride = Object.entries(updatedAxes).reduce((acc, curr) => { + const [axis, value] = curr; + + acc[axis] = +((value * (movementDistanceOverride / 100)).toFixed(3)); + + return acc; + }, {}); + const largestAxisMovement = Object.entries(updatedAxes).reduce((acc, [key, value]) => { const val = Math.abs(value); if (acc === null || val > acc?.value) { @@ -265,7 +277,7 @@ export class JoystickLoop { return; } - this.jog({ ...updatedAxes, F: feedrate }); + this.jog({ ...updatedAxesWithOverride, F: feedrate }); this.jogMovementStartTime = new Date(); diff --git a/src/app/widgets/JogControl/Keypad.jsx b/src/app/widgets/JogControl/Keypad.jsx index 87cb07e13..6987e9fcc 100644 --- a/src/app/widgets/JogControl/Keypad.jsx +++ b/src/app/widgets/JogControl/Keypad.jsx @@ -66,7 +66,6 @@ class Keypad extends PureComponent { axes: PropTypes.array, jog: PropTypes.object, actions: PropTypes.object, - firmwareType: PropTypes.string, }; handleSelect = (eventKey) => { @@ -126,7 +125,7 @@ class Keypad extends PureComponent { } render() { - const { canClick, canClickCancel, actions, axes, activeState, selectedSpeed, firmwareType } = this.props; + const { canClick, canClickCancel, actions, axes, activeState, selectedSpeed } = this.props; const canClickX = canClick && _includes(axes, 'x'); const canClickY = canClick && _includes(axes, 'y'); const canClickXY = canClickX && canClickY; @@ -164,14 +163,14 @@ class Keypad extends PureComponent { jog={() => actions.jog({ X: -xyDistance, Y: xyDistance, F: feedrate })} continuousJog={() => actions.startContinuousJog({ X: -1, Y: 1 }, feedrate)} stopContinuousJog={() => actions.stopContinuousJog()} - disabled={xyControlsDisabled || rotary && firmwareType === 'Grbl'} + disabled={xyControlsDisabled || rotary} /> actions.jog({ Y: xyDistance, F: feedrate })} continuousJog={() => actions.startContinuousJog({ Y: 1 }, feedrate)} stopContinuousJog={() => actions.stopContinuousJog()} - disabled={xyControlsDisabled || rotary && firmwareType === 'Grbl'} + disabled={xyControlsDisabled || rotary} > Y + @@ -181,7 +180,7 @@ class Keypad extends PureComponent { jog={() => actions.jog({ X: xyDistance, Y: xyDistance, F: feedrate })} continuousJog={() => actions.startContinuousJog({ X: 1, Y: 1 }, feedrate)} stopContinuousJog={() => actions.stopContinuousJog()} - disabled={xyControlsDisabled || rotary && firmwareType === 'Grbl'} + disabled={xyControlsDisabled || rotary} /> actions.jog({ X: -xyDistance, Y: -xyDistance, F: feedrate })} continuousJog={() => actions.startContinuousJog({ X: -1, Y: -1 }, feedrate)} stopContinuousJog={() => actions.stopContinuousJog()} - disabled={xyControlsDisabled || rotary && firmwareType === 'Grbl'} + disabled={xyControlsDisabled || rotary} /> actions.jog({ Y: -xyDistance, F: feedrate })} continuousJog={() => actions.startContinuousJog({ Y: -1 }, feedrate)} stopContinuousJog={() => actions.stopContinuousJog()} - disabled={xyControlsDisabled || rotary && firmwareType === 'Grbl'} + disabled={xyControlsDisabled || rotary} > Y - @@ -238,7 +237,7 @@ class Keypad extends PureComponent { jog={() => actions.jog({ X: xyDistance, Y: -xyDistance, F: feedrate })} continuousJog={() => actions.startContinuousJog({ X: 1, Y: -1 }, feedrate)} stopContinuousJog={() => actions.stopContinuousJog()} - disabled={xyControlsDisabled || rotary && firmwareType === 'Grbl'} + disabled={xyControlsDisabled || rotary} /> ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0); - const JogControl = ({ timeout = 600, disabled = false, jog, continuousJog, stopContinuousJog, className, children }) => { const bind = useLongPress(() => { continuousJog(); }, { threshold: timeout, onCancel: jog, - onFinish: stopContinuousJog, - detect: isTouchEnabled() ? 'touch' : 'mouse' + onFinish: stopContinuousJog }); return ( diff --git a/src/app/widgets/JogControl/index.jsx b/src/app/widgets/JogControl/index.jsx index f97ae383f..e46e61109 100644 --- a/src/app/widgets/JogControl/index.jsx +++ b/src/app/widgets/JogControl/index.jsx @@ -954,8 +954,13 @@ class AxesWidget extends PureComponent { if (!data) { return; } + const { rapid, normal, precise } = data; + if (jog.rapid === rapid && jog.normal === normal && jog.precise === precise) { + return; + } + this.setState({ jog: { ...jog, @@ -975,7 +980,7 @@ class AxesWidget extends PureComponent { gamepad.on('gamepad:button', throttle((event) => runAction({ event, shuttleControlEvents: this.shuttleControlEvents })), 50, { leading: false, trailing: true }); gamepad.on('gamepad:axis', ({ detail }) => { - if (gamepad.shouldHold) { + if (gamepad.shouldHold || !this.props.isConnected) { return; } @@ -1039,7 +1044,7 @@ class AxesWidget extends PureComponent { }); gamepad.on('gamepad:axis', throttle(({ detail }) => { - if (gamepad.shouldHold) { + if (gamepad.shouldHold || !this.props.isConnected) { return; } @@ -1069,7 +1074,7 @@ class AxesWidget extends PureComponent { const actionType = !isHoldingModifierButton ? 'primaryAction' : 'secondaryAction'; - const isUsingMPGMode = !!joystickOptions[activeStick].mpgMode[actionType]; + const isUsingMPGMode = !!get(joystickOptions, `${activeStick}.mpgMode.${actionType}`, false); if (isUsingMPGMode) { return; diff --git a/src/app/widgets/Location/DisplayPanel.jsx b/src/app/widgets/Location/DisplayPanel.jsx index 231c2dcc5..5d0b68638 100644 --- a/src/app/widgets/Location/DisplayPanel.jsx +++ b/src/app/widgets/Location/DisplayPanel.jsx @@ -343,7 +343,7 @@ class DisplayPanel extends PureComponent { const { homingSetting } = this.props; const binary = parseInt(homingSetting, 10).toString(2); const singleAxis = binary.charAt(binary.length - 2); - return singleAxis; + return Number(singleAxis); } handleMovementSwitch(newValue) { @@ -375,7 +375,7 @@ class DisplayPanel extends PureComponent { } render() { - const { axes, actions, canClick, safeRetractHeight, units, homingEnabled, canHome, homingDirection, homingRun, firmware } = this.props; + const { axes, actions, canClick, safeRetractHeight, units, homingEnabled, canHome, homingDirection, homingRun } = this.props; const { modalShow, relative, location } = this.state; const homingLocation = getHomingLocation(homingDirection); const hasAxisX = includes(axes, AXIS_X); @@ -455,22 +455,11 @@ class DisplayPanel extends PureComponent {
- {firmware === 'Grbl' - ? ( - - {hasAxisX && this.renderAxis(AXIS_X)} - {!isInRotaryMode && hasAxisY ? this.renderAxis(AXIS_Y) : this.renderAxis(AXIS_Y, true)} - {hasAxisZ && this.renderAxis(AXIS_Z, false, isInRotaryMode)} - - ) - : ( - - {hasAxisX && this.renderAxis(AXIS_X)} - {hasAxisY && this.renderAxis(AXIS_Y)} - {hasAxisZ && this.renderAxis(AXIS_Z)} - - ) - } + + {hasAxisX && this.renderAxis(AXIS_X)} + {!isInRotaryMode && hasAxisY ? this.renderAxis(AXIS_Y) : this.renderAxis(AXIS_Y, true)} + {hasAxisZ && this.renderAxis(AXIS_Z, false, isInRotaryMode)} +
{ const activeState = get(store, 'controller.state.status.activeState'); const canHome = isConnected && [GRBL_ACTIVE_STATE_IDLE, GRBL_ACTIVE_STATE_ALARM].includes(activeState) && workflowState !== WORKFLOW_STATE_RUNNING; const mpos = get(store, 'controller.mpos'); - const firmware = get(store, 'controller.type'); const modalDistance = get(store, 'controller.state.parserstate.modal.distance'); const $13 = get(store, 'controller.settings.settings.$13'); return { @@ -619,7 +607,6 @@ export default connect((store) => { homingRun, pullOff, mpos, - firmware, modalDistance, $13 }; diff --git a/src/app/widgets/Location/RapidPosition.js b/src/app/widgets/Location/RapidPosition.js index 965b527b4..32fef8150 100644 --- a/src/app/widgets/Location/RapidPosition.js +++ b/src/app/widgets/Location/RapidPosition.js @@ -32,7 +32,8 @@ export const BACK_RIGHT = 'BR'; export const BACK_LEFT = 'BL'; export const OTHER = 'OT'; -const OFFSET_DISTANCE = 0.95; +const OFFSET_DISTANCE = 1; +const PULLOFF_DISTANCE = 5; export const getHomingLocation = (setting) => { if (setting === '0') { @@ -53,17 +54,17 @@ const getMachineMovementLimits = () => { const settings = get(store, 'controller.settings.settings'); const { $130: xMax, $131: yMax } = settings; - const xLimit = (Number(xMax) * OFFSET_DISTANCE).toFixed(3); - const yLimit = (Number(yMax) * OFFSET_DISTANCE).toFixed(3); + // Limits are PULLOFF_DISTANCE away from reported limits + const xLimit = (Number(xMax) - PULLOFF_DISTANCE).toFixed(3); + const yLimit = (Number(yMax) - PULLOFF_DISTANCE).toFixed(3); return [xLimit, yLimit]; }; -// Get a single bit from integer at position -export function getBit(number, bitPosition) { +// Get a single bit from integer at position. It does not use 0 indexing so pretend that arrays start at 1 :) +export function isBitSetInNumber(number, bitPosition) { number = Number(number); - console.log(number); // eslint-disable-next-line no-bitwise return (number & (1 << bitPosition)) !== 0; } @@ -71,7 +72,7 @@ export function getBit(number, bitPosition) { const getPositionMovements = (requestedPosition, homingPosition, homingFlag, pullOff) => { const [xLimit, yLimit] = getMachineMovementLimits(); - pullOff = Number(pullOff) || 2; + pullOff = PULLOFF_DISTANCE; // If homing flag not set, we treat all movements as negative space if (!homingFlag) { homingPosition = BACK_RIGHT; @@ -143,7 +144,7 @@ export const getMovementGCode = (requestedPosition, homingPositionSetting, homin const store = reduxStore.getState(); const settings = get(store, 'controller.settings.settings'); const { $22: homingValue } = settings; - homingFlag = getBit(homingValue, 3); + homingFlag = isBitSetInNumber(homingValue, 3); } const [xMovement, yMovement] = getPositionMovements(requestedPosition, homingPosition, homingFlag, pullOff); diff --git a/src/app/widgets/Probe/index.jsx b/src/app/widgets/Probe/index.jsx index 0db630238..401a957ec 100644 --- a/src/app/widgets/Probe/index.jsx +++ b/src/app/widgets/Probe/index.jsx @@ -370,15 +370,21 @@ class ProbeWidget extends PureComponent { this.config.set('probeDepth', probeDepth); this.config.set('touchPlateHeight', touchPlateHeight); - // get updated settings - this.getUpdatedSettings(); + + const probeFeedrate = this.config.get('probeFeedrate', this.state.probeFeedrate); + const probeFastFeedrate = this.config.get('probeFastFeedrate', this.state.probeFastFeedrate); + const retractionDistance = this.config.get('retractionDistance', this.state.retractionDistance); + + if (this.state.probeFeedrate !== probeFeedrate || this.state.probeFastFeedrate !== probeFastFeedrate || this.state.retractionDistance !== retractionDistance) { + this.getUpdatedSettings(); + } } getUpdatedSettings() { this.setState({ - probeFeedrate: this.config.get('probeFeedrate') || this.state.probeFeedrate, - probeFastFeedrate: this.config.get('probeFastFeedrate') || this.state.probeFastFeedrate, - retractionDistance: this.config.get('retractionDistance') || this.state.retractionDistance, + probeFeedrate: this.config.get('probeFeedrate', this.state.probeFeedrate), + probeFastFeedrate: this.config.get('probeFastFeedrate', this.state.probeFastFeedrate), + retractionDistance: this.config.get('retractionDistance', this.state.retractionDistance), }); } diff --git a/src/app/widgets/Rotary/DROarea.js b/src/app/widgets/Rotary/DROarea.js index 498d70c6c..77bcc5c9d 100644 --- a/src/app/widgets/Rotary/DROarea.js +++ b/src/app/widgets/Rotary/DROarea.js @@ -26,7 +26,7 @@ const DROarea = ({ canClick = true, actions }) => { const machinePosition = useSelector(state => state.controller.mpos); const workPosition = useSelector(state => state.controller.wpos); - const { type: controllerType, state: controllerState } = useSelector(state => state.controller); + const { state: controllerState } = useSelector(state => state.controller); const [positionInput] = useState({ [AXIS_E]: false, [AXIS_X]: false, @@ -39,10 +39,10 @@ const DROarea = ({ canClick = true, actions }) => { const renderAxis = (axis, label) => { const workspaceMode = store.get('workspace.mode', WORKSPACE_MODE.DEFAULT); - const inRotaryModeAndIsGrbl = workspaceMode === WORKSPACE_MODE.ROTARY && controllerType === 'Grbl'; + const inRotaryMode = workspaceMode === WORKSPACE_MODE.ROTARY; // Report the y value in the DRO since the A-axis is not reported back from the grbl controller we are simulating the rotary axis - axis = axis === AXIS_A && inRotaryModeAndIsGrbl ? AXIS_Y : axis; + axis = axis === AXIS_A && inRotaryMode ? AXIS_Y : axis; let mpos = machinePosition[axis] || '0.000'; const wpos = workPosition[axis] || '0.000'; diff --git a/src/app/widgets/Rotary/RotaryToggle.js b/src/app/widgets/Rotary/RotaryToggle.js index 8cd062a12..aae12304e 100644 --- a/src/app/widgets/Rotary/RotaryToggle.js +++ b/src/app/widgets/Rotary/RotaryToggle.js @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import store from 'app/store'; +import controller from 'app/lib/controller'; import ToggleSwitch from 'app/components/ToggleSwitch'; import { WORKSPACE_MODE } from 'app/constants'; import { updateWorkspaceMode } from 'app/lib/rotary'; @@ -32,6 +33,7 @@ const RotaryToggle = () => { const handleToggle = (toggled) => { const newMode = toggled ? ROTARY : DEFAULT; updateWorkspaceMode(newMode); + controller.command('updateRotaryMode', newMode === ROTARY); }; return ( diff --git a/src/app/widgets/Rotary/SpeedControls.js b/src/app/widgets/Rotary/SpeedControls.js index aed287dd6..3daae7d44 100644 --- a/src/app/widgets/Rotary/SpeedControls.js +++ b/src/app/widgets/Rotary/SpeedControls.js @@ -13,7 +13,7 @@ const SpeedControls = ({ actions, jog }) => {
A move (deg) - + { +const TabArea = ({ tabs, currentTab, onTabChange, mountAllTabs = false }) => { return ( { { tabs.map((tab, index) => { const active = index === currentTab; + + if (mountAllTabs) { + return ( + + {tab.component} + + ); + } + return ( {active && tab.component} diff --git a/src/app/widgets/Rotary/StockTurning/index.js b/src/app/widgets/Rotary/StockTurning/index.js index da7f7987d..3e9e16b6e 100644 --- a/src/app/widgets/Rotary/StockTurning/index.js +++ b/src/app/widgets/Rotary/StockTurning/index.js @@ -77,7 +77,14 @@ const StockTurning = () => { const serializedFile = new File([stockTurningGenerator.gcode], 'rotary_surfacing.gcode'); - pubsub.publish('visualizer:load', stockTurningGenerator.gcode, serializedFile.size, serializedFile.originalname, VISUALIZER_SECONDARY); + const payload = { + content: stockTurningGenerator.gcode, + size: serializedFile.size, + name: serializedFile.name, + visualizer: VISUALIZER_SECONDARY + }; + + pubsub.publish('visualizer:load', payload); }; const loadGcode = () => { @@ -125,6 +132,7 @@ const StockTurning = () => { tabs={tabs} currentTab={activeTab} onTabChange={(index) => dispatch({ type: SET_ACTIVE_STOCK_TURNING_TAB, payload: index })} + mountAllTabs />
diff --git a/src/app/widgets/Visualizer/ClientRecentFiles.js b/src/app/widgets/Visualizer/ClientRecentFiles.js index 64deb0506..90871869b 100644 --- a/src/app/widgets/Visualizer/ClientRecentFiles.js +++ b/src/app/widgets/Visualizer/ClientRecentFiles.js @@ -104,7 +104,6 @@ export const sortRecentFiles = (recentFiles = []) => { }; export const loadRecentFile = (filePath) => { - //window.api.loadRecentFile({ filePath: filePath }); window.ipcRenderer.send('load-recent-file', { filePath: filePath }); return true; }; diff --git a/src/app/widgets/Visualizer/Visualizer.jsx b/src/app/widgets/Visualizer/Visualizer.jsx index 252796665..a196ed518 100644 --- a/src/app/widgets/Visualizer/Visualizer.jsx +++ b/src/app/widgets/Visualizer/Visualizer.jsx @@ -1564,13 +1564,13 @@ class Visualizer extends Component { } // Use y-axis in grbl, a-axis in grblHal - const axis = isInRotaryMode && isUsingGRBL && isRotaryFile ? 'y' : 'a'; + const axis = isInRotaryMode && isRotaryFile ? 'y' : 'a'; const prevValue = prevPos[axis]; const currValue = currPos[axis]; const grblCondition = isUsingGRBL && valueHasChanged && isInRotaryMode; - const grblHalCondition = isUsingGRBLHal && valueHasChanged; + const grblHalCondition = isUsingGRBLHal && valueHasChanged || isUsingGRBLHal && isInRotaryMode; /** * GRBL Condition diff --git a/src/app/widgets/Visualizer/WorkflowControl.jsx b/src/app/widgets/Visualizer/WorkflowControl.jsx index 14888f31a..3d20c7956 100644 --- a/src/app/widgets/Visualizer/WorkflowControl.jsx +++ b/src/app/widgets/Visualizer/WorkflowControl.jsx @@ -40,8 +40,8 @@ import pubsub from 'pubsub-js'; import i18n from 'app/lib/i18n'; import Modal from 'app/components/Modal'; import Input from 'app/containers/Preferences/components/Input'; -import WorkerOutline from '../../workers/Outline.worker'; +import WorkerOutline from '../../workers/Outline.worker'; import CameraDisplay from './CameraDisplay/CameraDisplay'; import FunctionButton from '../../components/FunctionButton/FunctionButton'; import { @@ -69,7 +69,7 @@ import { } from '../../constants'; import styles from './workflow-control.styl'; import RecentFileButton from './RecentFileButton'; -import { addRecentFile, createRecentFile, createRecentFileFromRawPath } from './ClientRecentFiles'; +import { addRecentFile, createRecentFileFromRawPath } from './ClientRecentFiles'; import { UPDATE_FILE_INFO } from '../../actions/fileInfoActions'; import { outlineResponse } from '../../workers/Outline.response'; import { shouldVisualizeSVG } from '../../workers/Visualize.response'; @@ -285,12 +285,22 @@ class WorkflowControl extends PureComponent { componentDidMount() { if (isElectron()) { - window.ipcRenderer.on('loaded-recent-file', (msg, fileMetaData) => { + window.ipcRenderer.on('loaded-recent-file', (_, fileMetaData) => { + if (!fileMetaData) { + Toaster.pop({ + msg: 'Error loading recent file, it may have been deleted or moved to a different folder.', + type: TOASTER_DANGER, + duration: 5000 + }); + + return; + } + this.loadRecentFile(fileMetaData); - const recentFile = createRecentFile(fileMetaData); - addRecentFile(recentFile); + // const recentFile = createRecentFile(fileMetaData); + // addRecentFile(recentFile); }); - window.ipcRenderer.on('returned-upload-dialog-data', (msg, file) => { + window.ipcRenderer.on('returned-upload-dialog-data', (_, file) => { this.handleElectronFileUpload(file); }); } diff --git a/src/electron-app/RecentFiles.js b/src/electron-app/RecentFiles.js index 13f692ce3..ded4a33b3 100644 --- a/src/electron-app/RecentFiles.js +++ b/src/electron-app/RecentFiles.js @@ -47,6 +47,7 @@ export const parseAndReturnGCode = async ({ filePath }) => { try { const fileExists = await fileExistsAtPath(filePath); + if (!fileExists) { return null; // TODO: Handle null as FILENOTFOUND error } @@ -55,6 +56,7 @@ export const parseAndReturnGCode = async ({ filePath }) => { const { size } = stats; const data = await fs.readFile(filePath, 'utf-8'); + return { result: data, size: size, diff --git a/src/electron-app/WindowManager.js b/src/electron-app/WindowManager.js index b2aefae07..3c087d20e 100644 --- a/src/electron-app/WindowManager.js +++ b/src/electron-app/WindowManager.js @@ -101,7 +101,7 @@ class WindowManager { const webContents = window.webContents; // Enable remote API remoteMain.enable(window.webContents); - //window.removeMenu(); + window.removeMenu(); window.webContents.once('did-finish-load', () => { window.setTitle(options.title); }); diff --git a/src/main.js b/src/main.js index 70ccfff9f..e65c7a4a0 100644 --- a/src/main.js +++ b/src/main.js @@ -45,7 +45,7 @@ let grblLog = log.create('grbl'); let logPath; if (process.env.NODE_ENV === 'production') { - Sentry.init({ dsn: 'https://c09ff263997c4a47ba22b3c948f19734@o558751.ingest.sentry.io/5692684' }); + Sentry.init({ dsn: 'https://c09ff263997c4a47ba22b3c948f19734@o558751.ingest.sentry.io/5692684', release: pkg.version }); } const main = () => { @@ -182,7 +182,9 @@ const main = () => { }); autoUpdater.on('update-available', (info) => { - window.webContents.send('update_available', info); + setTimeout(() => { + window.webContents.send('update_available', info); + }, 5000); }); autoUpdater.on('error', (err) => { @@ -344,7 +346,7 @@ const main = () => { } autoUpdater.autoDownload = false; // We don't want to force update but will prompt until it is updated // There may be situations where something is blocking the update check outside of internet connectivity - // This sets a 5 second timeout on the await. + // This sets a 4 second timeout on the await. asyncCallWithTimeout(autoUpdater.checkForUpdates(), 4000); } }); diff --git a/src/package.json b/src/package.json index 40dac902b..f90158b75 100644 --- a/src/package.json +++ b/src/package.json @@ -1,6 +1,6 @@ { - "name": "gSender-Edge", - "version": "1.3.10-EDGE", + "name": "gSender", + "version": "1.4.1", "productName": "gSender", "description": "CNC Milling Controller", "author": { diff --git a/src/server/controllers/Grbl/GrblController.js b/src/server/controllers/Grbl/GrblController.js index d6f89d5dc..f0dfda1a3 100644 --- a/src/server/controllers/Grbl/GrblController.js +++ b/src/server/controllers/Grbl/GrblController.js @@ -248,7 +248,7 @@ class GrblController { } } } - return data; + return data.replace(/\([^\)]*\)/gm, ''); } }); @@ -270,7 +270,6 @@ class GrblController { const commentString = (comment && comment[0].length > 0) ? comment[0].trim() .replace(';', '') : ''; line = line.replace(commentMatcher, '') - .replace('/uFEFF', '') .trim(); context = this.populateContext(context); @@ -420,7 +419,7 @@ class GrblController { line = line.replace(bracketCommentLine, '').trim(); let comment = line.match(commentMatcher); let commentString = (comment && comment[0].length > 0) ? comment[0].trim().replace(';', '') : ''; - line = line.replace(commentMatcher, '').replace('/uFEFF', '').trim(); + line = line.replace(commentMatcher, '').trim(); context = this.populateContext(context); const { sent, received } = this.sender.state; @@ -751,7 +750,7 @@ class GrblController { this.emit('error', { type: ERROR, code: `${code}`, - description: error.description, + description: _.get(error, 'description', ''), line: line, lineNumber: isFileError ? received + 1 : '', origin: errorOrigin, @@ -1938,7 +1937,7 @@ class GrblController { //axes.Z = calculateAxisValue({ direction: Math.sign(axes.Z), position: mpos.z, maxTravel: (-1 * $132) }); } } else { - jogFeedrate = 1250; + jogFeedrate = 10000; Object.keys(axes).forEach((axis) => { axes[axis] *= jogFeedrate; }); diff --git a/src/server/controllers/Grblhal/GrblHalController.js b/src/server/controllers/Grblhal/GrblHalController.js index 69d57d6ca..9f79c4c0a 100644 --- a/src/server/controllers/Grblhal/GrblHalController.js +++ b/src/server/controllers/Grblhal/GrblHalController.js @@ -46,9 +46,11 @@ import monitor from '../../services/monitor'; import taskRunner from '../../services/taskrunner'; import store from '../../store'; import { + A_AXIS_COMMANDS, GLOBAL_OBJECTS as globalObjects, WRITE_SOURCE_CLIENT, - WRITE_SOURCE_FEEDER + WRITE_SOURCE_FEEDER, + Y_AXIS_COMMANDS } from '../constants'; import GrblHalRunner from './GrblHalRunner'; import { @@ -82,6 +84,7 @@ import { determineMachineZeroFlagSet, determineMaxMovement, getAxisMaximumLocati import { calcOverrides } from '../runOverride'; import ToolChanger from '../../lib/ToolChanger'; import { GRBL_ACTIVE_STATE_CHECK } from 'server/controllers/Grbl/constants'; +import { GCODE_TRANSLATION_TYPE, translateGcode } from '../../lib/gcode-translation'; // % commands const WAIT = '%wait'; const PREHOOK_COMPLETE = '%pre_complete'; @@ -196,6 +199,9 @@ class GrblHalController { // Toolchange toolChanger = null; + // Rotary + isInRotaryMode = false; + constructor(engine, options) { if (!engine) { throw new Error('engine must be specified'); @@ -336,6 +342,23 @@ class GrblHalController { line = line.replace('M6', '(M6)'); } + if (this.isInRotaryMode) { + const containsACommand = A_AXIS_COMMANDS.test(line); + const containsYCommand = Y_AXIS_COMMANDS.test(line); + + if (containsACommand && !containsYCommand) { + const isUsingImperialUnits = context.modal.units === 'G20'; + + line = translateGcode({ + gcode: line, + from: 'A', + to: 'Y', + regex: A_AXIS_COMMANDS, + type: isUsingImperialUnits ? GCODE_TRANSLATION_TYPE.TO_IMPERIAL : GCODE_TRANSLATION_TYPE.DEFAULT + }); + } + } + return line; } }); @@ -479,6 +502,30 @@ class GrblHalController { line = line.replace(`${tool?.[0]}`, `(${tool?.[0]})`); } + /** + * Rotary Logic + * Need to change the A-axis movements to Y-movements to emulate the rotary axis on grbl + */ + if (this.isInRotaryMode) { + const containsACommand = A_AXIS_COMMANDS.test(line); + const containsYCommand = Y_AXIS_COMMANDS.test(line); + + if (containsACommand && !containsYCommand) { + const isUsingImperialUnits = context.modal.units === 'G20'; + + line = translateGcode({ + gcode: line, + from: 'A', + to: 'Y', + regex: A_AXIS_COMMANDS, + type: isUsingImperialUnits ? GCODE_TRANSLATION_TYPE.TO_IMPERIAL : GCODE_TRANSLATION_TYPE.DEFAULT + }); + } + } + /** + * End of Rotary Logic + */ + return line; } }); @@ -688,7 +735,7 @@ class GrblHalController { this.emit('error', { type: ERROR, code: `${code}`, - description: error.description || '', + description: error?.description || '', line: line, lineNumber: isFileError ? received + 1 : '', origin: errorOrigin, @@ -1898,7 +1945,7 @@ class GrblHalController { axes.Z = calculateAxisValue({ direction: Math.sign(axes.Z), position: Math.abs(mpos.z), maxTravel: $132 }); } } else { - jogFeedrate = 1250; + jogFeedrate = 10000; Object.keys(axes).forEach((axis) => { axes[axis] *= jogFeedrate; }); @@ -2031,6 +2078,10 @@ class GrblHalController { const [estimateData] = args; this.sender.setEstimateData(estimateData.estimates); this.sender.setEstimatedTime(estimateData.estimatedTime); + }, + 'updateRotaryMode': () => { + const [isInRotaryMode] = args; + this.isInRotaryMode = isInRotaryMode; } }[cmd]; diff --git a/src/server/services/cncengine/CNCEngine.js b/src/server/services/cncengine/CNCEngine.js index 27a779cf6..5fdaf72cc 100644 --- a/src/server/services/cncengine/CNCEngine.js +++ b/src/server/services/cncengine/CNCEngine.js @@ -271,7 +271,7 @@ class CNCEngine { }); // Filter ports by productId to avoid non-arduino devices from appearing - const validProductIDs = ['6015', '6001', '606D', '003D', '0042', '0043', '2341', '7523', 'EA60', '2303', '2145', '0AD8', '08D8', '5740']; + const validProductIDs = ['6015', '6001', '606D', '003D', '0042', '0043', '2341', '7523', 'EA60', '2303', '2145', '0AD8', '08D8', '5740', '0FA7']; const validVendorIDs = ['1D50', '0403', '2341', '0042', '1A86', '10C4', '067B', '03EB', '16D0', '0483']; let [recognizedPorts, unrecognizedPorts] = partition(ports, (port) => { return validProductIDs.includes(port.productId) && validVendorIDs.includes(port.vendorId); @@ -332,7 +332,7 @@ class CNCEngine { }); // Open serial port - socket.on('open', (port, controllerType, options, callback = noop) => { + socket.on('open', (port, controllerType = GRBL, options, callback = noop) => { //const numClients = this.io.sockets.adapter.rooms.get(port)?.size || 0; if (typeof callback !== 'function') { callback = noop;