├── .github └── workflows │ └── main.yml ├── .gitignore ├── BaseLinux ├── raspi64 │ └── Linux ├── raspihf │ └── Linux ├── recore │ ├── Linux │ └── u-boot └── replicape │ ├── Linux │ ├── Toggle │ └── U-Boot ├── LICENSE ├── README.md ├── SYSTEM_klipper_mainsail-DEFAULT.yml ├── SYSTEM_klipper_octoprint-DEFAULT.yml ├── addons ├── INSTALL_smbshare.yml ├── INSTALL_usbreset.yml └── roles │ ├── install_smbshare │ ├── files │ │ └── smb.conf │ └── tasks │ │ └── main.yml │ └── install_usbreset │ ├── files │ └── usbreset.c │ └── tasks │ └── main.yml ├── build-image-in-chroot-end-to-end.sh ├── generate-image-from-sd.sh ├── hosts ├── image.layout ├── legacy ├── README.md ├── install_dummy_logger │ └── meta │ │ └── main.yml ├── install_framebuffer │ ├── files │ │ ├── powervr.ini │ │ ├── sgx-libgbm.deb │ │ └── sgx-ti335x-userspace-1.14.3699939_1.1.deb │ └── tasks │ │ └── main.yml └── install_mjpgstreamer │ ├── files │ ├── mjpg.service │ └── mjpg_recore.service │ └── tasks │ ├── main.yml │ ├── pi.yml │ ├── recore.yml │ └── replicape.yml ├── make-refactor.sh └── roles ├── install_autohotspot ├── files │ ├── autohotspot │ └── autohotspot.service └── tasks │ ├── main.yml │ └── recore.yml ├── install_klipper ├── files │ ├── ar100.config │ ├── bl31.bin │ ├── enable-i2c.patch │ ├── flash-stm32 │ ├── flash-stm32.service │ ├── generic-recore-a5.cfg │ ├── generic-recore-a6.cfg │ ├── generic-recore-a7.cfg │ ├── install-recore.sh │ ├── klipper-pru.path │ ├── klipper-recore.service │ ├── klipper.service │ ├── klipper_host_mcu.service │ ├── klipper_pru │ ├── klipper_pru.service │ ├── klippy.service │ ├── octoprint_config.yaml │ ├── octoprint_replicape.service │ ├── pru_config │ ├── recore.py │ ├── recore_a5.py │ ├── recore_adc_temperature.py │ ├── recore_config │ ├── recore_thermistor.py │ ├── remoteproc1.path │ ├── replicape_linux_config │ ├── stm32f031-32KB-serial.config │ ├── stm32f031-serial.config │ ├── thermocouple.py │ ├── tmc2130_a5.py │ ├── tmc2209_a5.py │ └── uEnv.txt ├── meta │ └── main.yml ├── tasks │ ├── main.yml │ ├── pi.yml │ ├── recore.yml │ └── replicape.yml └── vars │ └── main.yml ├── install_klipperscreen ├── files │ ├── KlipperScreen.conf │ └── KlipperScreen.service ├── meta │ └── main.yml └── tasks │ ├── main.yml │ └── recore.yml ├── install_mainsail ├── files │ ├── common_vars.conf │ ├── mainsail │ ├── mainsail.cfg │ └── upstreams.conf ├── meta │ └── main.yml └── tasks │ ├── main.yml │ └── recore.yml ├── install_moonraker ├── files │ ├── moonraker.conf │ ├── moonraker.service │ └── recore.py ├── meta │ └── main.yml └── tasks │ ├── main.yml │ └── recore.yml ├── install_octoprint ├── files │ ├── config_recore.yaml │ ├── config_replicape.yaml │ ├── enable-octoprint │ ├── nftables.conf │ └── octoprint.service ├── meta │ └── main.yml ├── tasks │ ├── main.yml │ ├── recore.yml │ └── replicape.yml └── vars │ └── main.yml ├── install_octoprint_klipper_plugins ├── meta │ └── main.yml └── tasks │ └── main.yml ├── install_toggle ├── files │ ├── toggle-runfirst │ ├── toggle-runfirst.service │ ├── toggle.service │ └── toggle_recore.service ├── meta │ └── main.yml ├── tasks │ ├── main.yml │ ├── pi.yml │ ├── recore.yml │ └── replicape.yml └── vars │ └── main.yml ├── install_ustreamer ├── files │ └── ustreamer.service ├── meta │ └── main.yml └── tasks │ ├── main.yml │ └── recore.yml ├── install_weston ├── meta │ └── main.yml └── tasks │ ├── main.yml │ └── recore.yml └── linux_preparation ├── files ├── 100update ├── cpufreq.service ├── cpufreq.sh ├── get-boot-media ├── get-recore-config ├── get-recore-revision ├── get-recore-serial-number ├── get-rootfs ├── get_refactor_version.sh ├── is-media-present ├── is-ssh-enabled ├── refactor-apt-upgrade ├── set-boot-media ├── set-recore-revision ├── set-ssh-access └── update-recore-revision ├── tasks ├── main.yml ├── pi.yml ├── recore.yml └── replicape.yml └── vars └── main.yml /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build Refactor on AWS 2 | on: push 3 | jobs: 4 | build-recore-octoprint: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Checkout 8 | uses: actions/checkout@v2 9 | - name: Build Refactor Recore with OctoPrint on AWS 10 | uses: garygrossgarten/github-action-ssh@release 11 | with: 12 | command: | 13 | cd Refactor 14 | git fetch 15 | export branch=$(echo ${{github.ref}} | cut -d'/' -f 3-) 16 | git reset --hard 17 | git checkout --force $branch 18 | git pull 19 | git log HEAD --oneline --no-walk 20 | rm -rf Refactor-*.xz 21 | ls armbian*.img.xz | grep -v $(date +"%F") | xargs -d"\n" rm -rf 22 | sudo ./build-image-in-chroot-end-to-end.sh recore 23 | host: ${{ secrets.HOST }} 24 | username: ${{ secrets.USERNAME }} 25 | privateKey: ${{ secrets.PRIVATE_KEY}} 26 | env: 27 | CI: true 28 | - name: Download file via SSH if tagged 29 | uses: nicklasfrahm/scp-action@main 30 | if: startsWith(github.ref, 'refs/tags/') 31 | with: 32 | direction: download 33 | host: ${{ secrets.HOST }} 34 | fingerprint: ${{ secrets.EC2_FINGERPRINT }} 35 | username: ${{ secrets.USERNAME }} 36 | key: ${{ secrets.PRIVATE_KEY }} 37 | source: /home/admin/Refactor/Refactor-recore-latest.img.xz 38 | target: ./Refactor-recore-octoprint-latest.img.xz 39 | - name: Rename file 40 | if: startsWith(github.ref, 'refs/tags/') 41 | run: | 42 | TAG=$(git log -n1 --pretty="format:%d" | sed "s/, /\n/g" | grep tag: | grep -v origin | sed "s/tag: \|)//g" | tr -d '\n') 43 | if [[ $TAG == "" ]]; then 44 | TAG=$(git reflog --decorate -1 | awk -F' ' '{print $1}' | tr -d '\n') 45 | fi 46 | DATE=$(date --iso-8601) 47 | mv ./Refactor-recore-octoprint-latest.img.xz Refactor-recore-octoprint-${TAG}-${DATE}.img.xz 48 | - name: Release if tagged 49 | uses: ncipollo/release-action@v1 50 | if: startsWith(github.ref, 'refs/tags/') 51 | with: 52 | allowUpdates: true 53 | artifacts: Refactor-recore-octoprint-*.img.xz 54 | token: ${{ secrets.GITHUB_TOKEN }} 55 | prerelease: true 56 | 57 | build-recore-mainsail: 58 | runs-on: ubuntu-latest 59 | steps: 60 | - name: Checkout 61 | uses: actions/checkout@v2 62 | - name: Build Refactor Recore with Mainsail on AWS 63 | uses: garygrossgarten/github-action-ssh@release 64 | with: 65 | command: | 66 | cd Refactor 67 | git fetch 68 | export branch=$(echo ${{github.ref}} | cut -d'/' -f 3-) 69 | git reset --hard 70 | git checkout --force $branch 71 | git pull 72 | git log HEAD --oneline --no-walk 73 | rm -rf Refactor-*.xz 74 | sudo ./build-image-in-chroot-end-to-end.sh recore SYSTEM_klipper_mainsail-DEFAULT.yml 75 | host: ${{ secrets.HOST_REPLICAPE }} 76 | username: ${{ secrets.USERNAME }} 77 | privateKey: ${{ secrets.PRIVATE_KEY}} 78 | env: 79 | CI: true 80 | - name: Download file via SSH if tagged 81 | uses: nicklasfrahm/scp-action@main 82 | if: startsWith(github.ref, 'refs/tags/') 83 | with: 84 | direction: download 85 | host: ${{ secrets.HOST_REPLICAPE }} 86 | fingerprint: ${{ secrets.EC2_FINGERPRINT_REPLICAPE }} 87 | username: ${{ secrets.USERNAME }} 88 | key: ${{ secrets.PRIVATE_KEY }} 89 | source: /home/admin/Refactor/Refactor-recore-latest.img.xz 90 | target: ./Refactor-recore-mainsail-latest.img.xz 91 | - name: Rename file if tagged 92 | if: startsWith(github.ref, 'refs/tags/') 93 | run: | 94 | TAG=$(git log -n1 --pretty="format:%d" | sed "s/, /\n/g" | grep tag: | grep -v origin | sed "s/tag: \|)//g" | tr -d '\n') 95 | if [[ $TAG == "" ]]; then 96 | TAG=$(git reflog --decorate -1 | awk -F' ' '{print $1}' | tr -d '\n') 97 | fi 98 | DATE=$(date --iso-8601) 99 | mv ./Refactor-recore-mainsail-latest.img.xz Refactor-recore-mainsail-${TAG}-${DATE}.img.xz 100 | - name: Release if tagged 101 | uses: ncipollo/release-action@v1 102 | if: startsWith(github.ref, 'refs/tags/') 103 | with: 104 | allowUpdates: true 105 | artifacts: Refactor-recore-mainsail-*.img.xz 106 | token: ${{ secrets.GITHUB_TOKEN }} 107 | prerelease: true 108 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Allow individual customization that is not in the repository 2 | customize.sh 3 | *.img 4 | *.img.* 5 | _config.yml 6 | .vscode 7 | image.layout -------------------------------------------------------------------------------- /BaseLinux/raspi64/Linux: -------------------------------------------------------------------------------- 1 | # This specifies the base Ubuntu system 2 | BASEIMAGE_URL=https://downloads.raspberrypi.org/raspbian_lite_latest 3 | BASEIMAGE=raspbian_lite.zip 4 | 5 | ANSIBLE_PLATFORM_VARS='{"platform":"pi64", "packaging":"apt"}' 6 | 7 | function decompress { 8 | mkdir -p ./raspbianhf-image 9 | unzip BASEIMAGE 10 | mv ./raspbian-image/*.img $TARGETIMAGE 11 | rm -r ./raspbian-image 12 | } 13 | -------------------------------------------------------------------------------- /BaseLinux/raspihf/Linux: -------------------------------------------------------------------------------- 1 | # This specifies the base Ubuntu system 2 | BASEIMAGE_URL=https://downloads.raspberrypi.org/raspbian_lite_latest 3 | BASEIMAGE=raspbian_lite.zip 4 | 5 | ANSIBLE_PLATFORM_VARS='{"platform":"pi", "packaging":"apt"}' 6 | 7 | function decompress { 8 | mkdir -p ./raspbianhf-image 9 | unzip BASEIMAGE 10 | mv ./raspbian-image/*.img $TARGETIMAGE 11 | rm -r ./raspbian-image 12 | } 13 | -------------------------------------------------------------------------------- /BaseLinux/recore/Linux: -------------------------------------------------------------------------------- 1 | # This specifies the base image system 2 | BASEIMAGE_URL=https://github.com/intelligent-agent/Rebuild/releases/download/v0.0.1-RC7/rebuild-barebone-v0.0.1-RC7.img.xz 3 | 4 | BASEIMAGE=rebuild-barebone-v0.0.1-RC7.img.xz 5 | 6 | ANSIBLE_PLATFORM_VARS='{"platform":"recore", "packaging":"apt", "ansible_python_interpreter": "/usr/bin/python3"}' 7 | 8 | function decompress { 9 | xz -T0 -vc -c -d $BASEIMAGE >> $TARGETIMAGE 10 | } 11 | -------------------------------------------------------------------------------- /BaseLinux/recore/u-boot: -------------------------------------------------------------------------------- 1 | UBOOT_BIN="roles/install_uboot/files/u-boot-sunxi-with-spl.bin" 2 | -------------------------------------------------------------------------------- /BaseLinux/replicape/Linux: -------------------------------------------------------------------------------- 1 | # This specifies the base Ubuntu system 2 | BASEIMAGE_URL=https://debian.beagleboard.org/images/bone-debian-10.3-console-armhf-2020-04-06-1gb.img.xz 3 | BASEIMAGE=`basename ${BASEIMAGE_URL}` 4 | 5 | 6 | 7 | ANSIBLE_PLATFORM_VARS='{"platform":"replicape", "packaging":"apt"}' 8 | 9 | function decompress { 10 | xz -c -d $BASEIMAGE >> $TARGETIMAGE 11 | } 12 | -------------------------------------------------------------------------------- /BaseLinux/replicape/Toggle: -------------------------------------------------------------------------------- 1 | # This specifies the appropriate version of Toggle 2 | TOGGLE_REPOSITORY="https://github.com/intelligent-agent/toggle" 3 | TOGGLE_BRANCH="1.4.x" 4 | TOGGLE_BRANCH_SINCE="2018-01-15" 5 | TOGGLE_ENVIRONMENT="/usr/local/Toggle-${TOGGLE_BRANCH}" 6 | -------------------------------------------------------------------------------- /BaseLinux/replicape/U-Boot: -------------------------------------------------------------------------------- 1 | # This specifies the appropriate version of U-Boot 2 | # UBOOT_REPOSITORY="git://git.denx.de/u-boot.git" 3 | # UBOOT_BRANCH="master" 4 | UBOOT_HOME="${VERSIONING}/../u-boot" 5 | 6 | UBOOT_VERSION="2018.09-r8" 7 | 8 | UBOOT_SPL_URL="https://rcn-ee.com/repos/bootloader/am335x_evm/MLO-am335x_evm-v${UBOOT_VERSION}" 9 | UBOOT_SPL=`basename ${UBOOT_SPL_URL}` 10 | UBOOT_BIN_URL="https://rcn-ee.com/repos/bootloader/am335x_evm/u-boot-am335x_evm-v${UBOOT_VERSION}.img" 11 | UBOOT_BIN=`basename ${UBOOT_BIN_URL}` 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Refactor 2 | Refactor is a Linux distro for Recore based on Armbian. 3 | 4 | [![Build](https://github.com/intelligent-agent/Refactor/actions/workflows/main.yml/badge.svg)](https://github.com/intelligent-agent/Refactor/actions/workflows/main.yml) 5 | 6 | The starting point for Refactor is the Armbian console image, details are in the wiki here: 7 | https://wiki.iagent.no/wiki/Refactor 8 | 9 | This build system will install Klipper and the choice of OctoPrint or Mainsail and Moonraker. 10 | A touch screen interface is also installed, either Toggle for OctoPrint or KlipperScreen for Mainsail. 11 | In addition, there are some other programs such as mjpg-streamer to add webcam functionality and the setting up the 12 | right folders and config files so the software is ready to use out of the box. 13 | 14 | The hostname for Recore is `recore`. 15 | 16 | During installation using Reflash, the user can choose to leave the SSH access for user `debian` open or closed. If you choose to have it open, you should log in as user `debian` which will force a change of password. The USB C connector also presents the a serial port which will always allow anyone with physical access to the board to log in. Default passwords are: 17 | Username/password: `root`/`kamikaze` 18 | Username/password: `debian`/`temppwd` 19 | 20 | ## Running the image generation on the command line 21 | The images generated are focused on being a boot-strapped firmware for Thing-Printer control boards, such as Replicape and Recore. PRs to make Refactor better are welcome. To support multiple platforms, the build script usage has been modified: 22 | ``` 23 | cd 24 | sudo ./build-image-in-chroot-end-to-end.sh [OPTIONAL: system setup script] 25 | ``` 26 | If not specified, the _ansible-playbook_ that is used is ___SYSTEM_klipper_octoprint-DEFAULT.yml___ 27 | 28 | The script then exports the `platform` ansible variable, and sources the `BaseLinux/$platform/Linux` file for a number of items: 29 | * a URL for which base linux image to build from (pine64 armbian for `pi64` and `recore`, RCN-built console debian 10.3 for `replicape`, raspbian for `pi`) 30 | * the `decompress()` function, to allow the script to properly decompress the downloaded file and export the image file to where it can be mounted 31 | * additional ansible parameters specific to the platform requirements. For the moment this is where the `platform` gets passed through, as well as the `firmware` variable. 32 | 33 | **IMPORTANT NOTE**: Only the `SYSTEM-[...].yml` playbook files can work with the `build-image-in-chroot-end-to-end.sh` script. The `INSTALL-[...].yml` playbooks are provided as means for end-users to customize their running images. It is inadvisable to run a `SYSTEM-[...].yml` playbook on an already running system. And especially not during a print. That would cause a division by zero and make the printer disappear into its own micro black hole. Or release the magic smoke. Either way, not a good thing. You have been warned. 34 | 35 | # Contributing 36 | Any contribution you make should be in the form of a PR in a separate branch and mull against master. 37 | It's nice to add a descriptive prefix like `chore/clean-up-unused-code` 38 | If you are trying to fix a bug, please prefix the `PR` with `[bug]`, and mention the Github Issue # in the PR description. 39 | 40 | In case you need help building an image to test your changes and do not have a build environment available, please submit your PR against `goeland86/ReFactor`, with a title prefixed with `[Dev]` to clearly identify that the features are still under active development. 41 | 42 | # Latest images 43 | Latest images for testing are uploaded to github: https://github.com/intelligent-agent/Refactor/releases 44 | -------------------------------------------------------------------------------- /SYSTEM_klipper_mainsail-DEFAULT.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | vars: 5 | - firmware: klipper 6 | roles: 7 | - install_klipper 8 | - install_ustreamer 9 | - install_moonraker 10 | - install_mainsail 11 | - install_klipperscreen 12 | - install_autohotspot 13 | -------------------------------------------------------------------------------- /SYSTEM_klipper_octoprint-DEFAULT.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | vars: 5 | - firmware: klipper 6 | roles: 7 | - install_klipper 8 | - install_octoprint 9 | - install_octoprint_klipper_plugins 10 | - install_ustreamer 11 | - install_toggle 12 | - install_autohotspot 13 | -------------------------------------------------------------------------------- /addons/INSTALL_smbshare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | vars: 5 | - firmware: klipper 6 | roles: 7 | - install_smbshare 8 | -------------------------------------------------------------------------------- /addons/INSTALL_usbreset.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | vars: 5 | - firmware: klipper 6 | roles: 7 | - install_usbreset 8 | -------------------------------------------------------------------------------- /addons/roles/install_smbshare/files/smb.conf: -------------------------------------------------------------------------------- 1 | dns proxy = no 2 | log file = /var/log/samba/log.%m 3 | syslog = 0 4 | panic action = /usr/share/samba/panic-action %d 5 | server role = standalone server 6 | passdb backend = tdbsam 7 | obey pam restrictions = yes 8 | unix password sync = yes 9 | passwd program = /usr/bin/passwd %u 10 | passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . 11 | pam password change = yes 12 | map to guest = bad user 13 | usershare allow guests = yes 14 | 15 | [homes] 16 | comment = Home Directories 17 | browseable = no 18 | read only = no 19 | create mask = 0777 20 | directory mask = 0777 21 | valid users = %S 22 | 23 | [printers] 24 | comment = All Printers 25 | browseable = no 26 | path = /var/spool/samba 27 | printable = yes 28 | guest ok = no 29 | read only = yes 30 | create mask = 0700 31 | 32 | [print$] 33 | comment = Printer Drivers 34 | path = /var/lib/samba/printers 35 | browseable = yes 36 | read only = yes 37 | guest ok = no 38 | 39 | [public] 40 | path = /home/debian/.octoprint/uploads 41 | public = yes 42 | writable = yes 43 | comment = smb share 44 | printable = no 45 | guest ok = yes 46 | locking = no -------------------------------------------------------------------------------- /addons/roles/install_smbshare/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: installing samba 3 | apt: 4 | name: samba 5 | state: present 6 | 7 | - name: installing smb.conf 8 | copy: 9 | src: '{{ role_path }}/files/smb.conf' 10 | dest: /etc/samba/smb.conf 11 | 12 | - name: enabling samba 13 | service: 14 | name: smbd 15 | enabled: yes -------------------------------------------------------------------------------- /addons/roles/install_usbreset/files/usbreset.c: -------------------------------------------------------------------------------- 1 | /* usbreset -- send a USB port reset to a USB device */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | int main(int argc, char **argv) 12 | { 13 | const char *filename; 14 | int fd; 15 | int rc; 16 | 17 | if (argc != 2) { 18 | fprintf(stderr, "Usage: usbreset device-filename\n"); 19 | return 1; 20 | } 21 | filename = argv[1]; 22 | 23 | fd = open(filename, O_WRONLY); 24 | if (fd < 0) { 25 | perror("Error opening output file"); 26 | return 1; 27 | } 28 | 29 | printf("Resetting USB device %s\n", filename); 30 | rc = ioctl(fd, USBDEVFS_RESET, 0); 31 | if (rc < 0) { 32 | perror("Error in ioctl"); 33 | return 1; 34 | } 35 | printf("Reset successful\n"); 36 | 37 | close(fd); 38 | return 0; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /addons/roles/install_usbreset/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install usb reset 3 | shell: 4 | cmd: 'cc {{ role_path }}/files/usbreset.c -o {{ role_path }}/files/usbreset && chmod +x {{role_path}}/files/usbreset && mv {{ role_path }}/files/usbreset /usr/local/bin/' 5 | -------------------------------------------------------------------------------- /build-image-in-chroot-end-to-end.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -lt 1 ]; then 4 | echo "We need to know which platform we're building for." 5 | echo "Should be one of: {replicape, recore, raspihf, raspi64}" 6 | echo "Usage: build-image-in-chroot-end-to-end.sh platform [system-build-script]" 7 | exit 8 | fi 9 | 10 | if [ "$#" -eq 2 ]; then 11 | SYSTEM_ANSIBLE=$2 12 | else 13 | SYSTEM_ANSIBLE=SYSTEM_klipper_octoprint-DEFAULT.yml 14 | fi 15 | 16 | if [ ! -f ${SYSTEM_ANSIBLE} ]; then 17 | echo "Could not find the system build playbook ${SYSTEM_ANSIBLE}. Cannot continue." 18 | exit 19 | fi 20 | 21 | set -x 22 | set -e 23 | 24 | 25 | TARGET_PLATFORM=$1 26 | 27 | for f in $(ls BaseLinux/${TARGET_PLATFORM}/*) 28 | do 29 | source $f 30 | done 31 | if [ -f "customize.sh" ] ; then 32 | source customize.sh 33 | fi 34 | 35 | TARGETIMAGE=refactor-${TARGET_PLATFORM}-rootfs.img 36 | MOUNTPOINT=$(mktemp -d /tmp/umikaze-root.XXXXXX) 37 | REFACTOR_HOME="/usr/src/Refactor" 38 | 39 | if [ ! -f $BASEIMAGE ]; then 40 | wget -q $BASEIMAGE_URL -O $BASEIMAGE 41 | fi 42 | 43 | rm -f $TARGETIMAGE 44 | decompress || $(echo "check your Linux platform file is correct!"; exit) # defined in the BaseLinux/{platform}/Linux file 45 | 46 | echo "preparing the partition layout" 47 | if [ ${TARGET_PLATFORM} == "recore" ]; then 48 | truncate -s 6000M $TARGETIMAGE 49 | DEVICE=`losetup -P -f --show $TARGETIMAGE` 50 | PARTITION=${DEVICE}p2 51 | cat < image.layout 52 | # partition table of ${DEVICE} 53 | unit: sectors 54 | 55 | ${DEVICE}p1 : start=8192, size=524288, type=83 56 | ${DEVICE}p2 : start=532480, size=11303520, type=83 57 | EOF 58 | fi 59 | 60 | if [ ${TARGET_PLATFORM} == 'replicape' ]; then 61 | truncate -s 3600M $TARGETIMAGE 62 | DEVICE=`losetup -P -f --show $TARGETIMAGE` 63 | PARTITION=${DEVICE}p1 64 | cat < image.layout 65 | # partition table of ${DEVICE} 66 | unit: sectors 67 | 68 | ${DEVICE}p1 : start=8192, size=7364608, type=83 69 | EOF 70 | fi 71 | 72 | 73 | sfdisk --delete ${DEVICE} 74 | # Perform actual modifications to the partition layout 75 | sfdisk ${DEVICE} < image.layout 76 | echo "checking the filesystem..." 77 | 78 | e2fsck -f -p ${PARTITION} 79 | clean_status=$? 80 | if [ "$clean_status" -ne "0" ]; then 81 | echo "had to clear out something on the FS..." 82 | fi 83 | echo "resizing" 84 | resize2fs ${PARTITION} 85 | 86 | echo "Beginning the mount sequence." 87 | mount ${PARTITION} ${MOUNTPOINT} 88 | if [ ${TARGET_PLATFORM} == "recore" ]; then 89 | mount ${DEVICE}p1 ${MOUNTPOINT}/boot 90 | fi 91 | mount -o bind /dev ${MOUNTPOINT}/dev 92 | mount -o bind /sys ${MOUNTPOINT}/sys 93 | mount -o bind /proc ${MOUNTPOINT}/proc 94 | mount -o bind /dev/pts ${MOUNTPOINT}/dev/pts 95 | 96 | rm ${MOUNTPOINT}/etc/resolv.conf 97 | echo "nameserver 8.8.8.8" >> ${MOUNTPOINT}/etc/resolv.conf 98 | 99 | # don't git clone here - if someone did a commit since this script started, Unexpected Things will happen 100 | # instead, do a deep copy so the image has a git repo as well 101 | mkdir -p ${MOUNTPOINT}${REFACTOR_HOME} 102 | 103 | shopt -s dotglob # include hidden files/directories so we get .git 104 | shopt -s extglob # allow excluding so we can hide the img files 105 | cp -r `pwd`/!(*.img*|*.7z) ${MOUNTPOINT}${REFACTOR_HOME} 106 | shopt -u extglob 107 | shopt -u dotglob 108 | 109 | set +e # allow this to fail - we'll check the return code 110 | chroot ${MOUNTPOINT} su -c "\ 111 | export DEBIAN_FRONTEND=noninteractive && \ 112 | cd ${REFACTOR_HOME} && \ 113 | apt update && \ 114 | apt install -y ansible python && \ 115 | ansible-playbook ${SYSTEM_ANSIBLE} -T 180 --extra-vars '${ANSIBLE_PLATFORM_VARS}' -i hosts" 116 | 117 | status=$? 118 | set -e 119 | 120 | rm -rf ${MOUNTPOINT}${REFACTOR_HOME} 121 | rm -rf ${MOUNTPOINT}/root/.ansible 122 | 123 | rm ${MOUNTPOINT}/etc/resolv.conf 124 | umount -l ${MOUNTPOINT}/dev/pts 125 | umount -l ${MOUNTPOINT}/dev 126 | umount -l ${MOUNTPOINT}/proc 127 | umount -l ${MOUNTPOINT}/sys 128 | if [ ${TARGET_PLATFORM} == "recore" ]; then 129 | umount -l ${MOUNTPOINT}/boot 130 | fi 131 | umount -l ${MOUNTPOINT} 132 | rmdir ${MOUNTPOINT} 133 | 134 | if [ $status -eq 0 ]; then 135 | echo "Looks like the image was prepared successfully - packing it up" 136 | if [ ${TARGET_PLATFORM} == 'replicape' ]; then 137 | if [ ! -f ${UBOOT_SPL} ] ; then 138 | wget ${UBOOT_SPL_URL} 139 | fi 140 | if [ ! -f ${UBOOT_BIN} ] ; then 141 | wget ${UBOOT_BIN_URL} 142 | fi 143 | dd if=${UBOOT_SPL} of=${DEVICE} seek=1 bs=128k 144 | dd if=${UBOOT_BIN} of=${DEVICE} seek=1 bs=384k 145 | fi 146 | ./generate-image-from-sd.sh $DEVICE $TARGET_PLATFORM 147 | losetup -d $DEVICE 148 | else 149 | echo "image generation seems to have failed - cleaning up, returning $status" 150 | losetup -d $DEVICE 151 | exit ${status} 152 | fi 153 | -------------------------------------------------------------------------------- /generate-image-from-sd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script currently does not have error checking in it and has not been heavily tested. 4 | # use this script at your own risk. 5 | # 6 | # If you are debugging or just concerned uncomment the "set -e" line below to force the script to 7 | # terminate on any error. This includes erroring on already existing directories and similar minor issues. 8 | 9 | set -e 10 | set -x 11 | 12 | #echo 13 | #echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 14 | #echo "! This script currently does not have error checking in it and has not been heavily tested. !" 15 | #echo "! As such use this script at your own risk till it can be refined further. !" 16 | #echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 17 | #echo 18 | #echo "This script will resize the file system and partition on the SD card to as small as possible." 19 | #echo "After this it will clone the results to an image file on USB drive" 20 | #echo 21 | #echo "Please make sure the SD card and FAT formatted USB drive are inserted." 22 | #read -rsp $'Press any key to continue...\n' -n1 key 23 | 24 | # This is commended out because it currently cannot work, the script shuts the BB down after running 25 | #echo "Running script to clone eMMC to SD" 26 | #echo "/opt/scripts/tools/eMMC/beaglebone-black-make-microSD-flasher-from-eMMC.sh" 27 | echo 28 | 29 | DEVICE=$1 30 | TARGET_PLATFORM=$2 31 | if [ ${TARGET_PLATFORM} == "recore" ]; then 32 | PARTITION=${DEVICE}p2 33 | fi 34 | if [ ${TARGET_PLATFORM} == "replicape" ]; then 35 | PARTITION=${DEVICE}p1 36 | fi 37 | 38 | echo "Device: $DEVICE" 39 | echo "Partition: $PARTITION" 40 | 41 | # This makes it so the image will boot on other BB not just the one it was built on 42 | MOUNTPOINT=$(mktemp -d /tmp/Refactor-sd.XXXXXX) 43 | mount $PARTITION ${MOUNTPOINT} 44 | if [ ${TARGET_PLATFORM} == 'replicape' ]; then 45 | echo "Removing UUID references and uncommenting flasher option from /boot/uEnv.txt" 46 | sed -ie '/^uuid=/d' ${MOUNTPOINT}/boot/uEnv.txt 47 | #sed -ie 's/#cmdline=init=\/opt\/scripts\/tools\/eMMC\/init-eMMC-flasher-v3.sh$/cmdline=init=\/opt\/scripts\/tools\/eMMC\/init-eMMC-flasher-v3.sh/' ${MOUNTPOINT}/boot/uEnv.txt 48 | fi 49 | 50 | echo "Removing WPA wifi access file just in case" 51 | rm -rf ${MOUNTPOINT}/root/wpa.conf 52 | echo "Clearing bash history" 53 | rm -rf ${MOUNTPOINT}/root/.bash_history 54 | rm -rf ${MOUNTPOINT}/home/ubuntu/.bash_history 55 | echo 56 | 57 | # Likely not needed but for the sake of making the image smaller we defrag first 58 | echo "Defragmenting partition mounted at ${MOUNTPOINT}." 59 | e4defrag -c ${MOUNTPOINT} > /dev/null 60 | umount -l ${MOUNTPOINT} 61 | if [[ $(mount | grep ${PARTITION}) ]]; then 62 | fuser -km ${MOUNTPOINT} # as described here: https://serverfault.com/a/59037 63 | umount -l ${MOUNTPOINT} 64 | fi 65 | 66 | # Run file system checks and then shrink the file system as much as possible 67 | echo "Resizing filesystem." 68 | if [[ $(mount | grep ${PARTITION}) ]]; then 69 | fuser -km ${MOUNTPOINT} 70 | umount -l ${MOUNTPOINT} 71 | fi 72 | e2fsck -f $PARTITION -y 73 | resize2fs -pM $PARTITION 74 | resize2fs -pM $PARTITION 75 | e2fsck -f $PARTITION -y 76 | echo 77 | 78 | # Zero out the free space remaining on the file system 79 | echo "Defrag and zero partition free space." 80 | mount $PARTITION ${MOUNTPOINT} 81 | e4defrag -c ${MOUNTPOINT} > /dev/null 82 | dd if=/dev/zero of=${MOUNTPOINT}/zero_fill || true 83 | rm -rf ${MOUNTPOINT}/zero_fill 84 | umount -l ${MOUNTPOINT} 85 | if [[ $(mount | grep ${PARTITION}) ]]; then 86 | fuser -km ${MOUNTPOINT} # as described here: https://serverfault.com/a/59037 87 | umount -l ${MOUNTPOINT} 88 | fi 89 | echo 90 | 91 | # Run the file system checks and another series of file system shrinks just in case 92 | # we can shrink the file system any further after zeroing the free space. 93 | echo "Resizing filesystem again." 94 | e2fsck -f $PARTITION -y 95 | resize2fs -pM $PARTITION 96 | e2fsck -f $PARTITION -y 97 | echo 98 | 99 | # This is where the real danger starts with modifying the partitions 100 | echo "Shrinking partition now." 101 | # Gather useful partition data 102 | fsblockcount=$(tune2fs -l $PARTITION | grep "Block count:" | awk '{printf $3}') 103 | fsblocksize=$(tune2fs -l $PARTITION | grep "Block size:" | awk '{printf $3}') 104 | partblocksize=$(fdisk -l $PARTITION | grep Units: | awk '{printf $8}') 105 | partblockstart=$(fdisk -l -o Device,Start $DEVICE | grep $PARTITION | awk '{printf $2}') 106 | partsize=$((fsblockcount*fsblocksize/partblocksize)) 107 | 108 | # Write out the partition layout that will replace the currently existing one. 109 | if [ ${TARGET_PLATFORM} == "recore" ]; then 110 | cat < shrink.layout 111 | # partition table of ${DEVICE} 112 | unit: sectors 113 | 114 | ${DEVICE}p1 : start=8192, size=524288, type=83 115 | ${DEVICE}p2 : start=${partblockstart}, size=${partsize}, Id=83 116 | EOF 117 | fi 118 | if [ ${TARGET_PLATFORM} == 'replicape' ]; then 119 | cat < shrink.layout 120 | # partition table of ${DEVICE} 121 | unit: sectors 122 | 123 | ${DEVICE}p1 : start=${partblockstart}, size=${partsize}, type=83 124 | EOF 125 | fi 126 | # Perform actual modifications to the partition layout 127 | sfdisk $DEVICE < shrink.layout 128 | #rm -rf /shrink.layout 129 | 130 | # Make sure the system sees the new partition layout, check the file system for issues 131 | # and then resize the file system to the full size of the new partition if it is needed 132 | echo "Re-read partition table" 133 | #hdparm -z $DEVICE 134 | sync 135 | echo "Wait for the kernel to re-read the table" 136 | sleep 5 137 | 138 | e2fsck -f $PARTITION -y 139 | resize2fs $PARTITION 140 | e2fsck -f $PARTITION -y 141 | echo 142 | 143 | # Run one last defrag and zero of the free space before backing it up 144 | echo "Final defrag and zeroing partition free space." 145 | mount $PARTITION ${MOUNTPOINT} 146 | ImageVersion=$(cat ${MOUNTPOINT}/etc/refactor.version | sed 's/ /-/g' | awk -F' ' '{printf $1}') 147 | e4defrag -c ${MOUNTPOINT} > /dev/null 148 | # ignore the failure on this line - it runs until it's out of space 149 | dd if=/dev/zero of=${MOUNTPOINT}/zero_fill || true 150 | rm -rf ${MOUNTPOINT}/zero_fill 151 | umount -l ${MOUNTPOINT} 152 | if [[ $(mount | grep ${PARTITION}) ]]; then 153 | fuser -km ${MOUNTPOINT} # as described here: https://serverfault.com/a/59037 154 | umount -l ${MOUNTPOINT} 155 | fi 156 | rmdir ${MOUNTPOINT} 157 | echo 158 | 159 | # Final file system check 160 | echo "File system and partition shrink are complete, running last file system check." 161 | e2fsck -f $PARTITION -y 162 | echo 163 | 164 | # Mounting the USB thumb drive and generating the compressed image file on it from the sd card 165 | echo "Generating image file now." 166 | blocksize=$(fdisk -l $DEVICE | grep Units: | awk '{printf $8}') 167 | count=$(fdisk -l -o Device,End $DEVICE | grep $PARTITION | awk '{printf $2}') 168 | ddcount=$((count*blocksize/1000000+1)) 169 | dd if=$DEVICE bs=1MB count=${ddcount} | xz -vc -0 -T 0 > Refactor-${TARGET_PLATFORM}-"${ImageVersion}".img.xz 170 | ln -sf Refactor-${TARGET_PLATFORM}-"${ImageVersion}".img.xz Refactor-${TARGET_PLATFORM}-latest.img.xz 171 | 172 | # Talkie talkie 173 | echo "***************************************************************************************" 174 | echo "Image file generated on USB drive as Refactor-${TARGET_PLATFORM}-${ImageVersion}.img.xz" 175 | echo "USB drive and MicroSD card can be removed safely now." 176 | echo "***************************************************************************************" 177 | -------------------------------------------------------------------------------- /hosts: -------------------------------------------------------------------------------- 1 | [local] 2 | localhost 3 | -------------------------------------------------------------------------------- /image.layout: -------------------------------------------------------------------------------- 1 | label: dos 2 | label-id: 0x9e9adf64 3 | device: /dev/loop8 4 | unit: sectors 5 | 6 | /dev/loop8p1 : start= 8192, size= 524288, type=83 7 | /dev/loop8p2 : start= 532480, size= 7364608, type=83 8 | -------------------------------------------------------------------------------- /legacy/README.md: -------------------------------------------------------------------------------- 1 | # Legacy roles: 2 | 3 | This folder contains older roles no longer used by ReFactor, but which we want to keep for reference. 4 | 5 | At the moment this contains only Replicape-specific roles that are not run on a Recore image build. -------------------------------------------------------------------------------- /legacy/install_dummy_logger/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: install_framebuffer } -------------------------------------------------------------------------------- /legacy/install_framebuffer/files/powervr.ini: -------------------------------------------------------------------------------- 1 | [default] 2 | WindowSystem=libpvrDRMWSEGL.so 3 | DefaultPixelFormat=RGB565 -------------------------------------------------------------------------------- /legacy/install_framebuffer/files/sgx-libgbm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelligent-agent/Refactor/c54a15a75e3530493f477c5ed15d3f2b2ce76405/legacy/install_framebuffer/files/sgx-libgbm.deb -------------------------------------------------------------------------------- /legacy/install_framebuffer/files/sgx-ti335x-userspace-1.14.3699939_1.1.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelligent-agent/Refactor/c54a15a75e3530493f477c5ed15d3f2b2ce76405/legacy/install_framebuffer/files/sgx-ti335x-userspace-1.14.3699939_1.1.deb -------------------------------------------------------------------------------- /legacy/install_framebuffer/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install Beaglebone sgx drivers 3 | command: 4 | cmd: 'apt-get install -y {{ role_path }}/files/sgx-libgbm.deb {{ role_path }}/files/sgx-ti335x-userspace-1.14.3699939_1.1.deb' 5 | when: platform == 'replicape' 6 | 7 | - name: copy powervr.ini file 8 | copy: 9 | src: '{{ role_path }}/files/powervr.ini' 10 | dest: /etc/powervr.ini 11 | mode: 755 12 | owner: root 13 | when: platform == 'replicape' 14 | 15 | - name: enable sgx-startup 16 | service: 17 | name: sgx-startup 18 | enabled: yes 19 | when: platform == 'replicape' 20 | 21 | - name: create console-setup 22 | file: 23 | path: /etc/default/console-setup 24 | owner: root 25 | group: root 26 | state: touch 27 | when: platform == 'replicape' 28 | 29 | - name: set font in console-setup 30 | lineinfile: 31 | path: /etc/default/console-setup 32 | line: 'FONT=Lat15-Terminus12x6.psf.gz' 33 | state: present 34 | 35 | - name: set colors in terminal for sessions 36 | lineinfile: 37 | path: /etc/profile 38 | line: 'force_color_prompt=yes' 39 | state: present 40 | 41 | - name: set colors in terminal for sessions 42 | lineinfile: 43 | path: /etc/profile 44 | line: 'force_color_prompt=no' 45 | state: absent 46 | -------------------------------------------------------------------------------- /legacy/install_mjpgstreamer/files/mjpg.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Mjpg streamer 3 | Wants=dev-video0.device 4 | After=dev-video0.device 5 | 6 | [Service] 7 | ExecStart=/usr/local/bin/mjpg_streamer -i "/usr/local/lib/mjpg-streamer/input_uvc.so" -o "/usr/local/lib/mjpg-streamer/output_http.so" 8 | 9 | [Install] 10 | WantedBy=basic.target -------------------------------------------------------------------------------- /legacy/install_mjpgstreamer/files/mjpg_recore.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Mjpg streamer 3 | 4 | [Service] 5 | ExecStart=/usr/local/bin/mjpg_streamer -i "/usr/local/lib/mjpg-streamer/input_uvc.so -d /dev/webcam" -o "/usr/local/lib/mjpg-streamer/output_http.so" 6 | 7 | [Install] 8 | WantedBy=dev-webcam.device 9 | -------------------------------------------------------------------------------- /legacy/install_mjpgstreamer/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Replicape - Install Mjpg 3 | include: replicape.yml 4 | when: platform == 'replicape' 5 | 6 | - name: Recore - Install Mjpg 7 | include: recore.yml 8 | when: platform == 'recore' 9 | 10 | - name: Pi - Install Mjpg 11 | include: pi.yml 12 | when: platform == 'pi' 13 | 14 | - name: Pi64 - Install Mjpg 15 | include: pi.yml 16 | when: platform == 'pi64' 17 | -------------------------------------------------------------------------------- /legacy/install_mjpgstreamer/tasks/pi.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dependencies 3 | apt: 4 | pkg: 5 | - cmake 6 | - libjpeg-dev 7 | - ffmpeg 8 | state: latest 9 | 10 | - name: clone git repo 11 | git: 12 | repo: https://github.com/xeno14/mjpg-streamer 13 | dest: /usr/src/mjpg-streamer 14 | 15 | - name: compile mjpg-streamer 16 | shell: make && make install 17 | args: 18 | chdir: /usr/src/mjpg-streamer/mjpg-streamer-experimental/ 19 | creates: /usr/bin/mjpg_streamer 20 | 21 | - name: add video udev rule file 22 | file: 23 | path: /etc/udev/rules.d/50-video.rules 24 | state: touch 25 | 26 | - name: add video udev rules 27 | lineinfile: 28 | path: /etc/udev/rules.d/50-video.rules 29 | line: 'KERNEL=="video0", TAG+="systemd"' 30 | state: present 31 | 32 | - name: add debian sudo permission to restart the service 33 | lineinfile: 34 | path: /etc/sudoers.d/debian 35 | line: '%debian ALL=NOPASSWD: /bin/systemctl restart mjpg.service' 36 | state: present 37 | 38 | - name: deploy service file 39 | copy: 40 | src: '{{ role_path }}/files/mjpg.service' 41 | dest: /etc/systemd/system/mjpg.service 42 | 43 | - name: enable the video streaming service 44 | service: 45 | name: mjpg.service 46 | enabled: yes 47 | -------------------------------------------------------------------------------- /legacy/install_mjpgstreamer/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dependencies 3 | apt: 4 | pkg: 5 | - cmake 6 | - libjpeg-dev 7 | state: latest 8 | 9 | - name: clone git repo 10 | git: 11 | repo: https://github.com/xeno14/mjpg-streamer 12 | dest: /usr/src/mjpg-streamer 13 | depth: 1 14 | 15 | - name: remove raspicam from camera list 16 | lineinfile: 17 | path: /usr/src/mjpg-streamer/mjpg-streamer-experimental/CMakeLists.txt 18 | regex: input_raspicam 19 | line: '#add_subdirectory(plugins/input_raspicam)' 20 | 21 | - name: compile mjpg-streamer 22 | shell: make && make install 23 | args: 24 | chdir: /usr/src/mjpg-streamer/mjpg-streamer-experimental/ 25 | creates: /usr/bin/mjpg_streamer 26 | 27 | - name: add video udev rule file 28 | file: 29 | path: /etc/udev/rules.d/50-video.rules 30 | state: touch 31 | 32 | - name: add video udev rules 33 | lineinfile: 34 | path: /etc/udev/rules.d/50-video.rules 35 | line: 'SUBSYSTEM=="video4linux", ATTR{name}!="cedrus", ATTR{index}=="0", SYMLINK+="webcam", TAG+="systemd"' 36 | state: present 37 | 38 | - name: add debian sudo permission to restart the service 39 | lineinfile: 40 | path: /etc/sudoers.d/debian 41 | line: '%debian ALL=NOPASSWD: /bin/systemctl restart mjpg.service' 42 | state: present 43 | 44 | - name: deploy service file 45 | copy: 46 | src: '{{ role_path }}/files/mjpg_recore.service' 47 | dest: /etc/systemd/system/mjpg.service 48 | 49 | - name: enable the video streaming service 50 | service: 51 | name: mjpg.service 52 | enabled: yes 53 | -------------------------------------------------------------------------------- /legacy/install_mjpgstreamer/tasks/replicape.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dependencies 3 | apt: 4 | pkg: 5 | - cmake 6 | - libjpeg-dev 7 | state: latest 8 | 9 | - name: clone git repo 10 | git: 11 | repo: https://github.com/xeno14/mjpg-streamer 12 | dest: /usr/src/mjpg-streamer 13 | depth: 1 14 | 15 | - name: remove raspicam from camera list 16 | lineinfile: 17 | path: /usr/src/mjpg-streamer/mjpg-streamer-experimental/CMakeLists.txt 18 | regex: input_raspicam 19 | line: '#add_subdirectory(plugins/input_raspicam)' 20 | 21 | - name: compile mjpg-streamer 22 | shell: make && make install 23 | args: 24 | chdir: /usr/src/mjpg-streamer/mjpg-streamer-experimental/ 25 | creates: /usr/bin/mjpg_streamer 26 | 27 | - name: add video udev rule file 28 | file: 29 | path: /etc/udev/rules.d/50-video.rules 30 | state: touch 31 | 32 | - name: add video udev rules 33 | lineinfile: 34 | path: /etc/udev/rules.d/50-video.rules 35 | line: 'KERNEL=="video0", TAG+="systemd"' 36 | state: present 37 | 38 | - name: add debian sudo permission to restart the service 39 | lineinfile: 40 | path: /etc/sudoers.d/debian 41 | line: '%debian ALL=NOPASSWD: /bin/systemctl restart mjpg.service' 42 | state: present 43 | 44 | - name: deploy service file 45 | copy: 46 | src: '{{ role_path }}/files/mjpg.service' 47 | dest: /etc/systemd/system/mjpg.service 48 | 49 | - name: enable the video streaming service 50 | service: 51 | name: mjpg.service 52 | enabled: yes -------------------------------------------------------------------------------- /make-refactor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | set -e 4 | >/root/make-refactor.log 5 | exec > >(tee -ia /root/make-refactor.log) 6 | exec 2> >(tee -ia /root/make-refactor.log >&2) 7 | 8 | if [[ $# -ne 1 ]]; then 9 | echo "You need to specify the platform when you run the script." 10 | echo "It currently needs to be one of [recore, replicape, pi, pi64]" 11 | exit 1 12 | fi 13 | 14 | ansible-playbook SYSTEM_klipper_octoprint-DEFAULT.yml --extra-vars "{platform: $1}" -i hosts 15 | 16 | echo "Now reboot!" 17 | -------------------------------------------------------------------------------- /roles/install_autohotspot/files/autohotspot: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | wifidev=`nmcli dev | grep "wifi " | cut -d' ' -f1` 4 | hotspot_SSID="Recore" 5 | hotspot_PW="12345678" 6 | 7 | create_hotspot() { 8 | echo "Creating hotspot" 9 | nmcli con add type wifi ifname "$wifidev" con-name Hotspot ssid "$hotspot_SSID" 10 | nmcli con modify Hotspot 802-11-wireless.mode ap 11 | nmcli con modify Hotspot 802-11-wireless.band bg 12 | nmcli con modify Hotspot ipv4.method shared 13 | nmcli con modify Hotspot ipv4.addresses 192.168.50.1/24 14 | nmcli con modify Hotspot connection.autoconnect-priority -10 15 | nmcli con modify Hotspot connection.autoconnect yes 16 | nmcli con modify Hotspot wifi-sec.key-mgmt wpa-psk 17 | nmcli con modify Hotspot wifi-sec.psk "$hotspot_PW" 18 | } 19 | 20 | if [ ! -f /etc/NetworkManager/system-connections/Hotspot.nmconnection ] 21 | then 22 | create_hotspot 23 | fi 24 | -------------------------------------------------------------------------------- /roles/install_autohotspot/files/autohotspot.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Automatically generates an internet Hotspot when a valid ssid is not in range 3 | After=NetworkManager.service 4 | Wants=NetworkManager.service 5 | 6 | [Service] 7 | Type=oneshot 8 | RemainAfterExit=yes 9 | ExecStart=/usr/bin/autohotspot 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /roles/install_autohotspot/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Prepare Linux 3 | include: recore.yml 4 | when: platform == 'recore' 5 | -------------------------------------------------------------------------------- /roles/install_autohotspot/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - install packages 3 | apt: 4 | name: 5 | - iptables 6 | - dnsmasq-base 7 | state: present 8 | 9 | - name: Recore - disable unique naming scheme 10 | file: 11 | src: /dev/null 12 | dest: /etc/systemd/network/99-default.link 13 | state: link 14 | 15 | - name: Recore - install autohotspot bin file 16 | copy: 17 | src: autohotspot 18 | dest: /usr/bin 19 | mode: '0755' 20 | 21 | - name: Recore - install autohotspot service file 22 | copy: 23 | src: autohotspot.service 24 | dest: /etc/systemd/system/ 25 | 26 | - name: Recore - enable the autohotspot service 27 | systemd: 28 | name: autohotspot.service 29 | state: stopped 30 | enabled: yes 31 | -------------------------------------------------------------------------------- /roles/install_klipper/files/ar100.config: -------------------------------------------------------------------------------- 1 | # config for the AR100 2 | 3 | CONFIG_LOW_LEVEL_OPTIONS=y 4 | CONFIG_MACH_AR100=y 5 | CONFIG_WANT_GPIO_BITBANGING=y 6 | # CONFIG_WANT_DISPLAYS is not set 7 | # CONFIG_WANT_SENSORS is not set 8 | CONFIG_WANT_SOFTWARE_SPI=y 9 | CONFIG_HAVE_GPIO=y 10 | CONFIG_HAVE_GPIO_SPI=y 11 | CONFIG_HAVE_STEPPER_BOTH_EDGE=y 12 | CONFIG_HAVE_LIMITED_CODE_SIZE=y 13 | CONFIG_INLINE_STEPPER_HACK=y 14 | -------------------------------------------------------------------------------- /roles/install_klipper/files/bl31.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelligent-agent/Refactor/c54a15a75e3530493f477c5ed15d3f2b2ce76405/roles/install_klipper/files/bl31.bin -------------------------------------------------------------------------------- /roles/install_klipper/files/enable-i2c.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/stm32/Kconfig b/src/stm32/Kconfig 2 | index e3961176..66363170 100644 3 | --- a/src/stm32/Kconfig 4 | +++ b/src/stm32/Kconfig 5 | @@ -7,7 +7,7 @@ config STM32_SELECT 6 | default y 7 | select HAVE_GPIO 8 | select HAVE_GPIO_ADC 9 | - select HAVE_GPIO_I2C if !MACH_STM32F031 10 | + select HAVE_GPIO_I2C 11 | select HAVE_GPIO_SPI if !MACH_STM32F031 12 | select HAVE_GPIO_SDIO if MACH_STM32F4 13 | select HAVE_GPIO_HARD_PWM if MACH_STM32F1 || MACH_STM32F4 || MACH_STM32F7 || MACH_STM32G0 || MACH_STM32H7 14 | @@ -206,7 +206,7 @@ config CLOCK_FREQ 15 | 16 | config FLASH_SIZE 17 | hex 18 | - default 0x4000 if MACH_STM32F031 19 | + default 0x8000 if MACH_STM32F031 20 | default 0x8000 if MACH_STM32F042 21 | default 0x20000 if MACH_STM32F070 || MACH_STM32F072 22 | default 0x10000 if MACH_STM32F103 || MACH_STM32L412 # Flash size of stm32f103x8 (64KiB) 23 | diff --git a/src/stm32/stm32f0_i2c.c b/src/stm32/stm32f0_i2c.c 24 | index e9cadccb..0157bd32 100644 25 | --- a/src/stm32/stm32f0_i2c.c 26 | +++ b/src/stm32/stm32f0_i2c.c 27 | @@ -22,6 +22,8 @@ struct i2c_info { 28 | DECL_CONSTANT_STR("BUS_PINS_i2c1_PF1_PF0", "PF1,PF0"); 29 | DECL_ENUMERATION("i2c_bus", "i2c1_PB8_PB9", 2); 30 | DECL_CONSTANT_STR("BUS_PINS_i2c1_PB8_PB9", "PB8,PB9"); 31 | + DECL_ENUMERATION("i2c_bus", "i2c1_PB7_PB8", 3); 32 | + DECL_CONSTANT_STR("BUS_PINS_i2c1_PB7_PB8", "PB7,PB8"); 33 | // Deprecated "i2c1a" style mappings 34 | DECL_ENUMERATION("i2c_bus", "i2c1", 0); 35 | DECL_CONSTANT_STR("BUS_PINS_i2c1", "PB6,PB7"); 36 | @@ -89,6 +91,7 @@ static const struct i2c_info i2c_bus[] = { 37 | { I2C1, GPIO('B', 6), GPIO('B', 7), GPIO_FUNCTION(1) }, 38 | { I2C1, GPIO('F', 1), GPIO('F', 0), GPIO_FUNCTION(1) }, 39 | { I2C1, GPIO('B', 8), GPIO('B', 9), GPIO_FUNCTION(1) }, 40 | + { I2C1, GPIO('B', 7), GPIO('B', 8), GPIO_FUNCTION(1) }, 41 | #elif CONFIG_MACH_STM32F7 42 | { I2C1, GPIO('B', 6), GPIO('B', 7), GPIO_FUNCTION(1) }, 43 | #elif CONFIG_MACH_STM32G0 44 | -------------------------------------------------------------------------------- /roles/install_klipper/files/flash-stm32: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | partprobe 6 | 7 | OUTFILE="/dev/"`lsblk -n -o NAME | grep 'mmcblk[0-2]$'` 8 | 9 | mkdir -p /mnt/config 10 | if ! grep -qs '/mnt/config ' /proc/mounts; then 11 | mount -r ${OUTFILE}boot0p1 /mnt/config/ 12 | fi 13 | 14 | CONFIG=`ls /mnt/config/*.json` 15 | REVISION=`cat "$CONFIG" | jq -r ".Revision" | tr '[:upper:]' '[:lower:]'` 16 | 17 | FLASH_DEVICE=/dev/ttyS2 18 | 19 | STM32_BINARY=/opt/firmware/stm32.bin 20 | if [ "$REVISION" == "a7" ] ; then 21 | STM32_BINARY=/opt/firmware/stm32-32KB.bin 22 | fi 23 | 24 | systemctl stop klipper 25 | 26 | gpioset 1 197=1 27 | gpioset 1 196=0 28 | gpioset 1 196=1 29 | stm32flash -w ${STM32_BINARY} -v -g 0 ${FLASH_DEVICE} 30 | gpioset 1 197=0 31 | gpioget 1 196 32 | 33 | systemctl disable flash-stm32 34 | systemctl start klipper 35 | -------------------------------------------------------------------------------- /roles/install_klipper/files/flash-stm32.service: -------------------------------------------------------------------------------- 1 | #Systemd service file for klipper 2 | [Unit] 3 | Description=flashing the stm32 firmware 4 | 5 | [Install] 6 | WantedBy=basic.target 7 | 8 | [Service] 9 | ExecStart=/usr/local/bin/flash-stm32 10 | -------------------------------------------------------------------------------- /roles/install_klipper/files/generic-recore-a5.cfg: -------------------------------------------------------------------------------- 1 | # This file contains an example configuration for the Recore A5. 2 | # To use this config, the firmware should be compiled for the 3 | # STM32F031 with a "16KiB bootloader" and the ar100. 4 | 5 | # The ar100 firmware can be loaded into memory (SRAM) by a script called 6 | # "flash-ar100.py" in the "scripts" folder. 7 | # The STM32F031 binary can be loaded using the flash-stm32 program. 8 | 9 | # On the Recore boards, there are systemd files that will handle the flashing 10 | # as a part of the boot and flashing process. 11 | 12 | # See docs/Config_Reference.md for a description of parameters. 13 | 14 | [recore_a5] 15 | revision: A5 16 | gain_t0: 1 17 | gain_t1: 1 18 | gain_t2: 1 19 | gain_t3: 1 20 | pullup_t0: 1 21 | pullup_t1: 1 22 | pullup_t2: 1 23 | pullup_t3: 1 24 | 25 | # The STM32F031 mcu 26 | [mcu] 27 | serial: /dev/ttyS2 28 | baud: 250000 29 | restart_method: command 30 | 31 | # The AR100 mcu 32 | [mcu ar100] 33 | serial: /dev/ttyS1 34 | baud: 1500000 35 | 36 | [static_digital_output endstops_5V_enable] 37 | pins: ar100:PG11 38 | 39 | # pin high = 12V, pin low = 5V 40 | [static_digital_output endstop_ES0_5V_12V] 41 | pins: !ar100:PG8 42 | 43 | [static_digital_output temperature_5V_enable] 44 | pins: ar100:PG10 45 | 46 | [static_digital_output user_led_enable] 47 | pins: PA12 48 | 49 | # Load "thermocouple" sensor 50 | [thermocouple] 51 | 52 | # Load custom recore A5 sensors 53 | [recore_adc_temperature] 54 | 55 | # Load custom recore sensors 56 | 57 | # Definition from (20211101): https://download.lulzbot.com/retail_parts/Completed_Parts/100k_Semitech_GT2_Thermistor_KT-EL0059/GT-2-glass-thermistors.pdf 58 | [recore_thermistor RECORE ATC Semitec 104GT-2] 59 | temperature1: 20 60 | resistance1: 126800 61 | temperature2: 150 62 | resistance2: 1360 63 | temperature3: 300 64 | resistance3: 80.65 65 | 66 | # Definition from (20211112): https://atcsemitec.co.uk/wp-content/uploads/2019/01/Semitec-NT-4-Glass-NTC-Thermistor.pdf 67 | [recore_thermistor RECORE ATC Semitec 104NT-4-R025H42G] 68 | temperature1: 25 69 | resistance1: 100000 70 | temperature2: 160 71 | resistance2: 1074 72 | temperature3: 300 73 | resistance3: 82.78 74 | 75 | # Definition from (20211101): https://www.tdk-electronics.tdk.com/inf/50/db/ntc_09/Glass_enc_Sensors__B57560__G560__G1560.pdf 76 | # (B57560G104 is same definition as B57560G1104) 77 | [recore_thermistor RECORE EPCOS 100K B57560G104F] 78 | temperature1: 25 79 | resistance1: 100000 80 | temperature2: 150 81 | resistance2: 1641.9 82 | temperature3: 250 83 | resistance3: 226.15 84 | 85 | # Definition from (20211101): https://www.keenovo.com/NTC-Thermistor-R-T-Table.pdf 86 | [recore_thermistor RECORE Generic 3950] 87 | temperature1: 25 88 | resistance1: 100000 89 | temperature2: 150 90 | resistance2: 1770 91 | temperature3: 250 92 | resistance3: 230 93 | 94 | # Definition from (20211101): https://www.sliceengineering.com/products/thermistor-high-temperature and https://docs.google.com/spreadsheets/d/1904x5JK-Sup-cX5DqHiiZWaFVTK6_PQBFxgi_6yXEJw/edit#gid=0 95 | [recore_thermistor RECORE SliceEngineering 450] 96 | temperature1: 25 97 | resistance1: 500000 98 | temperature2: 200 99 | resistance2: 3734 100 | temperature3: 400 101 | resistance3: 240 102 | 103 | # Definition from (20211101): https://product.tdk.com/system/files/dam/doc/product/sensor/ntc/chip-ntc-thermistor/rt_sheets/ntcg104lh104jt1.csv 104 | [recore_thermistor RECORE TDK NTCG104LH104JT1] 105 | temperature1: 25 106 | resistance1: 100000 107 | temperature2: 50 108 | resistance2: 31230 109 | temperature3: 125 110 | resistance3: 2066 111 | 112 | # Definition from (20211101): https://sensing.honeywell.com/135-104lag-j01-thermistors 113 | [recore_thermistor RECORE Honeywell 100K 135-104LAG-J01] 114 | temperature1: 25 115 | resistance1: 100000 116 | beta: 3974 117 | 118 | # Definition inherent from name. This sensor is deprecated! 119 | [recore_thermistor RECORE NTC 100K beta 3950] 120 | temperature1: 25 121 | resistance1: 100000 122 | beta: 3950 123 | 124 | # Definition from description of Marlin "thermistor 75" 125 | [recore_thermistor RECORE NTC 100K MGB18-104F39050L32] 126 | temperature1: 25 127 | resistance1: 100000 128 | beta: 4100 129 | 130 | [printer] 131 | kinematics: cartesian 132 | max_velocity: 500 133 | max_accel: 3000 134 | max_z_velocity: 25 135 | max_z_accel: 30 136 | 137 | [tmc2209_a5 stepper_x] 138 | uart_pin: ar100:PB1 139 | uart_address: 0 140 | run_current: 0.500 141 | hold_current: 0.500 142 | stealthchop_threshold: 999999 143 | driver_internal_rsense: 1 144 | ref_resistor: 6800 145 | 146 | [tmc2209_a5 stepper_y] 147 | uart_pin: ar100:PB1 148 | uart_address: 1 149 | run_current: 0.500 150 | hold_current: 0.500 151 | stealthchop_threshold: 999999 152 | driver_internal_rsense: 1 153 | ref_resistor: 6800 154 | 155 | [tmc2209_a5 stepper_z] 156 | uart_pin: ar100:PB1 157 | uart_address: 2 158 | run_current: 0.500 159 | hold_current: 0.500 160 | stealthchop_threshold: 999999 161 | driver_internal_rsense: 1 162 | ref_resistor: 6800 163 | 164 | [tmc2209_a5 extruder] 165 | uart_pin: ar100:PB1 166 | uart_address: 3 167 | run_current: 0.500 168 | hold_current: 0.500 169 | stealthchop_threshold: 999999 170 | driver_internal_rsense: 1 171 | ref_resistor: 6800 172 | 173 | [tmc2209_a5 extruder1] 174 | uart_pin: ar100:PD1 175 | uart_address: 0 176 | run_current: 0.500 177 | hold_current: 0.500 178 | stealthchop_threshold: 999999 179 | 180 | [tmc2209_a5 extruder2] 181 | uart_pin: ar100:PD1 182 | uart_address: 1 183 | run_current: 0.500 184 | hold_current: 0.500 185 | stealthchop_threshold: 999999 186 | 187 | [stepper_x] 188 | step_pin: ar100:PL4 189 | dir_pin: ar100:PE8 190 | endstop_pin: !ar100:PH4 191 | rotation_distance: 40 192 | microsteps: 16 193 | position_endstop: 0 194 | position_max: 200 195 | homing_speed: 2.0 196 | 197 | [stepper_y] 198 | step_pin: ar100:PL5 199 | dir_pin: ar100:PE9 200 | endstop_pin: !ar100:PH5 201 | rotation_distance: 40 202 | microsteps: 16 203 | position_endstop: 0 204 | position_max: 200 205 | homing_speed: 2.0 206 | 207 | [stepper_z] 208 | step_pin: ar100:PL6 209 | dir_pin: ar100:PE10 210 | endstop_pin: !ar100:PH6 211 | rotation_distance: 40 212 | microsteps: 16 213 | position_endstop: 0 214 | position_max: 200 215 | homing_speed: 2.0 216 | 217 | [extruder] 218 | step_pin: ar100:PL7 219 | dir_pin: ar100:PE11 220 | heater_pin: PA8 221 | sensor_type: RECORE EPCOS 100K B57560G104F 222 | sensor_pin: PA0 223 | rotation_distance: 33.500 224 | microsteps: 16 225 | nozzle_diameter: 0.400 226 | filament_diameter: 1.75 227 | control: pid 228 | pid_Kp: 22.2 229 | pid_Ki: 1.08 230 | pid_Kd: 114 231 | min_extrude_temp: 30 232 | min_temp: -272 233 | max_temp: 300 234 | pullup_resistor: 4755 235 | adc_voltage: 3.301 236 | offset_voltage: 3.21206 237 | pullup_voltage: 3.27 238 | 239 | [extruder1] 240 | step_pin: ar100:PL8 241 | dir_pin: ar100:PE12 242 | heater_pin: PA9 243 | sensor_pin: PA1 244 | sensor_type: RECORE EPCOS 100K B57560G104F 245 | rotation_distance: 33.500 246 | microsteps: 16 247 | nozzle_diameter: 0.400 248 | filament_diameter: 1.75 249 | control: pid 250 | pid_Kp: 22.2 251 | pid_Ki: 1.08 252 | pid_Kd: 114 253 | min_extrude_temp: 30 254 | min_temp: -272 255 | max_temp: 300 256 | 257 | [extruder2] 258 | step_pin: ar100:PL9 259 | dir_pin: ar100:PE13 260 | heater_pin: PA10 261 | sensor_pin: PA2 262 | sensor_type: RECORE EPCOS 100K B57560G104F 263 | rotation_distance: 33.500 264 | microsteps: 16 265 | nozzle_diameter: 0.400 266 | filament_diameter: 1.75 267 | control: pid 268 | pid_Kp: 22.2 269 | pid_Ki: 1.08 270 | pid_Kd: 114 271 | min_extrude_temp: 30 272 | min_temp: -272 273 | max_temp: 300 274 | 275 | [heater_bed] 276 | heater_pin: PA11 277 | sensor_type: RECORE EPCOS 100K B57560G104F 278 | sensor_pin: PA3 279 | control: watermark 280 | min_temp: -272 281 | max_temp: 300 282 | pullup_resistor: 4755 283 | adc_voltage: 3.301 284 | offset_voltage: 3.21206 285 | pullup_voltage: 3.27 286 | 287 | [fan] 288 | pin: PB0 289 | 290 | [output_pin fan1] 291 | pin: PB1 292 | 293 | [output_pin fan2] 294 | pin: PB5 295 | 296 | [output_pin fan3] 297 | pin: PB4 298 | 299 | # Set up board voltage, current, temperature. 300 | 301 | [temperature_sensor board] 302 | sensor_type: EPCOS 100K B57560G104F 303 | sensor_pin: PA6 304 | max_temp: 110 305 | gcode_id: Board 306 | 307 | [temperature_sensor cold_junction] 308 | sensor_type: EPCOS 100K B57560G104F 309 | sensor_pin: PA7 310 | gcode_id: CJ 311 | 312 | # Vout = Vin * 10K/110K = Vin*11 313 | [adc_temperature v] 314 | temperature1: 0.35 315 | voltage1: 0 316 | temperature2: 36.65 317 | voltage2: 3.3 318 | 319 | [temperature_sensor voltage] 320 | adc_voltage: 3.3 321 | sensor_pin: PA4 322 | sensor_type: v 323 | gcode_id: Voltage 324 | 325 | # 1 A = 20 mV 326 | [adc_temperature current] 327 | temperature1: 0 328 | voltage1: 0 329 | temperature2: 165 330 | voltage2: 3.3 331 | 332 | [temperature_sensor current] 333 | adc_voltage: 3.3 334 | sensor_pin: PA5 335 | sensor_type: current 336 | max_temp: 20 337 | gcode_id: Current 338 | 339 | [gcode_button over_current_alarm] 340 | pin: !ar100:PG0 341 | press_gcode: M112 342 | -------------------------------------------------------------------------------- /roles/install_klipper/files/generic-recore-a6.cfg: -------------------------------------------------------------------------------- 1 | # This file contains an example configuration for the Recore A6. 2 | # To use this config, the firmware should be compiled for the 3 | # STM32F031 with a "16KiB bootloader" and the ar100. 4 | 5 | # The ar100 firmware can be loaded into memory (SRAM) by a script called 6 | # "flash-ar100.py" in the "scripts" folder. 7 | # The STM32F031 binary can be loaded using the flash-stm32 program. 8 | 9 | # On the Recore boards, there are systemd files that will handle the flashing 10 | # as a part of the boot and flashing process. 11 | 12 | # See docs/Config_Reference.md for a description of parameters. 13 | 14 | [recore] 15 | revision: A6 16 | gain_t0: 1 17 | gain_t1: 1 18 | gain_t2: 1 19 | gain_t3: 1 20 | pullup_t0: 1 21 | pullup_t1: 1 22 | pullup_t2: 1 23 | pullup_t3: 1 24 | offset_t0: 0 25 | offset_t1: 0 26 | offset_t2: 0 27 | offset_t3: 0 28 | 29 | [mcu] 30 | serial: /dev/ttyS2 31 | baud: 250000 32 | restart_method: command 33 | 34 | [mcu ar100] 35 | serial: /dev/ttyS1 36 | baud: 1500000 37 | 38 | [static_digital_output endstops_5V_enable] 39 | pins: ar100:PF2 40 | 41 | [static_digital_output endstop_ES0_5V_12V] 42 | pins: !ar100:PF0 43 | 44 | [static_digital_output temperature_5V_enable] 45 | pins: ar100:PF1 46 | 47 | [static_digital_output user_led_enable] 48 | pins: PA12 49 | 50 | [thermocouple] 51 | 52 | [printer] 53 | kinematics: cartesian 54 | max_velocity: 500 55 | max_accel: 3000 56 | max_z_velocity: 25 57 | max_z_accel: 30 58 | 59 | [tmc2209 stepper_x] 60 | uart_pin: ar100:PB1 61 | uart_address: 0 62 | run_current: 0.500 63 | hold_current: 0.500 64 | stealthchop_threshold: 999999 65 | 66 | [tmc2209 stepper_y] 67 | uart_pin: ar100:PB1 68 | uart_address: 1 69 | run_current: 0.500 70 | hold_current: 0.500 71 | stealthchop_threshold: 999999 72 | 73 | [tmc2209 stepper_z] 74 | uart_pin: ar100:PB1 75 | uart_address: 2 76 | run_current: 0.500 77 | hold_current: 0.500 78 | stealthchop_threshold: 999999 79 | 80 | [tmc2209 extruder] 81 | uart_pin: ar100:PB1 82 | uart_address: 3 83 | run_current: 0.500 84 | hold_current: 0.500 85 | stealthchop_threshold: 999999 86 | 87 | [tmc2209 extruder1] 88 | uart_pin: ar100:PD1 89 | uart_address: 0 90 | run_current: 0.500 91 | hold_current: 0.500 92 | stealthchop_threshold: 999999 93 | 94 | [tmc2209 extruder2] 95 | uart_pin: ar100:PD1 96 | uart_address: 1 97 | run_current: 0.500 98 | hold_current: 0.500 99 | stealthchop_threshold: 999999 100 | 101 | # Stepper_z1 and z2 are external steppers on S6, S7. 102 | # These might not be present, but we set 103 | # them up here to have Klipper disable them. 104 | [tmc2209 stepper_z1] 105 | uart_pin: ar100:PD1 106 | uart_address: 2 107 | run_current: 0.500 108 | hold_current: 0.500 109 | stealthchop_threshold: 999999 110 | 111 | [tmc2209 stepper_z2] 112 | uart_pin: ar100:PD1 113 | uart_address: 3 114 | run_current: 0.500 115 | hold_current: 0.500 116 | stealthchop_threshold: 999999 117 | 118 | [stepper_x] 119 | step_pin: ar100:PL4 120 | dir_pin: ar100:PE8 121 | endstop_pin: !ar100:PH4 122 | rotation_distance: 8 123 | microsteps: 16 124 | position_endstop: 0 125 | position_max: 200 126 | 127 | [stepper_y] 128 | step_pin: ar100:PL5 129 | dir_pin: ar100:PE9 130 | endstop_pin: !ar100:PH5 131 | rotation_distance: 8 132 | microsteps: 16 133 | position_endstop: 0 134 | position_max: 200 135 | 136 | [stepper_z] 137 | step_pin: ar100:PL6 138 | dir_pin: ar100:PE10 139 | endstop_pin: !ar100:PH6 140 | rotation_distance: 8 141 | microsteps: 16 142 | position_endstop: 0 143 | position_max: 200 144 | 145 | [stepper_z1] 146 | step_pin: ar100:PL10 147 | dir_pin: ar100:PE14 148 | rotation_distance: 8 149 | microsteps: 16 150 | 151 | [stepper_z2] 152 | step_pin: ar100:PL11 153 | dir_pin: ar100:PE15 154 | rotation_distance: 8 155 | microsteps: 16 156 | 157 | [extruder] 158 | step_pin: ar100:PL7 159 | dir_pin: ar100:PE11 160 | heater_pin: PA8 161 | sensor_pin: PA0 162 | sensor_type: EPCOS 100K B57560G104F 163 | rotation_distance: 33.500 164 | microsteps: 16 165 | nozzle_diameter: 0.400 166 | filament_diameter: 1.75 167 | control: pid 168 | pid_Kp: 22.2 169 | pid_Ki: 1.08 170 | pid_Kd: 114 171 | min_extrude_temp: 30 172 | min_temp: -272 173 | max_temp: 300 174 | 175 | [extruder1] 176 | step_pin: ar100:PL8 177 | dir_pin: ar100:PE12 178 | heater_pin: PA9 179 | sensor_pin: PA1 180 | sensor_type: EPCOS 100K B57560G104F 181 | rotation_distance: 33.500 182 | microsteps: 16 183 | nozzle_diameter: 0.400 184 | filament_diameter: 1.75 185 | control: pid 186 | pid_Kp: 22.2 187 | pid_Ki: 1.08 188 | pid_Kd: 114 189 | min_extrude_temp: 30 190 | min_temp: -272 191 | max_temp: 300 192 | 193 | [extruder2] 194 | step_pin: ar100:PL9 195 | dir_pin: ar100:PE13 196 | heater_pin: PA10 197 | sensor_pin: PA2 198 | sensor_type: EPCOS 100K B57560G104F 199 | rotation_distance: 33.500 200 | microsteps: 16 201 | nozzle_diameter: 0.400 202 | filament_diameter: 1.75 203 | control: pid 204 | pid_Kp: 22.2 205 | pid_Ki: 1.08 206 | pid_Kd: 114 207 | min_extrude_temp: 30 208 | min_temp: -272 209 | max_temp: 300 210 | 211 | [heater_bed] 212 | heater_pin: PA11 213 | sensor_pin: PA3 214 | sensor_type: EPCOS 100K B57560G104F 215 | control: watermark 216 | min_temp: -272 217 | max_temp: 300 218 | 219 | [fan] 220 | pin: PB0 221 | 222 | [output_pin fan1] 223 | pin: PB1 224 | 225 | [output_pin fan2] 226 | pin: PB5 227 | 228 | [temperature_fan board] 229 | pin: PB4 230 | min_temp: 0 231 | max_temp: 100 232 | sensor_type: EPCOS 100K B57560G104F 233 | sensor_pin: PA6 234 | control: watermark 235 | gcode_id: Board 236 | target_temp: 50 237 | 238 | [temperature_sensor cold_junction] 239 | sensor_type: EPCOS 100K B57560G104F 240 | sensor_pin: PA7 241 | gcode_id: CJ 242 | 243 | [adc_temperature v] 244 | temperature1: 0.35 245 | voltage1: 0 246 | temperature2: 36.65 247 | voltage2: 3.3 248 | 249 | [temperature_sensor voltage] 250 | adc_voltage: 3.3 251 | sensor_pin: PA4 252 | sensor_type: v 253 | gcode_id: Voltage 254 | 255 | [adc_temperature current] 256 | temperature1: 0 257 | voltage1: 0 258 | temperature2: 165 259 | voltage2: 3.3 260 | 261 | [temperature_sensor current] 262 | adc_voltage: 3.3 263 | sensor_pin: PA5 264 | sensor_type: current 265 | max_temp: 20 266 | gcode_id: Current 267 | 268 | [gcode_button over_current_alarm] 269 | pin: !ar100:PF6 270 | press_gcode: M112 271 | -------------------------------------------------------------------------------- /roles/install_klipper/files/generic-recore-a7.cfg: -------------------------------------------------------------------------------- 1 | # This file contains an example configuration for the Recore A7. 2 | # To use this config, the firmware should be compiled for the 3 | # STM32F031 with a "32KiB bootloader" and the ar100. 4 | 5 | # The ar100 firmware can be loaded into memory (SRAM) by a script called 6 | # "flash-ar100.py" in the "scripts" folder. 7 | # The STM32F031 binary can be loaded using the flash-stm32 program. 8 | 9 | # On the Recore boards, there are systemd files that will handle the flashing 10 | # as a part of the boot and flashing process. 11 | 12 | # See docs/Config_Reference.md for a description of parameters. 13 | 14 | [recore] 15 | revision: A7 16 | gain_t0: 1 17 | gain_t1: 1 18 | gain_t2: 1 19 | gain_t3: 1 20 | pullup_t0: 1 21 | pullup_t1: 1 22 | pullup_t2: 1 23 | pullup_t3: 1 24 | offset_t0: 0 25 | offset_t1: 0 26 | offset_t2: 0 27 | offset_t3: 0 28 | 29 | [mcu] 30 | serial: /dev/ttyS2 31 | baud: 250000 32 | restart_method: command 33 | 34 | [mcu ar100] 35 | serial: /dev/ttyS1 36 | baud: 1500000 37 | 38 | [static_digital_output endstops_5V_enable] 39 | pins: ar100:PF2 40 | 41 | [static_digital_output endstop_ES0_5V_12V] 42 | pins: !ar100:PF0 43 | 44 | [static_digital_output temperature_5V_enable] 45 | pins: ar100:PF1 46 | 47 | [static_digital_output user_led_enable] 48 | pins: PA12 49 | 50 | [thermocouple] 51 | 52 | [printer] 53 | kinematics: cartesian 54 | max_velocity: 500 55 | max_accel: 3000 56 | max_z_velocity: 25 57 | max_z_accel: 30 58 | 59 | [tmc2209 stepper_x] 60 | uart_pin: ar100:PE16 61 | uart_address: 0 62 | run_current: 0.500 63 | hold_current: 0.500 64 | stealthchop_threshold: 999999 65 | 66 | [tmc2209 stepper_y] 67 | uart_pin: ar100:PE16 68 | uart_address: 1 69 | run_current: 0.500 70 | hold_current: 0.500 71 | stealthchop_threshold: 999999 72 | 73 | [tmc2209 stepper_z] 74 | uart_pin: ar100:PE16 75 | uart_address: 2 76 | run_current: 0.500 77 | hold_current: 0.500 78 | stealthchop_threshold: 999999 79 | 80 | [tmc2209 extruder] 81 | uart_pin: ar100:PE16 82 | uart_address: 3 83 | run_current: 0.500 84 | hold_current: 0.500 85 | stealthchop_threshold: 999999 86 | 87 | [tmc2209 extruder1] 88 | uart_pin: ar100:PD24 89 | uart_address: 0 90 | run_current: 0.500 91 | hold_current: 0.500 92 | stealthchop_threshold: 999999 93 | 94 | [tmc2209 extruder2] 95 | uart_pin: ar100:PD24 96 | uart_address: 1 97 | run_current: 0.500 98 | hold_current: 0.500 99 | stealthchop_threshold: 999999 100 | 101 | # Stepper_z1 and z2 are external steppers on S6, S7. 102 | # These might not be present, but we set 103 | # them up here to have Klipper disable them. 104 | [tmc2209 stepper_z1] 105 | uart_pin: ar100:PD2 106 | uart_address: 3 107 | run_current: 0.500 108 | hold_current: 0.500 109 | stealthchop_threshold: 999999 110 | 111 | [tmc2209 stepper_z2] 112 | uart_pin: ar100:PD3 113 | uart_address: 3 114 | run_current: 0.500 115 | hold_current: 0.500 116 | stealthchop_threshold: 999999 117 | 118 | 119 | [stepper_x] 120 | step_pin: ar100:PL4 121 | dir_pin: ar100:PE8 122 | endstop_pin: !ar100:PH4 123 | rotation_distance: 8 124 | microsteps: 16 125 | position_endstop: 0 126 | position_max: 200 127 | 128 | [stepper_y] 129 | step_pin: ar100:PL5 130 | dir_pin: ar100:PE9 131 | endstop_pin: !ar100:PH5 132 | rotation_distance: 8 133 | microsteps: 16 134 | position_endstop: 0 135 | position_max: 200 136 | 137 | [stepper_z] 138 | step_pin: ar100:PL6 139 | dir_pin: ar100:PE10 140 | endstop_pin: !ar100:PH6 141 | rotation_distance: 8 142 | microsteps: 16 143 | position_endstop: 0 144 | position_max: 200 145 | 146 | [stepper_z1] 147 | step_pin: ar100:PL10 148 | dir_pin: ar100:PE14 149 | rotation_distance: 8 150 | microsteps: 16 151 | 152 | [stepper_z2] 153 | step_pin: ar100:PL11 154 | dir_pin: ar100:PE15 155 | rotation_distance: 8 156 | microsteps: 16 157 | 158 | [extruder] 159 | step_pin: ar100:PL7 160 | dir_pin: ar100:PE11 161 | heater_pin: PA8 162 | sensor_type: EPCOS 100K B57560G104F 163 | sensor_pin: PA0 164 | rotation_distance: 33.500 165 | microsteps: 16 166 | nozzle_diameter: 0.400 167 | filament_diameter: 1.75 168 | control: pid 169 | pid_Kp: 22.2 170 | pid_Ki: 1.08 171 | pid_Kd: 114 172 | min_extrude_temp: 30 173 | min_temp: -272 174 | max_temp: 300 175 | 176 | [extruder1] 177 | step_pin: ar100:PL8 178 | dir_pin: ar100:PE12 179 | heater_pin: PA9 180 | sensor_pin: PA1 181 | sensor_type: EPCOS 100K B57560G104F 182 | rotation_distance: 33.500 183 | microsteps: 16 184 | nozzle_diameter: 0.400 185 | filament_diameter: 1.75 186 | control: pid 187 | pid_Kp: 22.2 188 | pid_Ki: 1.08 189 | pid_Kd: 114 190 | min_extrude_temp: 30 191 | min_temp: -272 192 | max_temp: 300 193 | 194 | [extruder2] 195 | step_pin: ar100:PL9 196 | dir_pin: ar100:PE13 197 | heater_pin: PA10 198 | sensor_pin: PA2 199 | sensor_type: EPCOS 100K B57560G104F 200 | rotation_distance: 33.500 201 | microsteps: 16 202 | nozzle_diameter: 0.400 203 | filament_diameter: 1.75 204 | control: pid 205 | pid_Kp: 22.2 206 | pid_Ki: 1.08 207 | pid_Kd: 114 208 | min_extrude_temp: 30 209 | min_temp: -272 210 | max_temp: 300 211 | 212 | [heater_bed] 213 | heater_pin: PA11 214 | sensor_pin: PA3 215 | sensor_type: EPCOS 100K B57560G104F 216 | control: watermark 217 | min_temp: -272 218 | max_temp: 300 219 | 220 | [fan] 221 | pin: PF0 222 | 223 | [output_pin fan1] 224 | pin: PB1 225 | 226 | [output_pin fan2] 227 | pin: PB5 228 | 229 | [temperature_fan board] 230 | pin: PB4 231 | min_temp: 0 232 | max_temp: 100 233 | sensor_type: EPCOS 100K B57560G104F 234 | sensor_pin: PA6 235 | control: watermark 236 | gcode_id: Board 237 | target_temp: 50 238 | 239 | [temperature_sensor cold_junction] 240 | sensor_type: EPCOS 100K B57560G104F 241 | sensor_pin: PA7 242 | gcode_id: CJ 243 | 244 | [adc_temperature v] 245 | temperature1: 0.35 246 | voltage1: 0 247 | temperature2: 36.65 248 | voltage2: 3.3 249 | 250 | [temperature_sensor voltage] 251 | adc_voltage: 3.3 252 | sensor_pin: PA4 253 | sensor_type: v 254 | gcode_id: Voltage 255 | 256 | [adc_temperature current] 257 | temperature1: 0 258 | voltage1: 0 259 | temperature2: 165 260 | voltage2: 3.3 261 | 262 | [temperature_sensor current] 263 | adc_voltage: 3.3 264 | sensor_pin: PA5 265 | sensor_type: current 266 | max_temp: 20 267 | gcode_id: Current 268 | 269 | [gcode_button over_current_alarm] 270 | pin: !ar100:PF6 271 | press_gcode: M112 272 | 273 | [adc_temperature fan_current] 274 | temperature1: 0 275 | voltage1: 0 276 | temperature2: 33 277 | voltage2: 3.3 278 | 279 | [temperature_sensor fan_current] 280 | adc_voltage: 3.3 281 | sensor_pin: PB0 282 | sensor_type: fan_current 283 | max_temp: 2.0 284 | gcode_id: FanCurrent 285 | -------------------------------------------------------------------------------- /roles/install_klipper/files/install-recore.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script installs Klipper on a Debian 10 machine with Octoprint 3 | 4 | PYTHONDIR="${HOME}/klippy-env" 5 | SYSTEMDDIR="/etc/systemd/system" 6 | KLIPPER_USER=$USER 7 | KLIPPER_GROUP=$KLIPPER_USER 8 | 9 | # Step 1: Install system packages 10 | install_packages() 11 | { 12 | # Packages for python cffi 13 | PKGLIST="python-virtualenv virtualenv python-dev libffi-dev build-essential" 14 | # kconfig requirements 15 | PKGLIST="${PKGLIST} libncurses-dev" 16 | # hub-ctrl 17 | PKGLIST="${PKGLIST} libusb-dev" 18 | # AVR chip installation and building 19 | # ARM chip installation and building 20 | PKGLIST="${PKGLIST} stm32flash libnewlib-arm-none-eabi" 21 | PKGLIST="${PKGLIST} gcc-arm-none-eabi binutils-arm-none-eabi" 22 | 23 | # Update system package info 24 | report_status "Running apt-get update..." 25 | sudo apt-get update 26 | 27 | # Install desired packages 28 | report_status "Installing packages..." 29 | sudo apt-get install --yes ${PKGLIST} 30 | } 31 | 32 | # Step 2: Create python virtual environment 33 | create_virtualenv() 34 | { 35 | report_status "Updating python virtual environment..." 36 | 37 | # Create virtualenv if it doesn't already exist 38 | [ ! -d ${PYTHONDIR} ] && virtualenv -p /usr/bin/python2 ${PYTHONDIR} 39 | 40 | # Install/update dependencies 41 | ${PYTHONDIR}/bin/pip install -r ${SRCDIR}/scripts/klippy-requirements.txt 42 | } 43 | 44 | # Step 3: Install startup script 45 | install_script() 46 | { 47 | # Create systemd service file 48 | KLIPPER_LOG=/tmp/klippy.log 49 | report_status "Installing system start script..." 50 | sudo /bin/sh -c "cat > $SYSTEMDDIR/klipper.service" << EOF 51 | #Systemd service file for klipper 52 | [Unit] 53 | Description=Starts klipper on startup 54 | After=network.target 55 | 56 | [Install] 57 | WantedBy=multi-user.target 58 | 59 | [Service] 60 | Type=simple 61 | User=debian 62 | RemainAfterExit=yes 63 | PermissionsStartOnly=true 64 | ExecStartPre=/usr/bin/gpioset 1 196=0 65 | ExecStartPre=/usr/bin/gpioget 1 196 66 | ExecStartPre=${SRCDIR}/scripts/flash-ar100.py /opt/firmware/ar100.bin 67 | ExecStart=${PYTHONDIR}/bin/python ${SRCDIR}/klippy/klippy.py ${HOME}/printer_config/printer.cfg -l ${KLIPPER_LOG} 68 | ExecStopPost=${SRCDIR}/scripts/flash-ar100.py --bl31 --halt /opt/firmware/bl31.bin 69 | EOF 70 | # Use systemctl to enable the klipper systemd service script 71 | sudo systemctl enable klipper.service 72 | } 73 | 74 | # Step 4: Start host software 75 | start_software() 76 | { 77 | report_status "Launching Klipper host software..." 78 | sudo systemctl start klipper 79 | } 80 | 81 | # Helper functions 82 | report_status() 83 | { 84 | echo -e "\n\n###### $1" 85 | } 86 | 87 | verify_ready() 88 | { 89 | if [ "$EUID" -eq 0 ]; then 90 | echo "This script must not run as root" 91 | exit -1 92 | fi 93 | } 94 | 95 | # Force script to exit if an error occurs 96 | set -e 97 | 98 | # Find SRCDIR from the pathname of this script 99 | SRCDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )" 100 | 101 | # Run installation steps defined above 102 | verify_ready 103 | install_packages 104 | create_virtualenv 105 | install_script 106 | start_software 107 | -------------------------------------------------------------------------------- /roles/install_klipper/files/klipper-pru.path: -------------------------------------------------------------------------------- 1 | #Systemd path file for klipper-pru 2 | [Unit] 3 | Description=klipper pru PATH 4 | PartOf=klipper_pru.service 5 | 6 | [Path] 7 | PathExists=/sys/class/remoteproc/remoteproc2/state 8 | PathExists=/sys/class/remoteproc/remoteproc1/state 9 | -------------------------------------------------------------------------------- /roles/install_klipper/files/klipper-recore.service: -------------------------------------------------------------------------------- 1 | #Systemd service file for klipper 2 | [Unit] 3 | Description=Starts klipper on startup 4 | After=network.target 5 | 6 | [Install] 7 | WantedBy=multi-user.target 8 | 9 | [Service] 10 | Environment=KLIPPER_CONFIG=/home/debian/printer_data/config/printer.cfg 11 | Environment=KLIPPER_LOG=/var/log/klipper_logs/klippy.log 12 | Environment=KLIPPER_SOCKET=/tmp/klippy_uds 13 | Type=simple 14 | User=debian 15 | RemainAfterExit=yes 16 | PermissionsStartOnly=true 17 | ExecStartPre=/usr/bin/gpioset 1 196=0 18 | ExecStartPre=/usr/bin/gpioget 1 196 19 | ExecStartPre=/home/debian/klipper/scripts/flash-ar100.py /opt/firmware/ar100.bin 20 | ExecStart=/home/debian/klippy-env/bin/python /home/debian/klipper/klippy/klippy.py ${KLIPPER_CONFIG} -l ${KLIPPER_LOG} -a ${KLIPPER_SOCKET} 21 | ExecStopPost=/home/debian/klipper/scripts/flash-ar100.py --bl31 --halt /opt/firmware/bl31.bin 22 | -------------------------------------------------------------------------------- /roles/install_klipper/files/klipper.service: -------------------------------------------------------------------------------- 1 | #Systemd service file for klipper 2 | [Unit] 3 | Description=Starts klipper on startup 4 | After=klipper_pru.service 5 | 6 | [Install] 7 | WantedBy=multi-user.target 8 | 9 | [Service] 10 | Type=simple 11 | User=debian 12 | RemainAfterExit=yes 13 | ExecStart=/home/debian/klippy-env/bin/python /home/debian/klipper/klippy/klippy.py /home/debian/printer.cfg -l /tmp/klippy.log -a /tmp/klippy_uds 14 | Restart=always 15 | RestartSec=10 16 | -------------------------------------------------------------------------------- /roles/install_klipper/files/klipper_host_mcu.service: -------------------------------------------------------------------------------- 1 | #Systemd service file for klipper_host_mcu 2 | [Unit] 3 | Description=klipper linux host 4 | Documentation=man:systemd.special(7) 5 | PartOf=klipper.service 6 | After=klipper_pru.service 7 | Requires=klipper_pru.service 8 | Before=klippy.service 9 | 10 | [Service] 11 | Type=simple 12 | RemainAfterExit=yes 13 | ExecStart=/usr/local/bin/klipper_mcu -w 14 | Restart=always 15 | RestartSec=15 16 | 17 | [Install] 18 | WantedBy=klipper.service 19 | -------------------------------------------------------------------------------- /roles/install_klipper/files/klipper_pru: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # System startup script to start the PRU firmware 3 | 4 | ### BEGIN INIT INFO 5 | # Provides: klipper_pru 6 | # Required-Start: $local_fs 7 | # Required-Stop: 8 | # Default-Start: 3 4 5 9 | # Default-Stop: 0 1 2 6 10 | # Short-Description: Klipper_PRU daemon 11 | # Description: Starts the PRU for Klipper. 12 | ### END INIT INFO 13 | 14 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 15 | DESC="klipper_pru startup" 16 | NAME="klipper_pru" 17 | KLIPPER_HOST_MCU=/usr/local/bin/klipper_mcu 18 | KLIPPER_HOST_ARGS="-w -r" 19 | PIDFILE=/var/run/klipper_mcu.pid 20 | RPROC0=/sys/class/remoteproc/remoteproc1 21 | RPROC1=/sys/class/remoteproc/remoteproc2 22 | 23 | 24 | . /lib/lsb/init-functions 25 | 26 | pru_stop() 27 | { 28 | # Shutdown existing Klipper instance (if applicable). The goal is to 29 | # put the GPIO pins in a safe state. 30 | if [ -c /dev/rpmsg_pru30 ]; then 31 | log_daemon_msg "Attempting to shutdown PRU..." 32 | set -e 33 | ( echo "FORCE_SHUTDOWN" > /dev/rpmsg_pru30 ) 2> /dev/null || ( log_action_msg "Firmware busy! Please shutdown Klipper and then retry." && exit 1 ) 34 | sleep 1 35 | ( echo "FORCE_SHUTDOWN" > /dev/rpmsg_pru30 ) 2> /dev/null || ( log_action_msg "Firmware busy! Please shutdown Klipper and then retry." && exit 1 ) 36 | sleep 1 37 | set +e 38 | fi 39 | 40 | log_daemon_msg "Stopping pru" 41 | echo 'stop' > $RPROC0/state 42 | echo 'stop' > $RPROC1/state 43 | } 44 | 45 | pru_start() 46 | { 47 | if [ -c /dev/rpmsg_pru30 ]; then 48 | pru_stop 49 | else 50 | echo 'stop' > $RPROC0/state 51 | echo 'stop' > $RPROC1/state 52 | fi 53 | sleep 1 54 | 55 | log_daemon_msg "Starting pru" 56 | echo 'start' > $RPROC0/state 57 | echo 'start' > $RPROC1/state 58 | 59 | } 60 | 61 | mcu_host_stop() 62 | { 63 | # Shutdown existing Klipper instance (if applicable). The goal is to 64 | # put the GPIO pins in a safe state. 65 | if [ -c /tmp/klipper_host_mcu ]; then 66 | log_daemon_msg "Attempting to shutdown host mcu..." 67 | set -e 68 | ( echo "FORCE_SHUTDOWN" > /tmp/klipper_host_mcu ) 2> /dev/null || ( log_action_msg "Firmware busy! Please shutdown Klipper and then retry." && exit 1 ) 69 | sleep 1 70 | ( echo "FORCE_SHUTDOWN" > /tmp/klipper_host_mcu ) 2> /dev/null || ( log_action_msg "Firmware busy! Please shutdown Klipper and then retry." && exit 1 ) 71 | sleep 1 72 | set +e 73 | fi 74 | 75 | log_daemon_msg "Stopping klipper host mcu" $NAME 76 | killproc -p $PIDFILE $KLIPPER_HOST_MCU 77 | } 78 | 79 | mcu_host_start() 80 | { 81 | [ -x $KLIPPER_HOST_MCU ] || return 82 | 83 | if [ -c /tmp/klipper_host_mcu ]; then 84 | mcu_host_stop 85 | fi 86 | 87 | log_daemon_msg "Starting klipper MCU" $NAME 88 | start-stop-daemon --start --quiet --exec $KLIPPER_HOST_MCU \ 89 | --background --pidfile $PIDFILE --make-pidfile \ 90 | -- $KLIPPER_HOST_ARGS 91 | log_end_msg $? 92 | } 93 | 94 | case "$1" in 95 | start) 96 | pru_start 97 | mcu_host_start 98 | ;; 99 | stop) 100 | pru_stop 101 | mcu_host_stop 102 | ;; 103 | restart) 104 | $0 stop 105 | $0 start 106 | ;; 107 | reload|force-reload) 108 | log_daemon_msg "Reloading configuration not supported" $NAME 109 | log_end_msg 1 110 | ;; 111 | status) 112 | status_of_proc -p $PIDFILE $KLIPPER_HOST_MCU $NAME && exit 0 || exit $? 113 | ;; 114 | *) log_action_msg "Usage: /etc/init.d/klipper {start|stop|status|restart|reload|force-reload}" 115 | exit 2 116 | ;; 117 | esac 118 | exit 0 119 | -------------------------------------------------------------------------------- /roles/install_klipper/files/klipper_pru.service: -------------------------------------------------------------------------------- 1 | # Automatically generated by systemd-sysv-generator 2 | 3 | [Unit] 4 | Documentation=man:systemd-sysv-generator(8) 5 | SourcePath=/etc/systemd/system/klipper_pru 6 | Description=LSB: Klipper_PRU daemon 7 | After=remoteproc1.path 8 | 9 | [Install] 10 | WantedBy=multi-user.target 11 | 12 | [Service] 13 | Type=forking 14 | Restart=no 15 | TimeoutSec=5min 16 | IgnoreSIGPIPE=no 17 | KillMode=process 18 | GuessMainPID=no 19 | RemainAfterExit=yes 20 | SuccessExitStatus=5 6 21 | ExecStart=/etc/systemd/system/klipper_pru start 22 | ExecStop=/etc/systemd/system/klipper_pru stop 23 | ExecReload=/etc/systemd/system/klipper_pru reload 24 | Group=gpio 25 | User=root -------------------------------------------------------------------------------- /roles/install_klipper/files/klippy.service: -------------------------------------------------------------------------------- 1 | #Systemd service file for klippy 2 | [Unit] 3 | Description=Klippy thread application 4 | PartOf=klipper.service 5 | After=klipper_host_mcu.service klipper_pru.service 6 | Requires=klipper_host_mcu.service klipper_pru.service 7 | Before=octoprint.service 8 | 9 | [Service] 10 | Type=simple 11 | User=debian 12 | RemainAfterExit=yes 13 | ExecStart=/home/debian/klippy-env/bin/python /home/debian/klipper/klippy/klippy.py /home/debian/printer.cfg -l /tmp/klippy.log 14 | RestartSec=20 15 | Restart=always 16 | 17 | [Install] 18 | WantedBy=klipper.service 19 | -------------------------------------------------------------------------------- /roles/install_klipper/files/octoprint_config.yaml: -------------------------------------------------------------------------------- 1 | accessControl: 2 | salt: pNbVSgrkZchidVXftJvg9JzDXC9aPT97 3 | api: 4 | key: A16E678B4725409883770F6DD4DAA436 5 | appearance: 6 | name: Refactor 7 | feature: {} 8 | folder: 9 | uploads: /home/debian/.octoprint/uploads 10 | gcodeViewer: {} 11 | plugins: 12 | announcements: 13 | _config_version: 1 14 | channels: 15 | _blog: 16 | read_until: 1574955000 17 | _important: 18 | read_until: 1521111600 19 | _octopi: 20 | read_until: 1573722900 21 | _plugins: 22 | read_until: 1574985600 23 | _releases: 24 | read_until: 1575299700 25 | discovery: 26 | upnpUuid: 05489750-db4d-4c17-8aa6-e9783bc31ef3 27 | errortracking: 28 | enabled: true 29 | unique_id: 89d862ca-31ef-43bf-a46a-a73248343ca8 30 | klipper: 31 | _config_version: 2 32 | configuration: 33 | path: /home/debian/klipper_config/printer.cfg 34 | softwareupdate: 35 | _config_version: 7 36 | check_providers: 37 | filemanager: filemanager 38 | klipper: klipper 39 | checks: 40 | Kamikaze: 41 | checkout_folder: /usr/src/Umikaze 42 | restart: echo "Umikaze dummy restart" 43 | type: git_commit 44 | update_script: /usr/src/Kamikaze2/update-kamikaze.sh 45 | octoprint: 46 | branch: null 47 | checkout_folder: /home/octo/OctoPrint 48 | prerelease: true 49 | prerelease_channel: rc/devel 50 | tracking: 51 | enabled: true 52 | unique_id: fbffc87a-33d1-40a0-9809-d7baad84ee8f 53 | printerParameters: {} 54 | printerProfiles: 55 | default: _default 56 | serial: 57 | additionalPorts: 58 | - /tmp/printer 59 | autoconnect: true 60 | baudrate: 115200 61 | port: /tmp/printer 62 | timeout: {} 63 | server: 64 | commands: 65 | serverRestartCommand: sudo systemctl restart octoprint.service 66 | systemRestartCommand: sudo reboot 67 | systemShutdownCommand: sudo shutdown -h now 68 | firstRun: true 69 | onlineCheck: 70 | enabled: true 71 | pluginBlacklist: 72 | enabled: true 73 | secretKey: t5QPDeUzU3yVmNnzLQfXDgC666wUnk7g 74 | seenWizards: 75 | corewizard: 3 76 | tracking: null 77 | system: 78 | actions: 79 | - action: restart klipper 80 | command: sudo systemctl stop klipper && sudo systemctl restart klipper_pru 81 | && sudo systemctl start klipper 82 | confirm: Are you sure? This will interrupt any ongoing printing. 83 | name: Restart Klipper 84 | - action: restart mjpg 85 | command: sudo systemctl restart mjpg 86 | name: Restart Mjpg 87 | temperature: 88 | profiles: 89 | - bed: 100 90 | chamber: null 91 | extruder: 210 92 | name: ABS 93 | - bed: 60 94 | chamber: null 95 | extruder: 180 96 | name: PLA 97 | terminalFilters: 98 | - name: Suppress temperature messages 99 | regex: '(Send: (N\d+\s+)?M105)|(Recv:\s+(ok\s+)?.*\s(T\d*):\d+)' 100 | - name: Suppress SD status messages 101 | regex: '(Send: (N\d+\s+)?M27)|(Recv: SD printing byte)|(Recv: Not SD printing)' 102 | - name: Suppress wait responses 103 | regex: 'Recv: (wait)|(ok)$' 104 | webcam: 105 | ffmpeg: /usr/bin/ffmpeg 106 | snapshot: http://localhost:8080/?action=snapshot 107 | stream: http://kamikaze.local:8080/?action=stream 108 | -------------------------------------------------------------------------------- /roles/install_klipper/files/octoprint_replicape.service: -------------------------------------------------------------------------------- 1 | #Systemd service file for OctoPrint 2 | [Unit] 3 | Description=OctoPrint 4 | PartOf=klipper.service 5 | After=klippy.service 6 | Requires= klipper_host_mcu.service klipper_pru.service klippy.service 7 | 8 | [Service] 9 | Type=simple 10 | ExecStart=/home/debian/OctoPrint/venv/bin/octoprint serve 11 | Restart=always 12 | RestartSec=60 13 | User=debian 14 | 15 | [Install] 16 | WantedBy=klipper.service 17 | -------------------------------------------------------------------------------- /roles/install_klipper/files/pru_config: -------------------------------------------------------------------------------- 1 | # 2 | # Automatically generated file; DO NOT EDIT. 3 | # Klipper Firmware Configuration 4 | # 5 | CONFIG_LOW_LEVEL_OPTIONS=y 6 | # CONFIG_MACH_AVR is not set 7 | # CONFIG_MACH_ATSAM is not set 8 | # CONFIG_MACH_ATSAMD is not set 9 | # CONFIG_MACH_LPC176X is not set 10 | # CONFIG_MACH_STM32 is not set 11 | CONFIG_MACH_PRU=y 12 | # CONFIG_MACH_LINUX is not set 13 | # CONFIG_MACH_SIMU is not set 14 | CONFIG_STEP_DELAY=2 15 | CONFIG_BOARD_DIRECTORY="pru" 16 | CONFIG_CLOCK_FREQ=200000000 17 | CONFIG_PRU_SELECT=y 18 | # CONFIG_CUSTOM_STEP_DELAY is not set 19 | CONFIG_INITIAL_PINS="" 20 | CONFIG_HAVE_GPIO=y 21 | # CONFIG_HAVE_GPIO_ADC is not set 22 | # CONFIG_HAVE_GPIO_SPI is not set 23 | # CONFIG_HAVE_GPIO_I2C is not set 24 | # CONFIG_HAVE_GPIO_HARD_PWM is not set 25 | # CONFIG_HAVE_GPIO_BITBANGING is not set 26 | # CONFIG_HAVE_CHIPID is not set 27 | CONFIG_INLINE_STEPPER_HACK=y 28 | -------------------------------------------------------------------------------- /roles/install_klipper/files/recore.py: -------------------------------------------------------------------------------- 1 | # Config for Recore, 2 | # 3 | # Copyright (C) 2017-2019 Kevin O'Connor 4 | # Copyright (C) 2019-2023 Elias Bakken 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | import logging, os 8 | import pins, mcu 9 | 10 | pins = { 11 | "A7": { 12 | 'enable_pin': 'ar100:PF5', 13 | 'oc_reset_pin': 'ar100:PF4', 14 | 'gain_enable_t0': 'ar100:PD4', 15 | 'gain_enable_t1': 'ar100:PH11', 16 | 'gain_enable_t2': 'ar100:PE17', 17 | 'gain_enable_t3': 'ar100:PB2', 18 | 'pullup_t0': 'ar100:PG10', 19 | 'pullup_t1': 'ar100:PG11', 20 | 'pullup_t2': 'ar100:PG12', 21 | 'pullup_t3': 'ar100:PG13', 22 | 'offset_t0': 'ar100:PG0', 23 | 'offset_t1': 'ar100:PG1', 24 | 'offset_t2': 'ar100:PG2', 25 | 'offset_t3': 'ar100:PG3' 26 | } 27 | } 28 | 29 | 30 | class recore: 31 | def __init__(self, config): 32 | printer = config.get_printer() 33 | ppins = printer.lookup_object('pins') 34 | ppins.register_chip('recore', self) 35 | revisions = {'A6':'A6', 'A7':'A7'} 36 | self.revision = config.getchoice('revision', revisions) 37 | 38 | pins["A6"] = pins["A7"] 39 | # Setup enable pin 40 | enable_pin = config.get('enable_pin', 41 | pins[self.revision]['enable_pin']) 42 | mcu_power_enable = ppins.setup_pin('digital_out', enable_pin) 43 | mcu_power_enable.setup_start_value(start_value=0., 44 | shutdown_value=1., 45 | is_static=False) 46 | mcu_power_enable.setup_max_duration(0.) 47 | 48 | # Reset over current alarm 49 | oc_reset_pin = config.get('oc_reset_pin', 50 | pins[self.revision]['oc_reset_pin']) 51 | oc_reset = ppins.setup_pin('digital_out', oc_reset_pin) 52 | mcu = oc_reset.get_mcu() 53 | pin = oc_reset._pin 54 | mcu.add_config_cmd("set_digital_out pin=%s value=%d" % (pin, 0), True) 55 | mcu.add_config_cmd("set_digital_out pin=%s value=%d" % (pin, 1), True) 56 | 57 | for idx in range(4): 58 | gain = config.get('gain_t' + str(idx), '1') 59 | if gain not in ['1', '100']: 60 | raise Exception("Gain not 1 or 100") 61 | pin_name = pins[self.revision]['gain_enable_t' + str(idx)] 62 | if gain == '1': 63 | # Set pin to input 64 | pin = ppins.setup_pin('endstop', pin_name) 65 | else: 66 | pin = ppins.setup_pin('digital_out', pin_name) 67 | value = 1.0 68 | pin.setup_start_value(start_value=value, 69 | shutdown_value=value, 70 | is_static=True) 71 | 72 | pullup = config.get('pullup_t' + str(idx), '1') 73 | if pullup not in ['0', '1']: 74 | raise Exception("Pullup not 0 or 1") 75 | pin_name = pins[self.revision]['pullup_t' + str(idx)] 76 | if pullup == '0': 77 | pin = ppins.setup_pin('endstop', pin_name) 78 | else: 79 | pin = ppins.setup_pin('digital_out', pin_name) 80 | pin.setup_start_value(start_value=1., 81 | shutdown_value=1., 82 | is_static=True) 83 | offset = config.get('offset_t' + str(idx), '1') 84 | if offset not in ['0', '1']: 85 | raise Exception("Offset not 0 or 1") 86 | pin_name = pins[self.revision]['offset_t' + str(idx)] 87 | if offset == '0': 88 | pin = ppins.setup_pin('endstop', pin_name) 89 | else: 90 | pin = ppins.setup_pin('digital_out', pin_name) 91 | pin.setup_start_value(start_value=1., 92 | shutdown_value=1., 93 | is_static=True) 94 | 95 | 96 | def load_config(config): 97 | return recore(config) 98 | -------------------------------------------------------------------------------- /roles/install_klipper/files/recore_a5.py: -------------------------------------------------------------------------------- 1 | # Config for Recore Revision A5 and older. 2 | # 3 | # Copyright (C) 2017-2019 Kevin O'Connor 4 | # Copyright (C) 2019-2022 Elias Bakken 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | import logging, os 8 | import pins, mcu 9 | 10 | pins = { 11 | "A5": { 12 | 'enable_pin': 'ar100:PG2', 13 | 'oc_reset_pin': 'ar100:PG1', 14 | 'gain_enable_t0': 'ar100:PD4', 15 | 'gain_enable_t1': 'ar100:PH11', 16 | 'gain_enable_t2': 'ar100:PE17', 17 | 'gain_enable_t3': 'ar100:PB2', 18 | 'pullup_t0': 'ar100:PD6', 19 | 'pullup_t1': 'ar100:PD24', 20 | 'pullup_t2': 'ar100:PF0', 21 | 'pullup_t3': 'ar100:PF1' 22 | } 23 | } 24 | 25 | class recore_a5: 26 | def __init__(self, config): 27 | printer = config.get_printer() 28 | ppins = printer.lookup_object('pins') 29 | ppins.register_chip('recore', self) 30 | revisions = {'A3': 'A3', 'A4':'A4', 'A5':'A5'} 31 | self.revision = config.getchoice('revision', revisions) 32 | 33 | pins["A3"] = pins["A4"] = pins["A5"] 34 | # Setup enable pin 35 | enable_pin = config.get('enable_pin', 36 | pins[self.revision]['enable_pin']) 37 | mcu_power_enable = ppins.setup_pin('digital_out', enable_pin) 38 | mcu_power_enable.setup_start_value(start_value=0., 39 | shutdown_value=1., 40 | is_static=False) 41 | mcu_power_enable.setup_max_duration(0.) 42 | 43 | # Reset over current alarm 44 | oc_reset_pin = config.get('oc_reset_pin', 45 | pins[self.revision]['oc_reset_pin']) 46 | oc_reset = ppins.setup_pin('digital_out', oc_reset_pin) 47 | mcu = oc_reset.get_mcu() 48 | pin = oc_reset._pin 49 | mcu.add_config_cmd("set_digital_out pin=%s value=%d" % (pin, 0), True) 50 | mcu.add_config_cmd("set_digital_out pin=%s value=%d" % (pin, 1), True) 51 | 52 | for idx in range(4): 53 | gain = config.get('gain_t' + str(idx), '1') 54 | if gain not in ['1', '100']: 55 | raise Exception("Gain not 1 or 100") 56 | pin_name = pins[self.revision]['gain_enable_t' + str(idx)] 57 | if gain == '1': 58 | # Set pin to input 59 | pin = ppins.setup_pin('endstop', pin_name) 60 | else: 61 | pin = ppins.setup_pin('digital_out', pin_name) 62 | value = 0.0 63 | pin.setup_start_value(start_value=value, 64 | shutdown_value=value, 65 | is_static=True) 66 | 67 | pullup = config.get('pullup_t' + str(idx), '1') 68 | if pullup not in ['0', '1']: 69 | raise Exception("Pullup not 0 or 1") 70 | pin_name = pins[self.revision]['pullup_t' + str(idx)] 71 | if pullup == '0': 72 | pin = ppins.setup_pin('endstop', pin_name) 73 | else: 74 | pin = ppins.setup_pin('digital_out', pin_name) 75 | pin.setup_start_value(start_value=1., 76 | shutdown_value=1., 77 | is_static=True) 78 | 79 | def load_config(config): 80 | return recore_a5(config) 81 | -------------------------------------------------------------------------------- /roles/install_klipper/files/recore_adc_temperature.py: -------------------------------------------------------------------------------- 1 | # Obtain temperature using linear interpolation of ADC values, custom to Recore 2 | # 3 | # Copyright (C) 2016-2019 Kevin O'Connor 4 | # Copyright (C) 2021 Elias Bakken 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | import logging, bisect 8 | import math 9 | from . import adc_temperature 10 | ###################################################################### 11 | # Interface between MCU adc and heater temperature callbacks 12 | ###################################################################### 13 | 14 | SAMPLE_TIME = 0.001 15 | SAMPLE_COUNT = 8 16 | REPORT_TIME = 0.300 17 | RANGE_CHECK_COUNT = 4 18 | 19 | class RecoreLinearResistance(adc_temperature.LinearResistance): 20 | def __init__(self, config, samples): 21 | adc_temperature.LinearResistance.__init__(self, config, samples) 22 | self.adc_ref = config.getfloat('adc_voltage', 3.3) 23 | self.pullup_ref = config.getfloat('pullup_voltage', 3.3) 24 | self.vo_ref = config.getfloat('offset_voltage', 0.050) 25 | self.a = 1.84633422e-07 26 | self.b = -3.15418589e-07 27 | self.c = 3.16706799e-07 28 | self.d = -5.08889891e-08 29 | 30 | def smf5a_iv_curve(self, v): 31 | return self.a*v**3 + self.b*v**2 + self.c*v + self.d 32 | 33 | def calc_temp(self, adc): 34 | # Calculate temperature from adc 35 | adc = max(.00001, min(.99999, adc)) 36 | Vo = self.adc_ref*adc 37 | R2 = 100000 38 | R1 = 1000 39 | 40 | I1 = (Vo-self.vo_ref)/R2 # current through offset resistor 41 | VR1 = I1*R1 42 | V3 = Vo+VR1 # Voltage at the divider. 43 | 44 | ID = self.smf5a_iv_curve(V3) # TVS diode current 45 | I5 = (self.pullup_ref-V3)/self.pullup 46 | I3 = (I5-I1-ID) 47 | r = V3/(I3) 48 | return self.li.interpolate(r) 49 | 50 | class RecoreCustomLinearResistance: 51 | def __init__(self, config): 52 | self.name = " ".join(config.get_name().split()[1:]) 53 | self.samples = [] 54 | for i in range(1, 1000): 55 | t = config.getfloat("temperature%d" % (i,), None) 56 | if t is None: 57 | break 58 | r = config.getfloat("resistance%d" % (i,)) 59 | self.samples.append((t, r)) 60 | def create(self, config): 61 | lr = RecoreLinearResistance(config, self.samples) 62 | return adc_temperature.PrinterADCtoTemperature(config, lr) 63 | 64 | DefaultResistanceSensors = [ 65 | ("RECORE PT1000", adc_temperature.calc_pt100(1000.)) 66 | ] 67 | 68 | def load_config(config): 69 | pheaters = config.get_printer().load_object(config, "heaters") 70 | for sensor_type, params in DefaultResistanceSensors: 71 | func = (lambda config, params=params: 72 | adc_temperature.PrinterADCtoTemperature(config, 73 | RecoreLinearResistance(config, params))) 74 | pheaters.add_sensor_factory(sensor_type, func) 75 | 76 | def load_config_prefix(config): 77 | custom_sensor = RecoreCustomLinearResistance(config) 78 | pheaters = config.get_printer().load_object(config, "heaters") 79 | pheaters.add_sensor_factory(custom_sensor.name, custom_sensor.create) 80 | -------------------------------------------------------------------------------- /roles/install_klipper/files/recore_config: -------------------------------------------------------------------------------- 1 | # 2 | # Automatically generated file; DO NOT EDIT. 3 | # Klipper Firmware Configuration 4 | # 5 | # CONFIG_LOW_LEVEL_OPTIONS is not set 6 | # CONFIG_MACH_AVR is not set 7 | # CONFIG_MACH_ATSAM is not set 8 | # CONFIG_MACH_ATSAMD is not set 9 | # CONFIG_MACH_LPC176X is not set 10 | # CONFIG_MACH_STM32 is not set 11 | # CONFIG_MACH_STM32F0_HAL is not set 12 | # CONFIG_MACH_PRU is not set 13 | # CONFIG_MACH_AR100 is not set 14 | # CONFIG_MACH_LINUX is not set 15 | CONFIG_MACH_SIMU=y 16 | CONFIG_STEP_DELAY=2 17 | CONFIG_BOARD_DIRECTORY="simulator" 18 | CONFIG_CLOCK_FREQ=20000000 19 | CONFIG_SERIAL=y 20 | CONFIG_SERIAL_BAUD=250000 21 | CONFIG_SIMULATOR_SELECT=y 22 | CONFIG_HAVE_GPIO=y 23 | CONFIG_HAVE_GPIO_ADC=y 24 | CONFIG_HAVE_GPIO_SPI=y 25 | CONFIG_HAVE_GPIO_I2C=n 26 | CONFIG_HAVE_GPIO_HARD_PWM=y 27 | # CONFIG_HAVE_GPIO_BITBANGING is not set 28 | CONFIG_HAVE_GPIO_UART=y 29 | # CONFIG_HAVE_CHIPID is not set 30 | CONFIG_HAVE_ENDSTOPS=y 31 | CONFIG_HAVE_STEPPERS=y 32 | # CONFIG_HAVE_DEBUG is not set 33 | CONFIG_INLINE_STEPPER_HACK=y -------------------------------------------------------------------------------- /roles/install_klipper/files/recore_thermistor.py: -------------------------------------------------------------------------------- 1 | # Temperature measurements with thermistors 2 | # 3 | # Copyright (C) 2016-2019 Kevin O'Connor 4 | # Copyright (C) 2021 Elias Bakken 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | import math, logging 8 | from . import adc_temperature 9 | from . import thermistor 10 | 11 | KELVIN_TO_CELSIUS = -273.15 12 | 13 | class RecoreThermistor(thermistor.Thermistor): 14 | def __init__(self, pullup, inline_resistor, adc_ref, pullup_ref, vo_ref): 15 | thermistor.Thermistor.__init__(self, pullup, inline_resistor) 16 | self.adc_ref = adc_ref 17 | self.pullup_ref = pullup_ref 18 | self.vo_ref = vo_ref 19 | self.a = 1.84633422e-07 20 | self.b = -3.15418589e-07 21 | self.c = 3.16706799e-07 22 | self.d = -5.08889891e-08 23 | 24 | def smf5a_iv_curve(self, v): 25 | return self.a*v**3 + self.b*v**2 + self.c*v + self.d 26 | 27 | def calc_temp(self, adc): 28 | # Calculate temperature from adc 29 | adc = max(.00001, min(.99999, adc)) 30 | Vo = self.adc_ref*adc 31 | R2 = 100000 32 | R1 = 1000 33 | 34 | I1 = (Vo-self.vo_ref)/R2 # current through offset resistor 35 | VR1 = I1*R1 36 | V3 = Vo+VR1 # Voltage at the divider. 37 | 38 | ID = self.smf5a_iv_curve(V3) # TVS diode current 39 | I5 = (self.pullup_ref-V3)/self.pullup 40 | I3 = (I5-I1-ID) 41 | r = V3/I3 42 | 43 | ln_r = math.log(r) 44 | inv_t = self.c1 + self.c2 * ln_r + self.c3 * ln_r**3 45 | return 1.0/inv_t + KELVIN_TO_CELSIUS 46 | 47 | # Create an ADC converter with a thermistor 48 | def RecorePrinterThermistor(config, params): 49 | pullup = config.getfloat('pullup_resistor', 4700., above=0.) 50 | inline_resistor = config.getfloat('inline_resistor', 0., minval=0.) 51 | adc_ref = config.getfloat('adc_voltage', 3.3) 52 | pullup_ref = config.getfloat('pullup_voltage', 3.3) 53 | vo_ref = config.getfloat('offset_voltage', 0.05) 54 | thermistor = RecoreThermistor(pullup, inline_resistor, adc_ref, 55 | pullup_ref, vo_ref) 56 | 57 | if 'beta' in params: 58 | thermistor.setup_coefficients_beta( 59 | params['t1'], params['r1'], params['beta']) 60 | else: 61 | thermistor.setup_coefficients( 62 | params['t1'], params['r1'], params['t2'], params['r2'], 63 | params['t3'], params['r3'], name=config.get_name()) 64 | return adc_temperature.PrinterADCtoTemperature(config, thermistor) 65 | 66 | # Custom defined thermistors from the config file 67 | class RecoreCustomThermistor: 68 | def __init__(self, config): 69 | self.name = " ".join(config.get_name().split()[1:]) 70 | t1 = config.getfloat("temperature1", minval=KELVIN_TO_CELSIUS) 71 | r1 = config.getfloat("resistance1", minval=0.) 72 | beta = config.getfloat("beta", None, above=0.) 73 | if beta is not None: 74 | self.params = {'t1': t1, 'r1': r1, 'beta': beta} 75 | return 76 | t2 = config.getfloat("temperature2", minval=KELVIN_TO_CELSIUS) 77 | r2 = config.getfloat("resistance2", minval=0.) 78 | t3 = config.getfloat("temperature3", minval=KELVIN_TO_CELSIUS) 79 | r3 = config.getfloat("resistance3", minval=0.) 80 | (t1, r1), (t2, r2), (t3, r3) = sorted([(t1, r1), (t2, r2), (t3, r3)]) 81 | self.params = {'t1': t1, 'r1': r1, 't2': t2, 'r2': r2, 82 | 't3': t3, 'r3': r3} 83 | def create(self, config): 84 | return RecorePrinterThermistor(config, self.params) 85 | 86 | def load_config_prefix(config): 87 | thermistor = RecoreCustomThermistor(config) 88 | pheaters = config.get_printer().load_object(config, "heaters") 89 | pheaters.add_sensor_factory(thermistor.name, thermistor.create) 90 | -------------------------------------------------------------------------------- /roles/install_klipper/files/remoteproc1.path: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Remoteproc1 availability monitoring 3 | 4 | [Path] 5 | PathExists=/dev/remoteproc/ 6 | Unit=klipper_pru.service 7 | 8 | [Install] 9 | WantedBy=multi-user.target 10 | -------------------------------------------------------------------------------- /roles/install_klipper/files/replicape_linux_config: -------------------------------------------------------------------------------- 1 | # 2 | # Automatically generated file; DO NOT EDIT. 3 | # Klipper Firmware Configuration 4 | # 5 | CONFIG_LOW_LEVEL_OPTIONS=y 6 | # CONFIG_MACH_AVR is not set 7 | # CONFIG_MACH_ATSAM is not set 8 | # CONFIG_MACH_ATSAMD is not set 9 | # CONFIG_MACH_LPC176X is not set 10 | # CONFIG_MACH_STM32 is not set 11 | # CONFIG_MACH_PRU is not set 12 | CONFIG_MACH_LINUX=y 13 | # CONFIG_MACH_SIMU is not set 14 | CONFIG_STEP_DELAY=2 15 | CONFIG_BOARD_DIRECTORY="linux" 16 | CONFIG_CLOCK_FREQ=50000000 17 | CONFIG_LINUX_SELECT=y 18 | # CONFIG_CUSTOM_STEP_DELAY is not set 19 | CONFIG_INITIAL_PINS="" 20 | CONFIG_HAVE_GPIO=y 21 | CONFIG_HAVE_GPIO_ADC=y 22 | CONFIG_HAVE_GPIO_SPI=y 23 | CONFIG_HAVE_GPIO_I2C=y 24 | CONFIG_HAVE_GPIO_HARD_PWM=y 25 | CONFIG_HAVE_GPIO_BITBANGING=y 26 | # CONFIG_HAVE_CHIPID is not set 27 | CONFIG_INLINE_STEPPER_HACK=y 28 | -------------------------------------------------------------------------------- /roles/install_klipper/files/stm32f031-32KB-serial.config: -------------------------------------------------------------------------------- 1 | # Base config file for STM32F031 boards with serial on PA14/PA15 2 | CONFIG_MACH_STM32=y 3 | CONFIG_MACH_STM32F031=y 4 | CONFIG_SERIAL=y 5 | CONFIG_STM32_FLASH_START_0000=y 6 | CONFIG_STM32_SERIAL_USART2_ALT_PA15_PA14=y 7 | CONFIG_STM32_CLOCK_REF_INTERNAL=y 8 | CONFIG_LOW_LEVEL_OPTIONS=y 9 | CONFIG_WANT_GPIO_BITBANGING=y 10 | CONFIG_WANT_DISPLAYS=n 11 | -------------------------------------------------------------------------------- /roles/install_klipper/files/stm32f031-serial.config: -------------------------------------------------------------------------------- 1 | # Base config file for STM32F031 boards with serial on PA14/PA15 2 | CONFIG_MACH_STM32=y 3 | CONFIG_MACH_STM32F031=y 4 | CONFIG_SERIAL=y 5 | CONFIG_STM32_FLASH_START_0000=y 6 | CONFIG_STM32_SERIAL_USART2_ALT_PA15_PA14=y 7 | CONFIG_STM32_CLOCK_REF_INTERNAL=y 8 | CONFIG_LOW_LEVEL_OPTIONS=y 9 | CONFIG_WANT_GPIO_BITBANGING=n 10 | CONFIG_WANT_DISPLAYS=n 11 | -------------------------------------------------------------------------------- /roles/install_klipper/files/thermocouple.py: -------------------------------------------------------------------------------- 1 | # Temperature measurements with thermocouples. Only support for Type K for now. 2 | # Cold junction compensation 3 | # 4 | # Copyright (C) 2021 Elias Bakken 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | import math, logging 8 | from . import adc_temperature 9 | 10 | TYPE_K_COEFFEICIENTS = [ 11 | 0.000000E+00, 2.508355E+01, 7.860106E-02, -2.503131E-01, 8.315270E-02, 12 | -1.228034E-02, 9.804036E-04, -4.413030E-05, 1.057734E-06, -1.052755E-08 13 | ] 14 | TYPE_K_INVERSE = [ 15 | -0.176004136860E-01, 0.389212049750E-01, 0.185587700320E-04, 16 | -0.994575928740E-07, 0.318409457190E-09, -0.560728448890E-12, 17 | 0.560750590590E-15, -0.320207200030E-18, 0.971511471520E-22, 18 | -0.121047212750E-25 19 | ] 20 | TYPE_K_A = [0.118597600000E+00, -0.118343200000E-03, 0.126968600000E+03] 21 | 22 | 23 | # Analog voltage to temperature converter for thermocouple 24 | class Thermocouple: 25 | def __init__(self, gain, offset, vin, cj_temp): 26 | self.gain = gain 27 | self.offset = offset 28 | self.vin = vin 29 | self.cj_temp = cj_temp 30 | 31 | def get_exp(self, temp): 32 | return TYPE_K_A[0] * math.exp(TYPE_K_A[1] * (temp - TYPE_K_A[2])**2) 33 | 34 | def v_to_temp(self, v): 35 | return sum([ 36 | coeff * (v * 1000.0)**n 37 | for n, coeff in enumerate(TYPE_K_COEFFEICIENTS) 38 | ]) 39 | 40 | def temp_to_v(self, temp): 41 | return 0.001 * (sum([(coeff * temp**n) 42 | for n, coeff in enumerate(TYPE_K_INVERSE)]) + 43 | self.get_exp(temp)) 44 | 45 | def calc_temp(self, adc): 46 | adc_val = max(.00001, min(.99999, adc)) 47 | v_adc = self.vin * adc_val 48 | v_opamp = v_adc / self.gain 49 | v_in = (v_opamp - self.offset) 50 | cj_temp = self.cj_temp.get_temp(0)[0] 51 | v_cj = self.temp_to_v(cj_temp) 52 | temp = self.v_to_temp(v_in + v_cj) 53 | return temp 54 | 55 | # We do not know the cj temp at the time of setting limits, setting to 30 56 | def calc_adc(self, temp): 57 | cj_temp = 30 58 | v_in = self.temp_to_v(temp - cj_temp) 59 | v_opamp = v_in + self.offset 60 | v_adc = (v_opamp * self.gain) 61 | adc_val = v_adc / self.vin 62 | adc_val = max(.00001, min(.99999, adc_val)) 63 | return adc_val 64 | 65 | 66 | # Create an ADC converter with a thermocouple 67 | def PrinterThermocouple(config): 68 | gain = config.getfloat('gain', 101.0) 69 | offset = config.getfloat('offset', 0.0033) 70 | vin = config.getfloat('adc_voltage', 3.3) 71 | cj_sensor = config.get('cj_sensor', 'temperature_sensor cold_junction') 72 | cj_temp = config.get_printer().load_object(config, cj_sensor) 73 | thermocouple = Thermocouple(gain, offset, vin, cj_temp) 74 | return adc_temperature.PrinterADCtoTemperature(config, thermocouple) 75 | 76 | 77 | # Default sensors 78 | Sensors = ["Type K"] 79 | 80 | 81 | def load_config(config): 82 | pheaters = config.get_printer().load_object(config, "heaters") 83 | for sensor_type in Sensors: 84 | func = (lambda config: PrinterThermocouple(config)) 85 | pheaters.add_sensor_factory(sensor_type, func) 86 | -------------------------------------------------------------------------------- /roles/install_klipper/files/tmc2130_a5.py: -------------------------------------------------------------------------------- 1 | # TMC2130 configuration 2 | # 3 | # Copyright (C) 2018-2019 Kevin O'Connor 4 | # 5 | # This file may be distributed under the terms of the GNU GPLv3 license. 6 | import math, logging 7 | from . import bus, tmc 8 | 9 | TMC_FREQUENCY=13200000. 10 | 11 | Registers = { 12 | "GCONF": 0x00, "GSTAT": 0x01, "IOIN": 0x04, "IHOLD_IRUN": 0x10, 13 | "TPOWERDOWN": 0x11, "TSTEP": 0x12, "TPWMTHRS": 0x13, "TCOOLTHRS": 0x14, 14 | "THIGH": 0x15, "XDIRECT": 0x2d, "MSLUT0": 0x60, "MSLUT1": 0x61, 15 | "MSLUT2": 0x62, "MSLUT3": 0x63, "MSLUT4": 0x64, "MSLUT5": 0x65, 16 | "MSLUT6": 0x66, "MSLUT7": 0x67, "MSLUTSEL": 0x68, "MSLUTSTART": 0x69, 17 | "MSCNT": 0x6a, "MSCURACT": 0x6b, "CHOPCONF": 0x6c, "COOLCONF": 0x6d, 18 | "DCCTRL": 0x6e, "DRV_STATUS": 0x6f, "PWMCONF": 0x70, "PWM_SCALE": 0x71, 19 | "ENCM_CTRL": 0x72, "LOST_STEPS": 0x73, 20 | } 21 | 22 | ReadRegisters = [ 23 | "GCONF", "GSTAT", "IOIN", "TSTEP", "XDIRECT", "MSCNT", "MSCURACT", 24 | "CHOPCONF", "DRV_STATUS", "PWM_SCALE", "LOST_STEPS", 25 | ] 26 | 27 | Fields = {} 28 | Fields["GCONF"] = { 29 | "i_scale_analog": 1<<0, "internal_rsense": 1<<1, "en_pwm_mode": 1<<2, 30 | "enc_commutation": 1<<3, "shaft": 1<<4, "diag0_error": 1<<5, 31 | "diag0_otpw": 1<<6, "diag0_stall": 1<<7, "diag1_stall": 1<<8, 32 | "diag1_index": 1<<9, "diag1_onstate": 1<<10, "diag1_steps_skipped": 1<<11, 33 | "diag0_int_pushpull": 1<<12, "diag1_pushpull": 1<<13, 34 | "small_hysteresis": 1<<14, "stop_enable": 1<<15, "direct_mode": 1<<16, 35 | "test_mode": 1<<17 36 | } 37 | Fields["GSTAT"] = { "reset": 1<<0, "drv_err": 1<<1, "uv_cp": 1<<2 } 38 | Fields["IOIN"] = { 39 | "step": 1<<0, "dir": 1<<1, "dcen_cfg4": 1<<2, "dcin_cfg5": 1<<3, 40 | "drv_enn_cfg6": 1<<4, "dco": 1<<5, "version": 0xff << 24 41 | } 42 | Fields["IHOLD_IRUN"] = { 43 | "ihold": 0x1f << 0, "irun": 0x1f << 8, "iholddelay": 0x0f << 16 44 | } 45 | Fields["TPOWERDOWN"] = { "tpowerdown": 0xff } 46 | Fields["TSTEP"] = { "tstep": 0xfffff } 47 | Fields["TPWMTHRS"] = { "tpwmthrs": 0xfffff } 48 | Fields["TCOOLTHRS"] = { "tcoolthrs": 0xfffff } 49 | Fields["THIGH"] = { "thigh": 0xfffff } 50 | Fields["MSLUT0"] = { "mslut0": 0xffffffff } 51 | Fields["MSLUT1"] = { "mslut1": 0xffffffff } 52 | Fields["MSLUT2"] = { "mslut2": 0xffffffff } 53 | Fields["MSLUT3"] = { "mslut3": 0xffffffff } 54 | Fields["MSLUT4"] = { "mslut4": 0xffffffff } 55 | Fields["MSLUT5"] = { "mslut5": 0xffffffff } 56 | Fields["MSLUT6"] = { "mslut6": 0xffffffff } 57 | Fields["MSLUT7"] = { "mslut7": 0xffffffff } 58 | Fields["MSLUTSEL"] = { 59 | "x3": 0xFF << 24, 60 | "x2": 0xFF << 16, 61 | "x1": 0xFF << 8, 62 | "w3": 0x03 << 6, 63 | "w2": 0x03 << 4, 64 | "w1": 0x03 << 2, 65 | "w0": 0x03 << 0, 66 | } 67 | Fields["MSLUTSTART"] = { 68 | "start_sin": 0xFF << 0, 69 | "start_sin90": 0xFF << 16, 70 | } 71 | Fields["MSCNT"] = { "mscnt": 0x3ff } 72 | Fields["MSCURACT"] = { "cur_a": 0x1ff, "cur_b": 0x1ff << 16 } 73 | Fields["CHOPCONF"] = { 74 | "toff": 0x0f, "hstrt": 0x07 << 4, "hend": 0x0f << 7, "fd3": 1<<11, 75 | "disfdcc": 1<<12, "rndtf": 1<<13, "chm": 1<<14, "tbl": 0x03 << 15, 76 | "vsense": 1<<17, "vhighfs": 1<<18, "vhighchm": 1<<19, "sync": 0x0f << 20, 77 | "mres": 0x0f << 24, "intpol": 1<<28, "dedge": 1<<29, "diss2g": 1<<30 78 | } 79 | Fields["COOLCONF"] = { 80 | "semin": 0x0f, "seup": 0x03 << 5, "semax": 0x0f << 8, "sedn": 0x03 << 13, 81 | "seimin": 1<<15, "sgt": 0x7f << 16, "sfilt": 1<<24 82 | } 83 | Fields["DRV_STATUS"] = { 84 | "sg_result": 0x3ff, "fsactive": 1<<15, "cs_actual": 0x1f << 16, 85 | "stallguard": 1<<24, "ot": 1<<25, "otpw": 1<<26, "s2ga": 1<<27, 86 | "s2gb": 1<<28, "ola": 1<<29, "olb": 1<<30, "stst": 1<<31 87 | } 88 | Fields["PWMCONF"] = { 89 | "pwm_ampl": 0xff, "pwm_grad": 0xff << 8, "pwm_freq": 0x03 << 16, 90 | "pwm_autoscale": 1<<18, "pwm_symmetric": 1<<19, "freewheel": 0x03 << 20 91 | } 92 | Fields["PWM_SCALE"] = { "pwm_scale": 0xff } 93 | Fields["LOST_STEPS"] = { "lost_steps": 0xfffff } 94 | 95 | SignedFields = ["cur_a", "cur_b", "sgt"] 96 | 97 | FieldFormatters = { 98 | "i_scale_analog": (lambda v: "1(ExtVREF)" if v else ""), 99 | "shaft": (lambda v: "1(Reverse)" if v else ""), 100 | "reset": (lambda v: "1(Reset)" if v else ""), 101 | "drv_err": (lambda v: "1(ErrorShutdown!)" if v else ""), 102 | "uv_cp": (lambda v: "1(Undervoltage!)" if v else ""), 103 | "version": (lambda v: "%#x" % v), 104 | "mres": (lambda v: "%d(%dusteps)" % (v, 0x100 >> v)), 105 | "otpw": (lambda v: "1(OvertempWarning!)" if v else ""), 106 | "ot": (lambda v: "1(OvertempError!)" if v else ""), 107 | "s2ga": (lambda v: "1(ShortToGND_A!)" if v else ""), 108 | "s2gb": (lambda v: "1(ShortToGND_B!)" if v else ""), 109 | "ola": (lambda v: "1(OpenLoad_A!)" if v else ""), 110 | "olb": (lambda v: "1(OpenLoad_B!)" if v else ""), 111 | "cs_actual": (lambda v: ("%d" % v) if v else "0(Reset?)"), 112 | } 113 | 114 | 115 | ###################################################################### 116 | # TMC stepper current config helper 117 | ###################################################################### 118 | 119 | MAX_CURRENT = 2.000 120 | 121 | class TMCCurrentHelper: 122 | def __init__(self, config, mcu_tmc): 123 | self.printer = config.get_printer() 124 | self.name = config.get_name().split()[-1] 125 | self.mcu_tmc = mcu_tmc 126 | self.fields = mcu_tmc.get_fields() 127 | run_current = config.getfloat('run_current', 128 | above=0., maxval=MAX_CURRENT) 129 | hold_current = config.getfloat('hold_current', MAX_CURRENT, 130 | above=0., maxval=MAX_CURRENT) 131 | self.req_hold_current = hold_current 132 | self.sense_resistor = config.getfloat('sense_resistor', 0.110, above=0.) 133 | self.ref_resistor = config.getfloat('ref_resistor', 6800., above=0.) 134 | self.internal_r_sense = config.getint('driver_internal_rsense', 0) 135 | vsense, irun, ihold = self._calc_current(run_current, hold_current) 136 | self.fields.set_field("vsense", vsense) 137 | self.fields.set_field("ihold", ihold) 138 | self.fields.set_field("irun", irun) 139 | def _calc_current_bits(self, current, vsense): 140 | if self.internal_r_sense: 141 | r_ref = self.ref_resistor + 450 142 | v_ref = 5 143 | rms_current_max = (3000 * v_ref / (r_ref * math.sqrt(2.))) 144 | cs = int(32. * current / rms_current_max) 145 | else: 146 | sense_resistor = self.sense_resistor + 0.020 147 | vref = 0.32 148 | if vsense: 149 | vref = 0.18 150 | cs = int(32. * sense_resistor * current * math.sqrt(2.) 151 | / vref + .5) - 1 152 | return max(0, min(31, cs)) 153 | def _calc_current_from_bits(self, cs, vsense): 154 | if self.internal_r_sense: 155 | r_ref = self.ref_resistor + 450 156 | v_ref = 5 157 | rms_current_max = (3000 * v_ref / (r_ref * math.sqrt(2.))) 158 | return cs * rms_current_max / 32. 159 | else: 160 | sense_resistor = self.sense_resistor + 0.020 161 | vref = 0.32 162 | if vsense: 163 | vref = 0.18 164 | return (cs + 1) * vref / (32. * sense_resistor * math.sqrt(2.)) 165 | def _calc_current(self, run_current, hold_current): 166 | vsense = True 167 | irun = self._calc_current_bits(run_current, True) 168 | if irun == 31: 169 | cur = self._calc_current_from_bits(irun, True) 170 | if cur < run_current: 171 | irun2 = self._calc_current_bits(run_current, False) 172 | cur2 = self._calc_current_from_bits(irun2, False) 173 | if abs(run_current - cur2) < abs(run_current - cur): 174 | vsense = False 175 | irun = irun2 176 | ihold = self._calc_current_bits(min(hold_current, run_current), vsense) 177 | return vsense, irun, ihold 178 | def get_current(self): 179 | irun = self.fields.get_field("irun") 180 | ihold = self.fields.get_field("ihold") 181 | vsense = self.fields.get_field("vsense") 182 | run_current = self._calc_current_from_bits(irun, vsense) 183 | hold_current = self._calc_current_from_bits(ihold, vsense) 184 | return run_current, hold_current, self.req_hold_current, MAX_CURRENT 185 | def set_current(self, run_current, hold_current, print_time): 186 | self.req_hold_current = hold_current 187 | vsense, irun, ihold = self._calc_current(run_current, hold_current) 188 | if vsense != self.fields.get_field("vsense"): 189 | val = self.fields.set_field("vsense", vsense) 190 | self.mcu_tmc.set_register("CHOPCONF", val, print_time) 191 | self.fields.set_field("ihold", ihold) 192 | val = self.fields.set_field("irun", irun) 193 | self.mcu_tmc.set_register("IHOLD_IRUN", val, print_time) 194 | 195 | 196 | ###################################################################### 197 | # TMC2130 SPI 198 | ###################################################################### 199 | 200 | class MCU_TMC_SPI_chain: 201 | def __init__(self, config, chain_len=1): 202 | self.printer = config.get_printer() 203 | self.chain_len = chain_len 204 | self.mutex = self.printer.get_reactor().mutex() 205 | share = None 206 | if chain_len > 1: 207 | share = "tmc_spi_cs" 208 | self.spi = bus.MCU_SPI_from_config(config, 3, default_speed=4000000, 209 | share_type=share) 210 | self.taken_chain_positions = [] 211 | def _build_cmd(self, data, chain_pos): 212 | return ([0x00] * ((self.chain_len - chain_pos) * 5) + 213 | data + [0x00] * ((chain_pos - 1) * 5)) 214 | def reg_read(self, reg, chain_pos): 215 | cmd = self._build_cmd([reg, 0x00, 0x00, 0x00, 0x00], chain_pos) 216 | self.spi.spi_send(cmd) 217 | if self.printer.get_start_args().get('debugoutput') is not None: 218 | return 0 219 | params = self.spi.spi_transfer(cmd) 220 | pr = bytearray(params['response']) 221 | pr = pr[(self.chain_len - chain_pos) * 5 : 222 | (self.chain_len - chain_pos + 1) * 5] 223 | return (pr[1] << 24) | (pr[2] << 16) | (pr[3] << 8) | pr[4] 224 | def reg_write(self, reg, val, chain_pos, print_time=None): 225 | minclock = 0 226 | if print_time is not None: 227 | minclock = self.spi.get_mcu().print_time_to_clock(print_time) 228 | data = [(reg | 0x80) & 0xff, (val >> 24) & 0xff, (val >> 16) & 0xff, 229 | (val >> 8) & 0xff, val & 0xff] 230 | if self.printer.get_start_args().get('debugoutput') is not None: 231 | self.spi.spi_send(self._build_cmd(data, chain_pos), minclock) 232 | return val 233 | write_cmd = self._build_cmd(data, chain_pos) 234 | dummy_read = self._build_cmd([0x00, 0x00, 0x00, 0x00, 0x00], chain_pos) 235 | params = self.spi.spi_transfer_with_preface(write_cmd, dummy_read, 236 | minclock=minclock) 237 | pr = bytearray(params['response']) 238 | pr = pr[(self.chain_len - chain_pos) * 5 : 239 | (self.chain_len - chain_pos + 1) * 5] 240 | return (pr[1] << 24) | (pr[2] << 16) | (pr[3] << 8) | pr[4] 241 | 242 | # Helper to setup an spi daisy chain bus from settings in a config section 243 | def lookup_tmc_spi_chain(config): 244 | chain_len = config.getint('chain_length', None, minval=2) 245 | if chain_len is None: 246 | # Simple, non daisy chained SPI connection 247 | return MCU_TMC_SPI_chain(config, 1), 1 248 | 249 | # Shared SPI bus - lookup existing MCU_TMC_SPI_chain 250 | ppins = config.get_printer().lookup_object("pins") 251 | cs_pin_params = ppins.lookup_pin(config.get('cs_pin'), 252 | share_type="tmc_spi_cs") 253 | tmc_spi = cs_pin_params.get('class') 254 | if tmc_spi is None: 255 | tmc_spi = cs_pin_params['class'] = MCU_TMC_SPI_chain(config, chain_len) 256 | if chain_len != tmc_spi.chain_len: 257 | raise config.error("TMC SPI chain must have same length") 258 | chain_pos = config.getint('chain_position', minval=1, maxval=chain_len) 259 | if chain_pos in tmc_spi.taken_chain_positions: 260 | raise config.error("TMC SPI chain can not have duplicate position") 261 | tmc_spi.taken_chain_positions.append(chain_pos) 262 | return tmc_spi, chain_pos 263 | 264 | # Helper code for working with TMC devices via SPI 265 | class MCU_TMC_SPI: 266 | def __init__(self, config, name_to_reg, fields, tmc_frequency): 267 | self.printer = config.get_printer() 268 | self.name = config.get_name().split()[-1] 269 | self.tmc_spi, self.chain_pos = lookup_tmc_spi_chain(config) 270 | self.mutex = self.tmc_spi.mutex 271 | self.name_to_reg = name_to_reg 272 | self.fields = fields 273 | self.tmc_frequency = tmc_frequency 274 | def get_fields(self): 275 | return self.fields 276 | def get_register(self, reg_name): 277 | reg = self.name_to_reg[reg_name] 278 | with self.mutex: 279 | read = self.tmc_spi.reg_read(reg, self.chain_pos) 280 | return read 281 | def set_register(self, reg_name, val, print_time=None): 282 | reg = self.name_to_reg[reg_name] 283 | with self.mutex: 284 | for retry in range(5): 285 | v = self.tmc_spi.reg_write(reg, val, self.chain_pos, print_time) 286 | if v == val: 287 | return 288 | raise self.printer.command_error( 289 | "Unable to write tmc spi '%s' register %s" % (self.name, reg_name)) 290 | def get_tmc_frequency(self): 291 | return self.tmc_frequency 292 | 293 | 294 | ###################################################################### 295 | # TMC2130 printer object 296 | ###################################################################### 297 | 298 | class TMC2130: 299 | def __init__(self, config): 300 | # Setup mcu communication 301 | self.fields = tmc.FieldHelper(Fields, SignedFields, FieldFormatters) 302 | self.mcu_tmc = MCU_TMC_SPI(config, Registers, self.fields, 303 | TMC_FREQUENCY) 304 | # Allow virtual pins to be created 305 | tmc.TMCVirtualPinHelper(config, self.mcu_tmc) 306 | # Register commands 307 | current_helper = TMCCurrentHelper(config, self.mcu_tmc) 308 | cmdhelper = tmc.TMCCommandHelper(config, self.mcu_tmc, current_helper) 309 | cmdhelper.setup_register_dump(ReadRegisters) 310 | self.get_phase_offset = cmdhelper.get_phase_offset 311 | self.get_status = cmdhelper.get_status 312 | # Setup basic register values 313 | tmc.TMCWaveTableHelper(config, self.mcu_tmc) 314 | tmc.TMCStealthchopHelper(config, self.mcu_tmc, TMC_FREQUENCY) 315 | # Allow other registers to be set from the config 316 | set_config_field = self.fields.set_config_field 317 | # CHOPCONF 318 | set_config_field(config, "toff", 4) 319 | set_config_field(config, "hstrt", 0) 320 | set_config_field(config, "hend", 7) 321 | set_config_field(config, "tbl", 1) 322 | # COOLCONF 323 | set_config_field(config, "sgt", 0) 324 | # IHOLDIRUN 325 | set_config_field(config, "iholddelay", 8) 326 | # PWMCONF 327 | set_config_field(config, "pwm_ampl", 128) 328 | set_config_field(config, "pwm_grad", 4) 329 | set_config_field(config, "pwm_freq", 1) 330 | set_config_field(config, "pwm_autoscale", True) 331 | # TPOWERDOWN 332 | set_config_field(config, "tpowerdown", 0) 333 | 334 | def load_config_prefix(config): 335 | return TMC2130(config) 336 | -------------------------------------------------------------------------------- /roles/install_klipper/files/tmc2209_a5.py: -------------------------------------------------------------------------------- 1 | # TMC2209 configuration 2 | # 3 | # Copyright (C) 2019 Stephan Oelze 4 | # 5 | # This file may be distributed under the terms of the GNU GPLv3 license. 6 | from . import tmc2130_a5, tmc2208, tmc, tmc_uart 7 | 8 | TMC_FREQUENCY=12000000. 9 | 10 | Registers = dict(tmc2208.Registers) 11 | Registers.update({ 12 | "TCOOLTHRS": 0x14, 13 | "COOLCONF": 0x42, 14 | "SGTHRS": 0x40, 15 | "SG_RESULT": 0x41 16 | }) 17 | 18 | ReadRegisters = tmc2208.ReadRegisters + ["SG_RESULT"] 19 | 20 | Fields = dict(tmc2208.Fields) 21 | Fields["COOLCONF"] = { 22 | "semin": 0x0F << 0, 23 | "seup": 0x03 << 5, 24 | "semax": 0x0F << 8, 25 | "sedn": 0x03 << 13, 26 | "seimin": 0x01 << 15 27 | } 28 | Fields["IOIN"] = { 29 | "enn": 0x01 << 0, 30 | "ms1": 0x01 << 2, 31 | "ms2": 0x01 << 3, 32 | "diag": 0x01 << 4, 33 | "pdn_uart": 0x01 << 6, 34 | "step": 0x01 << 7, 35 | "spread_en": 0x01 << 8, 36 | "dir": 0x01 << 9, 37 | "version": 0xff << 24 38 | } 39 | Fields["SGTHRS"] = { 40 | "sgthrs": 0xFF << 0 41 | } 42 | Fields["SG_RESULT"] = { 43 | "sg_result": 0x3FF << 0 44 | } 45 | Fields["TCOOLTHRS"] = { 46 | "tcoolthrs": 0xfffff 47 | } 48 | 49 | FieldFormatters = dict(tmc2208.FieldFormatters) 50 | 51 | 52 | ###################################################################### 53 | # TMC2209 printer object 54 | ###################################################################### 55 | 56 | class TMC2209_a5: 57 | def __init__(self, config): 58 | # Setup mcu communication 59 | self.fields = tmc.FieldHelper(Fields, tmc2208.SignedFields, 60 | FieldFormatters) 61 | self.mcu_tmc = tmc_uart.MCU_TMC_uart(config, Registers, self.fields, 3, 62 | TMC_FREQUENCY) 63 | # Setup fields for UART 64 | self.fields.set_field("pdn_disable", True) 65 | self.fields.set_field("senddelay", 2) # Avoid tx errors on shared uart 66 | # Allow virtual pins to be created 67 | tmc.TMCVirtualPinHelper(config, self.mcu_tmc) 68 | # Register commands 69 | current_helper = tmc2130_a5.TMCCurrentHelper(config, self.mcu_tmc) 70 | cmdhelper = tmc.TMCCommandHelper(config, self.mcu_tmc, current_helper) 71 | cmdhelper.setup_register_dump(ReadRegisters) 72 | self.get_phase_offset = cmdhelper.get_phase_offset 73 | self.get_status = cmdhelper.get_status 74 | # Setup basic register values 75 | self.fields.set_field("mstep_reg_select", True) 76 | self.fields.set_field("multistep_filt", True) 77 | tmc.TMCStealthchopHelper(config, self.mcu_tmc, TMC_FREQUENCY) 78 | # Allow other registers to be set from the config 79 | set_config_field = self.fields.set_config_field 80 | # CHOPCONF 81 | set_config_field(config, "toff", 3) 82 | set_config_field(config, "hstrt", 5) 83 | set_config_field(config, "hend", 0) 84 | set_config_field(config, "tbl", 2) 85 | # IHOLDIRUN 86 | set_config_field(config, "iholddelay", 8) 87 | # PWMCONF 88 | set_config_field(config, "pwm_ofs", 36) 89 | set_config_field(config, "pwm_grad", 14) 90 | set_config_field(config, "pwm_freq", 1) 91 | set_config_field(config, "pwm_autoscale", True) 92 | set_config_field(config, "pwm_autograd", True) 93 | set_config_field(config, "pwm_reg", 8) 94 | set_config_field(config, "pwm_lim", 12) 95 | # TPOWERDOWN 96 | set_config_field(config, "tpowerdown", 20) 97 | # SGTHRS 98 | set_config_field(config, "sgthrs", 0) 99 | set_config_field(config, "internal_rsense", 0) 100 | 101 | def load_config_prefix(config): 102 | return TMC2209_a5(config) 103 | -------------------------------------------------------------------------------- /roles/install_klipper/files/uEnv.txt: -------------------------------------------------------------------------------- 1 | #Docs: http://elinux.org/Beagleboard:U-boot_partitioning_layout_2.0 2 | 3 | uname_r=4.14.108-ti-r124 4 | #uuid= 5 | #dtb= 6 | 7 | ###U-Boot Overlays### 8 | ###Documentation: http://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays 9 | ###Master Enable 10 | enable_uboot_overlays=1 11 | uboot_overlay_addr0=/lib/firmware/BB-BONE-REPLICAP-0B3A.dtbo 12 | ### 13 | ###Disable auto loading of virtual capes (emmc/video/wireless/adc) 14 | #disable_uboot_overlay_emmc=1 15 | #disable_uboot_overlay_video=1 16 | disable_uboot_overlay_audio=1 17 | #disable_uboot_overlay_wireless=1 18 | #disable_uboot_overlay_adc=1 19 | ### 20 | uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-14-TI-00A0.dtbo 21 | ###Cape Universal Enable 22 | enable_uboot_cape_universal=1 23 | ### 24 | ###Debug: disable uboot autoload of Cape 25 | #disable_uboot_overlay_addr0=1 26 | #disable_uboot_overlay_addr1=1 27 | #disable_uboot_overlay_addr2=1 28 | #disable_uboot_overlay_addr3=1 29 | ### 30 | ###U-Boot fdt tweaks... (60000 = 384KB) 31 | #uboot_overlay_pru=/lib/firmware/AM335X-PRU-UIO 32 | #uboot_fdt_buffer=0x60000 33 | ###U-Boot Overlays### 34 | 35 | cmdline=coherent_pool=1M net.ifnames=0 rng_core.default_quality=100 cape_universal=enable quiet omap_wdt.nowayout=0 36 | 37 | #In the event of edid real failures, uncomment this next line: 38 | #cmdline=coherent_pool=1M net.ifnames=0 rng_core.default_quality=100 cape_universal=enable quiet video=HDMI-A-1:1024x768@60e 39 | 40 | #Use an overlayfs on top of a read-only root filesystem: 41 | #cmdline=coherent_pool=1M net.ifnames=0 rng_core.default_quality=100 cape_universal=enable quiet overlayroot=tmpfs 42 | 43 | ##enable Generic eMMC Flasher: 44 | #cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh 45 | 46 | -------------------------------------------------------------------------------- /roles/install_klipper/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: linux_preparation } -------------------------------------------------------------------------------- /roles/install_klipper/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Replicape - Install Klipper 3 | include: replicape.yml 4 | when: platform == 'replicape' 5 | 6 | - name: Recore - Install Klipper 7 | include: recore.yml 8 | when: platform == 'recore' 9 | 10 | - name: Pi - Install Klipper 11 | include: pi.yml 12 | when: platform == 'pi' 13 | 14 | - name: Pi64 - Install Klipper 15 | include: pi.yml 16 | when: platform == 'pi64' 17 | -------------------------------------------------------------------------------- /roles/install_klipper/tasks/pi.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Pi - clone klipper from the master repository 3 | git: 4 | repo: https://github.com/KevinOConnor/klipper 5 | version: master 6 | dest: '{{ klipper_home }}' 7 | update: yes 8 | clone: yes 9 | 10 | - name: Pi - add debian user to tty group 11 | user: 12 | name: debian 13 | groups: tty 14 | append: yes 15 | 16 | - name: Pi - Install libgpiod-dev 17 | apt: 18 | name: 19 | - libgpiod-dev 20 | - gpiod 21 | state: present 22 | 23 | - name: Pi - adjust ownership of klipper source 24 | file: 25 | path: "{{ klipper_home }}" 26 | owner: debian 27 | group: debian 28 | recurse: yes 29 | 30 | - name: Pi - give debian user the klipper service permissions 31 | lineinfile: 32 | path: /etc/sudoers 33 | state: present 34 | line: "debian ALL=NOPASSWD: ALL" 35 | 36 | - name: Pi - remove sudoers group authorization 37 | lineinfile: 38 | path: /etc/sudoers 39 | line: "%sudo ALL=(ALL:ALL) ALL" 40 | state: absent 41 | 42 | - name: Pi - install Klipper with install scripts 43 | shell: "export USER=debian; {{ klipper_home }}/scripts/install-octopi.sh" 44 | args: 45 | chdir: "{{ klipper_home }}" 46 | become: true 47 | become_user: debian 48 | 49 | - name: Pi - determine if config is the default OctoPrint config or not 50 | lineinfile: 51 | path: /home/debian/.octoprint/config.yaml 52 | line: 'firstRun: true' 53 | state: present 54 | check_mode: yes 55 | register: replace_default_octoprint_config 56 | 57 | - name: Pi - place Klipper-friendly config for octoprint in place 58 | copy: 59 | src: "{{ role_path }}/files/octoprint_config.yaml" 60 | dest: /home/debian/.octoprint/config.yaml 61 | owner: debian 62 | group: debian 63 | remote_src: yes 64 | force: no 65 | when: replace_default_octoprint_config == 'True' 66 | 67 | - name: Pi - place Klipper-service files in place 68 | copy: 69 | src: "{{ role_path }}/files/octoprint.service" 70 | dest: /etc/systemd/system/ 71 | owner: debian 72 | group: debian 73 | 74 | - name: Pi - Install KIAUH 75 | git: 76 | repo: https://github.com/th33xitus/kiauh.git 77 | dest: '{{ klipper_home }}/../kiauh' 78 | update: yes 79 | clone: yes 80 | -------------------------------------------------------------------------------- /roles/install_klipper/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install packages 3 | apt: 4 | name: 5 | - libgpiod-dev 6 | - gpiod 7 | - git 8 | - virtualenv 9 | - python3-dev 10 | - libffi-dev 11 | - build-essential 12 | - libncurses-dev 13 | - libusb-dev 14 | - stm32flash 15 | - libnewlib-arm-none-eabi 16 | - binutils-arm-none-eabi 17 | - gcc-arm-none-eabi 18 | - pkg-config 19 | - python3-libxml2 20 | - python3-cffi 21 | - libc6-dev 22 | state: present 23 | 24 | - name: Recore - give debian permissions to python folders for updates 25 | file: 26 | path: '{{ item }}' 27 | group: debian 28 | owner: debian 29 | mode: 0755 30 | recurse: yes 31 | state: directory 32 | with_items: 33 | - /home/debian 34 | - /usr/local/lib/python3 35 | - /usr/local/bin 36 | 37 | - name: Recore - clone klipper from the repository 38 | git: 39 | repo: https://github.com/Klipper3d/klipper 40 | version: master 41 | dest: '{{ klipper_home }}' 42 | update: yes 43 | clone: yes 44 | 45 | - name: Recore - add missing files for klipper 46 | copy: 47 | src: 'files/{{ item }}' 48 | dest: "{{ klipper_home }}/klippy/extras/" 49 | mode: '0644' 50 | with_items: 51 | - thermocouple.py 52 | - recore.py 53 | - recore_a5.py 54 | - tmc2130_a5.py 55 | - tmc2209_a5.py 56 | - recore_thermistor.py 57 | - recore_adc_temperature.py 58 | 59 | - name: Recore - add missing install script 60 | copy: 61 | src: files/install-recore.sh 62 | dest: "{{ klipper_home }}/scripts/" 63 | mode: '0755' 64 | 65 | - name: Recore - add config files 66 | copy: 67 | src: "files/{{ item }}" 68 | dest: "{{ klipper_home }}/config/" 69 | mode: '0644' 70 | with_items: 71 | - generic-recore-a5.cfg 72 | - generic-recore-a6.cfg 73 | - generic-recore-a7.cfg 74 | 75 | - name: Recore - adjust ownership of klipper source 76 | file: 77 | path: "{{ klipper_home }}" 78 | owner: debian 79 | group: debian 80 | recurse: yes 81 | 82 | - name: Recore - give debian user the klipper service permissions 83 | lineinfile: 84 | path: /etc/sudoers 85 | state: present 86 | line: "debian ALL=NOPASSWD: ALL" 87 | 88 | - name: Recore - remove sudoers group authorization 89 | lineinfile: 90 | path: /etc/sudoers 91 | line: "%sudo ALL=(ALL:ALL) ALL" 92 | state: absent 93 | 94 | - name: Recore - Create virtual env 95 | shell: virtualenv -p python3 /home/debian/klippy-env 96 | become: true 97 | become_user: debian 98 | 99 | - name: Recore - install requirements 100 | shell: /home/debian/klippy-env/bin/pip install -r /home/debian/klipper/scripts/klippy-requirements.txt 101 | become: true 102 | become_user: debian 103 | 104 | - name: Recore - install Numpy 105 | shell: "/home/debian/klippy-env/bin/pip install numpy" 106 | 107 | - name: Recore - Install klipper service file 108 | copy: 109 | src: "{{ role_path }}/files/klipper-recore.service" 110 | dest: "/etc/systemd/system/klipper.service" 111 | mode: '0644' 112 | 113 | - name: Recore - Enable klipper service 114 | service: 115 | name: klipper.service 116 | enabled: yes 117 | 118 | - name: Recore - Make firmware folder 119 | file: 120 | path: /opt/firmware 121 | state: directory 122 | mode: '0755' 123 | owner: debian 124 | group: debian 125 | 126 | - name: Recore - Get and extract toolchain 127 | unarchive: 128 | src: http://feeds.iagent.no/toolchains/or1k-linux-musl-11.2.0.tar.xz 129 | dest: /opt/ 130 | owner: debian 131 | group: debian 132 | remote_src: yes 133 | 134 | - name: Recore - copy or1k toolchain to proper path 135 | shell: | 136 | rsync -a /opt/output/ /usr/local && rm -r /opt/output 137 | 138 | - name: Recore - Copy AR100 config 139 | copy: 140 | src: "{{ role_path }}/files/ar100.config" 141 | dest: "{{ klipper_home }}/.config" 142 | owner: debian 143 | group: debian 144 | 145 | - name: Recore - Compile AR100 binary 146 | shell: | 147 | chown debian:debian -R . 148 | make olddefconfig 149 | make 150 | args: 151 | chdir: "{{ klipper_home }}" 152 | 153 | - name: Recore - Copy AR100 binary 154 | copy: 155 | src: "{{ klipper_home }}/out/ar100.bin" 156 | dest: /opt/firmware/ar100.bin 157 | owner: debian 158 | group: debian 159 | remote_src: yes 160 | force: no 161 | 162 | - name: Recore - Install bl31 binary 163 | copy: 164 | src: "{{ role_path }}/files/bl31.bin" 165 | dest: /opt/firmware/bl31.bin 166 | owner: debian 167 | group: debian 168 | 169 | - name: Recore - Copy STM32 config 170 | copy: 171 | src: "{{ role_path }}/files/stm32f031-serial.config" 172 | dest: "{{ klipper_home }}/.config" 173 | owner: debian 174 | group: debian 175 | 176 | - name: Recore - Compile STM32 binary 177 | shell: | 178 | make olddefconfig 179 | make 180 | args: 181 | chdir: "{{ klipper_home }}" 182 | 183 | - name: Recore - Copy STM32 binary 184 | copy: 185 | src: "{{ klipper_home }}/out/klipper.bin" 186 | dest: /opt/firmware/stm32.bin 187 | owner: debian 188 | group: debian 189 | remote_src: yes 190 | force: no 191 | 192 | - name: Recore - Copy patch 193 | copy: 194 | src: "{{ role_path }}/files/enable-i2c.patch" 195 | dest: "{{ klipper_home }}" 196 | owner: debian 197 | group: debian 198 | 199 | - name: Recore - Increase flash size and add i2c 200 | shell: | 201 | patch -p1 < enable-i2c.patch 202 | args: 203 | chdir: "{{ klipper_home }}" 204 | 205 | - name: Recore - Copy STM32 config with 32 KB flash 206 | copy: 207 | src: "{{ role_path }}/files/stm32f031-32KB-serial.config" 208 | dest: "{{ klipper_home }}/.config" 209 | owner: debian 210 | group: debian 211 | 212 | - name: Recore - Compile STM32 binary with 32 KB flash 213 | shell: | 214 | make clean 215 | make olddefconfig 216 | make -j 217 | args: 218 | chdir: "{{ klipper_home }}" 219 | 220 | - name: Recore - Copy STM32 binary with 32 KB flash 221 | copy: 222 | src: "{{ klipper_home }}/out/klipper.bin" 223 | dest: /opt/firmware/stm32-32KB.bin 224 | owner: debian 225 | group: debian 226 | remote_src: yes 227 | force: no 228 | 229 | - name: Recore - reset folder 230 | shell: | 231 | git reset --hard 232 | args: 233 | chdir: "{{ klipper_home }}" 234 | 235 | - name: Recore - Install stm32 flasher script 236 | copy: 237 | src: "{{ role_path }}/files/flash-stm32" 238 | dest: "/usr/local/bin" 239 | mode: '0755' 240 | 241 | - name: Recore - Install stm32 flasher service 242 | copy: 243 | src: "{{ role_path }}/files/flash-stm32.service" 244 | dest: "/etc/systemd/system/" 245 | 246 | - name: Recore - Enable stm32 flasher service 247 | service: 248 | name: flash-stm32.service 249 | enabled: yes 250 | 251 | - name: Recore - Make Klipper config folder 252 | file: 253 | path: /home/debian/printer_data/config/ 254 | state: directory 255 | mode: '0755' 256 | owner: debian 257 | group: debian 258 | -------------------------------------------------------------------------------- /roles/install_klipper/tasks/replicape.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Replicape - get installed kernel version 3 | shell: ls /lib/modules 4 | register: kernel_version 5 | 6 | - name: Replicape - set kernel version to 4.14 7 | shell: 8 | cmd: 'FORCEMACHINE=TI_AM335x_BeagleBoneBlack /opt/scripts/tools/update_kernel.sh --lts-4_14 --ti-kernel' 9 | when: ('"4.14" not in kernel_version.stdout') 10 | 11 | - name: Replicape - Remove kernel 4.19 12 | apt: 13 | name: linux-image-4.19.94-ti-r57 14 | state: absent 15 | 16 | - name: Replicape - clone klipper from the master repository 17 | git: 18 | repo: https://github.com/KevinOConnor/klipper 19 | version: master 20 | dest: '{{ klipper_home }}' 21 | update: yes 22 | clone: yes 23 | depth: 1 24 | 25 | - name: Replicape - add debian user to tty group 26 | user: 27 | name: debian 28 | groups: tty 29 | append: yes 30 | 31 | - name: Replicape - install pru gcc 32 | apt: 33 | name: gcc-pru 34 | state: latest 35 | 36 | - name: Replicape - adjust ownership of klipper source 37 | file: 38 | path: "{{ klipper_home }}" 39 | owner: debian 40 | group: debian 41 | recurse: yes 42 | 43 | - name: Replicape - give debian user the klipper service permissions 44 | lineinfile: 45 | path: /etc/sudoers 46 | state: present 47 | line: "debian ALL=NOPASSWD: ALL" 48 | 49 | - name: Replicape - remove sudoers group authorization 50 | lineinfile: 51 | path: /etc/sudoers 52 | line: "%sudo ALL=(ALL:ALL) ALL" 53 | state: absent 54 | 55 | - name: Replicape - remove references to avr tooling 56 | lineinfile: 57 | regex: avr 58 | path: "{{ klipper_home }}/scripts/{{ item }}" 59 | state: absent 60 | with_items: 61 | - install-debian.sh 62 | - install-octopi.sh 63 | - install-ubuntu-18.04.sh 64 | 65 | - name: Replicape - Remove stm32 compiler and libs 66 | lineinfile: 67 | regex: "arm-none" 68 | path: "{{ klipper_home }}/scripts/{{ item }}" 69 | state: absent 70 | with_items: 71 | - install-debian.sh 72 | 73 | - name: Replicape - install Klipper with the install scripts 74 | shell: "export USER=debian; {{ klipper_home }}/scripts/install-beaglebone.sh" 75 | args: 76 | chdir: "{{ klipper_home }}" 77 | become: true 78 | become_user: debian 79 | 80 | - name: Replicape - Stop klipper. The install script starts it. 81 | systemd: 82 | name: klipper.service 83 | state: stopped 84 | 85 | - name: Replicape - Stop klipper_pru. It is hogging the pts. 86 | systemd: 87 | name: klipper_pru.service 88 | state: stopped 89 | 90 | - name: Replicape - compile binary blobs for klippy 91 | shell: 92 | cmd: "cd {{ klipper_home }} ; cp {{ item }} .config ; make flash" 93 | with_items: 94 | - "{{ role_path }}/files/pru_config" 95 | - "{{ role_path }}/files/replicape_linux_config" 96 | 97 | - name: Replicape - create klipper config file 98 | copy: 99 | src: "{{ klipper_home }}/config/generic-replicape.cfg" 100 | dest: /home/debian/printer.cfg 101 | owner: debian 102 | group: debian 103 | remote_src: yes 104 | force: no 105 | 106 | - name: Replicape - determine if config is the default OctoPrint config or not 107 | lineinfile: 108 | path: /home/debian/.octoprint/config.yaml 109 | line: 'firstRun: true' 110 | state: present 111 | check_mode: yes 112 | register: replace_default_octoprint_config 113 | 114 | - name: Replicape - place Klipper-friendly config for octoprint in place 115 | copy: 116 | src: "{{ role_path }}/files/octoprint_config.yaml" 117 | dest: /home/debian/.octoprint/config.yaml 118 | owner: debian 119 | group: debian 120 | remote_src: yes 121 | force: no 122 | 123 | - name: Replicape - place Klipper-service files in place 124 | copy: 125 | src: "{{ role_path }}/files/octoprint_replicape.service" 126 | dest: /etc/systemd/system/ 127 | owner: debian 128 | group: debian 129 | 130 | - name: Replicape - move the init.d/klipper_pru file 131 | shell: mv /etc/init.d/klipper_pru /etc/systemd/system/klipper_pru 132 | 133 | - name: Replicape - copy klipper_pru service related files 134 | copy: 135 | src: "{{ role_path }}/files/{{ item }}" 136 | dest: "/etc/systemd/system/{{ item }}" 137 | remote_src: yes 138 | with_items: 139 | - klipper.service 140 | - klipper_pru.service 141 | - remoteproc1.path 142 | 143 | - name: Replicape - enable PRU service on boot 144 | systemd: 145 | name: remoteproc1.path 146 | enabled: yes 147 | daemon_reload: yes 148 | 149 | - name: Replicape - disable power button causing a shutdown (Z1 endstop) 150 | lineinfile: 151 | path: /etc/systemd/logind.conf 152 | line: HandlePowerKey=ignore 153 | insertafter: #HandlePowerKey 154 | state: present 155 | 156 | - name: Replicape - replace UIO with rproc kernel overlays 157 | shell: 158 | cmd: "sed -i 's\\#uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-19-TI-00A0.dtbo\\uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-19-TI-00A0.dtbo\\' /boot/uEnv.txt" 159 | 160 | - name: Replicape - enable rproc overlay 161 | lineinfile: 162 | line: uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-14-TI-00A0.dtbo 163 | insertbefore: enable_uboot_cape_universal=1 164 | state: present 165 | path: /boot/uEnv.txt 166 | 167 | - name: Replicape - Install KIAUH 168 | git: 169 | repo: https://github.com/th33xitus/kiauh.git 170 | dest: '{{ klipper_home }}/../kiauh' 171 | update: yes 172 | clone: yes 173 | 174 | - name: Replicape - Update KIAUH to call the right install script 175 | replace: 176 | path: '{{ klipper_home }}/../kiauh/scripts/{{ item }}' 177 | regexp: install-octopi\.sh 178 | after: install-beaglebone.sh 179 | with_items: 180 | - update.sh 181 | - install_klipper.sh 182 | -------------------------------------------------------------------------------- /roles/install_klipper/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | klipper_home: /home/debian/klipper 3 | -------------------------------------------------------------------------------- /roles/install_klipperscreen/files/KlipperScreen.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelligent-agent/Refactor/c54a15a75e3530493f477c5ed15d3f2b2ce76405/roles/install_klipperscreen/files/KlipperScreen.conf -------------------------------------------------------------------------------- /roles/install_klipperscreen/files/KlipperScreen.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=a Klipper GUI for touch screens 3 | After=moonraker.service 4 | StartLimitIntervalSec=120 5 | StartLimitBurst=3 6 | 7 | [Service] 8 | Type=simple 9 | Restart=always 10 | RestartSec=1 11 | User=debian 12 | Environment="GDK_BACKEND=wayland" 13 | Environment="XDG_RUNTIME_DIR=/run/user/1000" 14 | Environment=KLIPPERSCREEN_CONFIG=/home/debian/printer_data/config/KlipperScreen.conf 15 | Environment=KLIPPERSCREEN_LOG=/var/log/klipper_logs/KlipperScreen.log 16 | WorkingDirectory=/home/debian/KlipperScreen 17 | ExecStart=/home/debian/.KlipperScreen-env/bin/python /home/debian/KlipperScreen/screen.py -c ${KLIPPERSCREEN_CONFIG} -l ${KLIPPERSCREEN_LOG} 18 | 19 | [Install] 20 | WantedBy=multi-user.target 21 | -------------------------------------------------------------------------------- /roles/install_klipperscreen/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: install_moonraker } -------------------------------------------------------------------------------- /roles/install_klipperscreen/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install KlipperScreen 3 | include: recore.yml 4 | when: platform == 'recore' 5 | -------------------------------------------------------------------------------- /roles/install_klipperscreen/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install packages 3 | apt: 4 | name: 5 | - libgirepository1.0-dev 6 | - libcairo2-dev 7 | - at-spi2-core 8 | - libdbus-1-3 9 | - libdbus-1-dev 10 | state: present 11 | 12 | - name: Recore - clone KlipperScreen from the master repository 13 | git: 14 | repo: https://github.com/jordanruthe/KlipperScreen 15 | version: master 16 | dest: /home/debian/KlipperScreen 17 | clone: yes 18 | become: yes 19 | become_user: debian 20 | 21 | - name: Recore - Install KlipperScreen 22 | shell: | 23 | /home/debian/KlipperScreen/scripts/KlipperScreen-install.sh 24 | become: yes 25 | become_user: debian 26 | 27 | - name: Recore - install config file 28 | copy: 29 | src: KlipperScreen.conf 30 | dest: /home/debian/printer_data/config 31 | owner: debian 32 | group: debian 33 | mode: 0755 34 | 35 | - name: Recore - Enable KlipperScreen 36 | systemd: 37 | name: KlipperScreen.service 38 | enabled: yes 39 | 40 | - name: Recore - Add debian to netdev 41 | user: 42 | name: debian 43 | groups: netdev 44 | append: yes 45 | -------------------------------------------------------------------------------- /roles/install_mainsail/files/common_vars.conf: -------------------------------------------------------------------------------- 1 | map $http_upgrade $connection_upgrade { 2 | default upgrade; 3 | '' close; 4 | } 5 | -------------------------------------------------------------------------------- /roles/install_mainsail/files/mainsail: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | 4 | access_log /var/log/nginx/mainsail-access.log; 5 | error_log /var/log/nginx/mainsail-error.log; 6 | 7 | # disable this section on smaller hardware like a pi zero 8 | gzip on; 9 | gzip_vary on; 10 | gzip_proxied any; 11 | gzip_proxied expired no-cache no-store private auth; 12 | gzip_comp_level 4; 13 | gzip_buffers 16 8k; 14 | gzip_http_version 1.1; 15 | gzip_types text/plain text/css text/xml text/javascript application/javascript application/x-javascript application/json application/xml; 16 | 17 | # web_path from mainsail static files 18 | root /home/debian/mainsail; 19 | 20 | index index.html; 21 | server_name _; 22 | 23 | # disable max upload size checks 24 | client_max_body_size 0; 25 | 26 | # disable proxy request buffering 27 | proxy_request_buffering off; 28 | 29 | location / { 30 | try_files $uri $uri/ /index.html; 31 | } 32 | 33 | location = /index.html { 34 | add_header Cache-Control "no-store, no-cache, must-revalidate"; 35 | } 36 | 37 | location /websocket { 38 | proxy_pass http://apiserver/websocket; 39 | proxy_http_version 1.1; 40 | proxy_set_header Upgrade $http_upgrade; 41 | proxy_set_header Connection $connection_upgrade; 42 | proxy_set_header Host $http_host; 43 | proxy_set_header X-Real-IP $remote_addr; 44 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 45 | proxy_read_timeout 86400; 46 | } 47 | 48 | location ~ ^/(printer|api|access|machine|server)/ { 49 | proxy_pass http://apiserver$request_uri; 50 | proxy_set_header Host $http_host; 51 | proxy_set_header X-Real-IP $remote_addr; 52 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 53 | proxy_set_header X-Scheme $scheme; 54 | } 55 | 56 | location /webcam/ { 57 | proxy_pass http://mjpgstreamer1/; 58 | } 59 | 60 | location /webcam2/ { 61 | proxy_pass http://mjpgstreamer2/; 62 | } 63 | 64 | location /webcam3/ { 65 | proxy_pass http://mjpgstreamer3/; 66 | } 67 | 68 | location /webcam4/ { 69 | proxy_pass http://mjpgstreamer4/; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /roles/install_mainsail/files/mainsail.cfg: -------------------------------------------------------------------------------- 1 | [pause_resume] 2 | 3 | [display_status] 4 | 5 | [virtual_sdcard] 6 | path: /home/debian/printer_data/gcodes 7 | 8 | [gcode_macro CANCEL_PRINT] 9 | description: Cancel the actual running print 10 | rename_existing: CANCEL_PRINT_BASE 11 | variable_park: True 12 | gcode: 13 | ## Move head and retract only if not already in the pause state and park set to true 14 | {% if printer.pause_resume.is_paused|lower == 'false' and park|lower == 'true'%} 15 | _TOOLHEAD_PARK_PAUSE_CANCEL 16 | {% endif %} 17 | TURN_OFF_HEATERS 18 | CANCEL_PRINT_BASE 19 | 20 | 21 | [gcode_macro pause] 22 | description: Pause the actual running print 23 | rename_existing: PAUSE_BASE 24 | # change this if you need more or less extrusion 25 | variable_extrude: 4.5 26 | gcode: 27 | ##### read E from pause macro ##### 28 | {% set E = printer["gcode_macro PAUSE"].extrude|float %} 29 | ##### set park positon for x and y ##### 30 | # default is your max posion from your printer.cfg 31 | {% set x_park = printer.toolhead.axis_maximum.x|float / 2 %} 32 | {% set y_park = printer.toolhead.axis_minimum.y|float + 5.0 %} 33 | ##### calculate save lift position ##### 34 | {% set max_z = printer.toolhead.axis_maximum.z|float %} 35 | {% set act_z = printer.toolhead.position.z|float %} 36 | {% if act_z < (max_z - 2.0) %} 37 | {% set z_safe = 2.0 %} 38 | {% else %} 39 | {% set z_safe = max_z - act_z %} 40 | {% endif %} 41 | ##### end of definitions ##### 42 | PAUSE_BASE 43 | G91 44 | {% if printer.extruder.can_extrude|lower == 'true' %} 45 | G1 E-{E} F2100 46 | {% else %} 47 | {action_respond_info("Extruder not hot enough")} 48 | {% endif %} 49 | {% if "xyz" in printer.toolhead.homed_axes %} 50 | G1 Z{z_safe} F900 51 | G90 52 | G1 X{x_park} Y{y_park} F6000 53 | {% else %} 54 | {action_respond_info("Printer not homed")} 55 | {% endif %} 56 | 57 | [gcode_macro RESUME] 58 | description: Resume the actual running print 59 | rename_existing: RESUME_BASE 60 | gcode: 61 | ##### read E from pause macro ##### 62 | {% set E = printer["gcode_macro PAUSE"].extrude|float %} 63 | #### get VELOCITY parameter if specified #### 64 | {% if 'VELOCITY' in params|upper %} 65 | {% set get_params = ('VELOCITY=' + params.VELOCITY) %} 66 | {%else %} 67 | {% set get_params = "" %} 68 | {% endif %} 69 | ##### end of definitions ##### 70 | {% if printer.extruder.can_extrude|lower == 'true' %} 71 | G91 72 | G1 E{E} F2100 73 | {% else %} 74 | {action_respond_info("Extruder not hot enough")} 75 | {% endif %} 76 | RESUME_BASE {get_params} 77 | -------------------------------------------------------------------------------- /roles/install_mainsail/files/upstreams.conf: -------------------------------------------------------------------------------- 1 | upstream apiserver { 2 | ip_hash; 3 | server 127.0.0.1:7125; 4 | } 5 | 6 | upstream mjpgstreamer1 { 7 | ip_hash; 8 | server 127.0.0.1:8080; 9 | } 10 | 11 | upstream mjpgstreamer2 { 12 | ip_hash; 13 | server 127.0.0.1:8081; 14 | } 15 | 16 | upstream mjpgstreamer3 { 17 | ip_hash; 18 | server 127.0.0.1:8082; 19 | } 20 | 21 | upstream mjpgstreamer4 { 22 | ip_hash; 23 | server 127.0.0.1:8083; 24 | } 25 | -------------------------------------------------------------------------------- /roles/install_mainsail/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: install_klipper } 4 | - { role: install_moonraker } 5 | - { role: linux_preparation } -------------------------------------------------------------------------------- /roles/install_mainsail/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install OctoPrint 3 | include: recore.yml 4 | when: platform == 'recore' 5 | -------------------------------------------------------------------------------- /roles/install_mainsail/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install nginx 3 | apt: 4 | name: 5 | - nginx 6 | state: present 7 | 8 | - name: Recore - Install upstream.conf 9 | copy: 10 | src: upstreams.conf 11 | dest: /etc/nginx/conf.d/ 12 | mode: 0700 13 | 14 | - name: Recore - Install common files 15 | copy: 16 | src: common_vars.conf 17 | dest: /etc/nginx/conf.d/ 18 | mode: 0700 19 | 20 | - name: Recore - Install mainsail config 21 | copy: 22 | src: mainsail 23 | dest: /etc/nginx/sites-available 24 | mode: 0700 25 | 26 | - name: Recore - Create mainsail dir 27 | file: 28 | path: /home/debian/mainsail 29 | state: directory 30 | mode: '0755' 31 | 32 | - name: Recore - Remove default nginx config 33 | file: 34 | path: /etc/nginx/sites-enabled/default 35 | state: absent 36 | 37 | - name: Recore - Symlink mainsail nginx config 38 | file: 39 | path: /etc/nginx/sites-enabled/default 40 | src: /etc/nginx/sites-available/mainsail 41 | dest: /etc/nginx/sites-enabled/mainsail 42 | state: link 43 | 44 | - name: Recore - Download mainsail 45 | unarchive: 46 | src: https://github.com/intelligent-agent/mainsail/releases/latest/download/mainsail.zip 47 | dest: /home/debian/mainsail 48 | remote_src: yes 49 | 50 | - name: Recore - Add USB disk rule 51 | copy: 52 | dest: /etc/udev/rules.d/60-usb-disk.rules 53 | content: | 54 | ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ATTR{partition}=="1", RUN{program}+="/usr/bin/systemd-mount -o ro --no-block --automount=yes --collect $devnode /home/debian/printer_data/gcodes/usb" 55 | 56 | - name: Recore - Enable nginx 57 | systemd: 58 | name: nginx.service 59 | enabled: yes 60 | 61 | - name: Recore - copy mainsail.cfg 62 | copy: 63 | src: mainsail.cfg 64 | dest: /home/debian/printer_data/config 65 | owner: debian 66 | group: debian 67 | 68 | - name: Recore - Create gcode_files dir 69 | file: 70 | path: /home/debian/printer_data/gcodes 71 | state: directory 72 | owner: debian 73 | group: debian 74 | mode: '0777' 75 | -------------------------------------------------------------------------------- /roles/install_moonraker/files/moonraker.conf: -------------------------------------------------------------------------------- 1 | [server] 2 | host: 0.0.0.0 3 | port: 7125 4 | 5 | # Make sure the klippy_uds_address is correct. It is initialized 6 | # to the default address. 7 | klippy_uds_address: /tmp/klippy_uds 8 | 9 | [authorization] 10 | cors_domains: 11 | https://my.mainsail.xyz 12 | http://my.mainsail.xyz 13 | http://*.local 14 | http://*.lan 15 | trusted_clients: 16 | 10.0.0.0/8 17 | 127.0.0.0/8 18 | 169.254.0.0/16 19 | 172.16.0.0/12 20 | 192.168.0.0/16 21 | FE80::/10 22 | ::1/128 23 | 24 | # enables partial support of Octoprint API 25 | [octoprint_compat] 26 | 27 | # enables moonraker to track and store print history. 28 | [history] 29 | 30 | # this enables moonraker's update manager 31 | [update_manager] 32 | enable_system_updates: False 33 | 34 | #[update_manager mainsail] 35 | #type: web 36 | #repo: intelligent-agent/mainsail 37 | #path: ~/mainsail 38 | 39 | [update_manager KlipperScreen] 40 | type: git_repo 41 | path: ~/KlipperScreen 42 | origin: https://github.com/jordanruthe/KlipperScreen.git 43 | env: ~/.KlipperScreen-env/bin/python 44 | requirements: scripts/KlipperScreen-requirements.txt 45 | install_script: scripts/KlipperScreen-install.sh 46 | managed_services: KlipperScreen 47 | 48 | [file_manager] 49 | 50 | [machine] 51 | provider: systemd_cli 52 | 53 | [recore] 54 | -------------------------------------------------------------------------------- /roles/install_moonraker/files/moonraker.service: -------------------------------------------------------------------------------- 1 | # systemd service file for moonraker 2 | [Unit] 3 | Description=API Server for Klipper SV1 4 | Requires=network-online.target 5 | After=network-online.target 6 | 7 | [Install] 8 | WantedBy=multi-user.target 9 | 10 | [Service] 11 | Type=simple 12 | User=debian 13 | SupplementaryGroups=moonraker-admin 14 | RemainAfterExit=yes 15 | WorkingDirectory=/home/debian/moonraker 16 | EnvironmentFile=/home/debian/printer_data/systemd/moonraker.env 17 | ExecStart=/home/debian/moonraker-env/bin/python $MOONRAKER_ARGS 18 | Restart=always 19 | RestartSec=10 20 | -------------------------------------------------------------------------------- /roles/install_moonraker/files/recore.py: -------------------------------------------------------------------------------- 1 | # Machine manipulation request handlers 2 | # 3 | # Copyright (C) 2020 Eric Callahan 4 | # Copyright (C) 2022 Elias Bakken 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | 8 | from __future__ import annotations 9 | import logging 10 | import asyncio 11 | 12 | # Annotation imports 13 | from typing import ( 14 | TYPE_CHECKING, 15 | Any, 16 | Dict, 17 | Optional 18 | ) 19 | 20 | if TYPE_CHECKING: 21 | from confighelper import ConfigHelper 22 | from websockets import WebRequest 23 | from .shell_command import ShellCommandFactory as SCMDComp 24 | 25 | class Recore: 26 | def __init__(self, config: ConfigHelper) -> None: 27 | self.server = config.get_server() 28 | 29 | self.server.register_endpoint( 30 | "/recore/enable_ssh", ['POST'], self._handle_enable_ssh_request) 31 | self.server.register_endpoint( 32 | "/recore/set_boot_media", ['POST'], self._handle_boot_media_request) 33 | self.server.register_endpoint( 34 | "/recore/state", ['GET'], self._handle_recore_state_request) 35 | 36 | shell_cmd: SCMDComp = self.server.load_component( 37 | config, 'shell_command') 38 | get_boot_media_bin = "/usr/local/bin/get-boot-media" 39 | self.get_boot_media_cmd = shell_cmd.build_shell_command( 40 | get_boot_media_bin) 41 | is_ssh_enabled_bin = "/usr/local/bin/is-ssh-enabled" 42 | self.is_ssh_enabled_cmd = shell_cmd.build_shell_command( 43 | is_ssh_enabled_bin) 44 | self.init_evt = asyncio.Event() 45 | 46 | async def wait_for_init( 47 | self, timeout: Optional[float] = None 48 | ) -> None: 49 | try: 50 | await asyncio.wait_for(self.init_evt.wait(), timeout) 51 | except asyncio.TimeoutError: 52 | pass 53 | 54 | async def component_init(self) -> None: 55 | self.init_evt.set() 56 | 57 | async def _exec_sudo_command(self, command: str): 58 | machine: Machine = self.server.lookup_component("machine") 59 | return await machine.exec_sudo_command(command, timeout=5) 60 | 61 | async def _handle_enable_ssh_request(self, web_request: WebRequest) -> str: 62 | enabled = web_request.get("value") 63 | await self._exec_sudo_command( 64 | f"/usr/local/bin/set-ssh-access {enabled}") 65 | return "ok" 66 | 67 | async def _handle_boot_media_request(self, web_request: WebRequest) -> str: 68 | media = web_request.get("value") 69 | await self._exec_sudo_command(f"/usr/local/bin/set-boot-media {media}") 70 | return "ok" 71 | 72 | async def _handle_recore_state_request(self, web_request: WebRequest 73 | ) -> Dict[str, Any]: 74 | boot_media = await self._get_boot_media() 75 | ssh_enabled = await self._get_ssh_enabled() 76 | recore_state = { 77 | "ssh_enabled": ssh_enabled, 78 | "boot_media": boot_media 79 | } 80 | return {"recore_state": recore_state} 81 | 82 | async def _get_boot_media(self) -> str: 83 | shell_cmd: SCMDComp = self.server.lookup_component('shell_command') 84 | try: 85 | resp = await self.get_boot_media_cmd.run_with_response( 86 | log_complete=False) 87 | except shell_cmd.error: 88 | return "Error: setting boot media failed" 89 | if resp: 90 | return resp.strip() 91 | return "unknown" 92 | 93 | async def _get_ssh_enabled(self) -> str: 94 | shell_cmd: SCMDComp = self.server.lookup_component('shell_command') 95 | try: 96 | resp = await self.is_ssh_enabled_cmd.run_with_response( 97 | log_complete=False) 98 | except shell_cmd.error: 99 | return "Error: setting SSH access failed" 100 | if resp: 101 | return resp.strip() 102 | return "unknown" 103 | 104 | def load_component(config: ConfigHelper) -> Recore: 105 | return Recore(config) 106 | -------------------------------------------------------------------------------- /roles/install_moonraker/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: linux_preparation } -------------------------------------------------------------------------------- /roles/install_moonraker/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install Moonraker 3 | include: recore.yml 4 | when: platform == 'recore' 5 | -------------------------------------------------------------------------------- /roles/install_moonraker/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install packages 3 | apt: 4 | name: 5 | - unzip 6 | state: present 7 | 8 | - name: Recore - clone klipper from the master repository 9 | git: 10 | repo: https://github.com/Arksine/moonraker 11 | version: master 12 | dest: /home/debian/moonraker 13 | update: yes 14 | clone: yes 15 | become: yes 16 | become_user: debian 17 | 18 | - name: Recore - Install moonraker 19 | shell: | 20 | /home/debian/moonraker/scripts/install-moonraker.sh 21 | /home/debian/moonraker/scripts/set-policykit-rules.sh 22 | become: yes 23 | become_user: debian 24 | 25 | - name: Recore - Create print config folder 26 | file: 27 | path: /home/debian/printer_data/config/ 28 | state: directory 29 | owner: debian 30 | group: debian 31 | 32 | - name: Recore - copy config 33 | copy: 34 | src: moonraker.conf 35 | dest: /home/debian/printer_data/config/ 36 | owner: debian 37 | group: debian 38 | 39 | - name: Recore - create folder for klipper logs in /var/log 40 | file: 41 | path: /var/log/klipper_logs 42 | state: directory 43 | mode: 0755 44 | owner: debian 45 | group: debian 46 | 47 | - name: Recore - remove logs folder 48 | file: 49 | path: /home/debian/printer_data/logs 50 | state: absent 51 | 52 | - name: Recore - Symlink logs to /var/log 53 | file: 54 | src: /var/log/klipper_logs 55 | dest: /home/debian/printer_data/logs 56 | owner: debian 57 | group: debian 58 | state: link 59 | 60 | - name: Recore - copy service file 61 | copy: 62 | src: moonraker.service 63 | dest: /etc/systemd/system 64 | mode: 0644 65 | 66 | - name: Recore - Create moonraker_components 67 | file: 68 | path: /home/debian/moonraker_components 69 | state: directory 70 | owner: debian 71 | group: debian 72 | mode: '0755' 73 | 74 | - name: Recore - Add recore moonraker component 75 | copy: 76 | src: recore.py 77 | dest: /home/debian/moonraker_components 78 | owner: debian 79 | group: debian 80 | 81 | - name: Recore - Symlink recore moonraker component 82 | file: 83 | src: /home/debian/moonraker_components/recore.py 84 | dest: /home/debian/moonraker/moonraker/components/recore.py 85 | owner: debian 86 | group: debian 87 | state: link 88 | -------------------------------------------------------------------------------- /roles/install_octoprint/files/config_recore.yaml: -------------------------------------------------------------------------------- 1 | appearance: 2 | name: Recore 3 | folder: 4 | uploads: /home/debian/printer_data/gcodes 5 | plugins: 6 | softwareupdate: 7 | _config_version: 9 8 | checks: 9 | octoprint: 10 | checkout_folder: /home/debian/OctoPrint 11 | prerelease: false 12 | klipper: 13 | configuration: 14 | config_path: ~/printer_data/config 15 | logpath: /var/log/klipper_logs/klippy.log 16 | toptemp: 17 | tool0: 18 | show: false 19 | bed: 20 | show: false 21 | customMon: 22 | cu2: 23 | cmd: (?:B):.*? Board:([^ ]+) 24 | colorIcons: false 25 | decSep: . 26 | graphSettings: 27 | color: '#000000' 28 | height: 50 29 | opa: 0.2 30 | show: false 31 | width: 1 32 | hideOnNoTarget: false 33 | icon: fas fa-thermometer-full 34 | interval: 25 35 | isTemp: true 36 | label: 'Input:' 37 | name: Board 38 | noDigits: '1' 39 | postCalc: null 40 | show: true 41 | showPopover: true 42 | showUnit: true 43 | type: gcIn 44 | unit: '' 45 | updated: 1628968382280 46 | waitForPrint: false 47 | width: 0 48 | cu3: 49 | cmd: (?:B):.*? Voltage:([^ ]+) 50 | colorChangeLevel: 60 51 | colorIcons: false 52 | decSep: . 53 | graphSettings: 54 | color: '#000000' 55 | height: 50 56 | opa: 0.2 57 | show: false 58 | width: 1 59 | hideOnNoTarget: false 60 | icon: fas fa-bolt 61 | interval: 25 62 | isTemp: false 63 | label: Voltage 64 | name: Voltage 65 | noDigits: '1' 66 | postCalc: null 67 | show: true 68 | showPopover: true 69 | showUnit: true 70 | type: gcIn 71 | unit: V 72 | updated: 1628968382280 73 | waitForPrint: false 74 | width: 0 75 | cu4: 76 | cmd: (?:B):.*? Current:([^ ]+) 77 | colorChangeLevel: 60 78 | colorIcons: false 79 | decSep: . 80 | graphSettings: 81 | color: '#000000' 82 | height: 50 83 | opa: 0.2 84 | show: false 85 | width: 1 86 | hideOnNoTarget: false 87 | icon: fas fa-battery-full 88 | interval: 25 89 | isTemp: false 90 | label: 'Current: ' 91 | name: Current 92 | noDigits: '1' 93 | postCalc: null 94 | show: true 95 | showPopover: true 96 | showUnit: true 97 | type: gcIn 98 | unit: A 99 | updated: 1628968382280 100 | waitForPrint: false 101 | width: 0 102 | firstRun: false 103 | sortOrder: 104 | - bed 105 | - tool0 106 | - cu2 107 | - cu3 108 | - cu4 109 | server: 110 | firstRun: true 111 | commands: 112 | serverRestartCommand: sudo systemctl restart octoprint.service 113 | systemRestartCommand: sudo reboot 114 | systemShutdownCommand: sudo shutdown -h now 115 | webcam: 116 | stream: http://recore.local:8080/?action=stream 117 | snapshot: http://recore.local:8080/?action=snapshot 118 | ffmpeg: /usr/bin/avconv 119 | serial: 120 | additionalPorts: 121 | - /tmp/printer 122 | port: /tmp/printer 123 | disconnectOnErrors: false 124 | -------------------------------------------------------------------------------- /roles/install_octoprint/files/config_replicape.yaml: -------------------------------------------------------------------------------- 1 | appearance: 2 | name: Replicape 3 | folder: 4 | uploads: /usr/share/models 5 | plugins: 6 | softwareupdate: 7 | _config_version: 9 8 | checks: 9 | octoprint: 10 | checkout_folder: /home/debian/OctoPrint 11 | prerelease: false 12 | server: 13 | firstRun: true 14 | commands: 15 | serverRestartCommand: sudo systemctl restart octoprint.service 16 | systemRestartCommand: sudo reboot 17 | systemShutdownCommand: sudo shutdown -h now 18 | webcam: 19 | stream: http://replicape.local:8080/?action=stream 20 | snapshot: http://replicape.local:8080/?action=snapshot 21 | ffmpeg: /usr/bin/avconv 22 | serial: 23 | additionalPorts: 24 | - /tmp/printer 25 | port: /tmp/printer 26 | disconnectOnErrors: false 27 | -------------------------------------------------------------------------------- /roles/install_octoprint/files/enable-octoprint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | systemctl disable nginx 4 | systemctl stop nginx 5 | 6 | systemctl disable moonraker 7 | systemctl stop moonraker 8 | 9 | systemctl enable octoprint 10 | systemctl start octoprint 11 | 12 | systemctl enable nftables 13 | systemctl start nftables 14 | -------------------------------------------------------------------------------- /roles/install_octoprint/files/nftables.conf: -------------------------------------------------------------------------------- 1 | #!/usr/sbin/nft -f 2 | 3 | flush ruleset 4 | 5 | table ip nat { 6 | chain prerouting { 7 | type nat hook prerouting priority -101; 8 | tcp dport http redirect to :5000 9 | } 10 | chain postrouting { 11 | type nat hook postrouting priority 100; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /roles/install_octoprint/files/octoprint.service: -------------------------------------------------------------------------------- 1 | #Systemd service file for OctoPrint 2 | [Unit] 3 | Description=OctoPrint 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=/home/debian/OctoPrint/venv/bin/octoprint serve 8 | Restart=always 9 | RestartSec=60 10 | User=debian 11 | 12 | [Install] 13 | WantedBy=klipper.service 14 | -------------------------------------------------------------------------------- /roles/install_octoprint/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: linux_preparation } -------------------------------------------------------------------------------- /roles/install_octoprint/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install OctoPrint 3 | include: recore.yml 4 | when: platform == 'recore' 5 | 6 | - name: Replicape - Install OctoPrint 7 | include: replicape.yml 8 | when: platform == 'replicape' 9 | -------------------------------------------------------------------------------- /roles/install_octoprint/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install packages 3 | apt: 4 | name: 5 | - nftables 6 | - python3.9 7 | - python3-pip 8 | - python3-dev 9 | - git 10 | - python-setuptools 11 | - gcc 12 | - pv 13 | state: present 14 | 15 | - name: Recore - verify python3-virtualenv is present 16 | pip: 17 | name: virtualenv 18 | executable: pip3 19 | 20 | - name: Recore - create nftables port forward from :80 to :5000 21 | copy: 22 | src: "{{ role_path }}/files/nftables.conf" 23 | dest: "/etc/nftables.conf" 24 | 25 | - name: Recore - Enable nftables 26 | service: 27 | name: nftables 28 | enabled: yes 29 | 30 | - name: create home octoprint folder 31 | file: 32 | path: /home/debian/.octoprint 33 | state: directory 34 | owner: debian 35 | group: debian 36 | 37 | - name: Recore - give debian permissions to python folders for updates 38 | file: 39 | path: '{{ item }}' 40 | group: debian 41 | owner: debian 42 | mode: 0755 43 | recurse: yes 44 | state: directory 45 | with_items: 46 | - '{{ octoprint_home }}/..' 47 | - /usr/local/lib/python3 48 | - /usr/local/bin 49 | 50 | - name: Recore - Make octoprint config folder 51 | file: 52 | path: "{{ octoprint_home}}/../.octoprint" 53 | state: directory 54 | owner: debian 55 | group: debian 56 | 57 | - name: Recore - Insert octoprint config 58 | copy: 59 | src: "{{ role_path }}/files/config_recore.yaml" 60 | dest: "{{ octoprint_home }}/../.octoprint/config.yaml" 61 | owner: debian 62 | group: debian 63 | force: no 64 | 65 | - name: Recore - Use pip to install OctoPrint 66 | pip: 67 | chdir: '{{ octoprint_home }}' 68 | virtualenv: '{{ octoprint_home }}/venv' 69 | virtualenv_python: python3.9 70 | state: latest 71 | name: git+https://github.com/foosel/OctoPrint.git 72 | become_user: debian 73 | 74 | - name: Recore - Have the upload folder ready 75 | file: 76 | path: /home/debian/printer_data/gcodes 77 | state: directory 78 | owner: debian 79 | group: debian 80 | mode: 0777 81 | 82 | - name: Recore - annotate OctoPrint port in services 83 | lineinfile: 84 | path: /etc/services 85 | line: octoprint 5000/tcp 86 | state: present 87 | 88 | - name: Recore - grant debian user sudo privileges for some commands 89 | blockinfile: 90 | path: /etc/sudoers.d/debian 91 | block: | 92 | %debian ALL=NOPASSWD: /bin/systemctl restart octoprint.service 93 | %debian ALL=NOPASSWD: /sbin/reboot 94 | %debian ALL=NOPASSWD: /sbin/shutdown -h now 95 | %debian ALL=NOPASSWD: /sbin/poweroff 96 | %debian ALL=NOPASSWD: /usr/local/bin/set-boot-media usb 97 | %debian ALL=NOPASSWD: /usr/local/bin/set-boot-media emmc 98 | %debian ALL=NOPASSWD: /usr/local/bin/flash-recore *.img.xz 99 | %debian ALL=NOPASSWD: /usr/local/bin/get-boot-media 100 | 101 | - name: Recore - install service file for OctoPrint 102 | copy: 103 | src: '{{ role_path }}/files/octoprint.service' 104 | dest: /etc/systemd/system/octoprint.service 105 | owner: root 106 | group: root 107 | mode: 0644 108 | 109 | - name: Recore - enable octoprint service 110 | service: 111 | name: octoprint 112 | enabled: yes 113 | 114 | - name: Recore - allow debian user access to relevant folders 115 | file: 116 | path: "{{ item }}" 117 | owner: debian 118 | group: debian 119 | state: directory 120 | recurse: yes 121 | with_items: 122 | - /usr/src/Refactor 123 | - /home/debian 124 | -------------------------------------------------------------------------------- /roles/install_octoprint/tasks/replicape.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Replicape - Install packages 3 | apt: 4 | name: 5 | - nftables 6 | - python3.7 7 | - python3-pip 8 | - python3-dev 9 | - git 10 | - python-setuptools 11 | state: present 12 | 13 | - name: Replicape - verify python3-virtualenv is present 14 | pip: 15 | name: virtualenv 16 | executable: pip3 17 | 18 | - name: Replicape - ensure the debian user exists 19 | user: 20 | name: debian 21 | comment: Default user for OctoPrint 22 | shell: /bin/bash 23 | groups: tty,dialout 24 | append: yes 25 | expires: -1 26 | home: /home/debian 27 | 28 | - name: Replicape - create nftables port forward from :80 to :5000 29 | copy: 30 | src: "{{ role_path }}/files/nftables.conf" 31 | dest: "/etc/nftables.conf" 32 | 33 | - name: Replicape - Enable nftables 34 | service: 35 | name: nftables 36 | enabled: yes 37 | 38 | - name: Replicape - create home octoprint folder 39 | file: 40 | path: /home/debian/.octoprint 41 | state: directory 42 | owner: debian 43 | group: debian 44 | 45 | - name: Replicape - give debian permissions to python folders for updates 46 | file: 47 | path: '{{ item }}' 48 | group: debian 49 | owner: debian 50 | mode: 0755 51 | recurse: yes 52 | state: directory 53 | with_items: 54 | - '{{ octoprint_home }}/..' 55 | - /usr/local/lib/python3.7 56 | - /usr/local/bin 57 | 58 | - name: Replicape - Make octoprint config folder 59 | file: 60 | path: "{{ octoprint_home}}/../.octoprint" 61 | state: directory 62 | owner: debian 63 | group: debian 64 | 65 | - name: Replicape - Insert octoprint config 66 | copy: 67 | src: "{{ role_path }}/files/config_replicape.yaml" 68 | dest: "{{ octoprint_home }}/../.octoprint/config.yaml" 69 | owner: debian 70 | group: debian 71 | force: no 72 | 73 | - name: Replicape - Use pip to install OctoPrint 74 | pip: 75 | chdir: '{{ octoprint_home }}' 76 | virtualenv: '{{ octoprint_home }}/venv' 77 | virtualenv_python: python3.7 78 | state: latest 79 | name: git+https://github.com/foosel/OctoPrint.git 80 | become_user: debian 81 | 82 | - name: Replicape - Have the upload folder ready 83 | file: 84 | path: /usr/share/models 85 | state: directory 86 | owner: debian 87 | group: debian 88 | mode: 0777 89 | 90 | - name: Replicape - make sure the sudoers.d/debian file exists 91 | file: 92 | path: /etc/sudoers.d/debian 93 | owner: root 94 | group: root 95 | state: touch 96 | 97 | - name: Replicape - grant debian user sudo privileges for some commands 98 | blockinfile: 99 | path: /etc/sudoers.d/debian 100 | block: | 101 | %debian ALL=NOPASSWD: /bin/systemctl restart octoprint.service 102 | %debian ALL=NOPASSWD: /sbin/reboot 103 | %debian ALL=NOPASSWD: /sbin/shutdown -h now 104 | %debian ALL=NOPASSWD: /sbin/poweroff 105 | 106 | - name: Replicape - install service file for OctoPrint 107 | copy: 108 | src: '{{ role_path }}/files/octoprint.service' 109 | dest: /lib/systemd/system/octoprint.service 110 | owner: root 111 | group: root 112 | mode: 0644 113 | 114 | - name: Replicape - enable octoprint service 115 | service: 116 | name: octoprint 117 | enabled: yes 118 | 119 | - name: Replicape - allow debian user access to relevant folders 120 | file: 121 | path: "{{ item }}" 122 | owner: debian 123 | group: debian 124 | state: directory 125 | recurse: yes 126 | with_items: 127 | - /usr/src/Refactor 128 | - /home/debian 129 | -------------------------------------------------------------------------------- /roles/install_octoprint/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | octoprint_home: /home/debian/OctoPrint 3 | -------------------------------------------------------------------------------- /roles/install_octoprint_klipper_plugins/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: linux_preparation } 4 | - { role: install_klipper } 5 | - { role: install_octoprint } -------------------------------------------------------------------------------- /roles/install_octoprint_klipper_plugins/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore, clone octoprint klipper plugin 3 | git: 4 | repo: https://github.com/thelastWallE/OctoprintKlipperPlugin.git 5 | dest: /usr/src/octoprint_klipper 6 | 7 | - name: Recore, Change ownership 8 | file: 9 | path: /usr/src/octoprint_klipper 10 | owner: debian 11 | group: debian 12 | state: directory 13 | recurse: yes 14 | 15 | - name: Recore, install octoprint klipper plugin in Octoprint virtual env 16 | shell: 17 | cmd: 'cd /usr/src/octoprint_klipper ; {{ octoprint_home }}/venv/bin/python setup.py clean install' 18 | become: yes 19 | become_user: debian 20 | 21 | - name: Recore, clone octoprint top temp plugin 22 | git: 23 | repo: https://github.com/LazeMSS/OctoPrint-TopTemp.git 24 | dest: /usr/src/octoprint_top_temp 25 | 26 | - name: Recore, Change ownership 27 | file: 28 | path: /usr/src/octoprint_top_temp 29 | owner: debian 30 | group: debian 31 | state: directory 32 | recurse: yes 33 | 34 | - name: Recore, install octoprint top temp plugin in Octoprint virtual env 35 | shell: 36 | cmd: 'cd /usr/src/octoprint_top_temp ; {{ octoprint_home }}/venv/bin/python setup.py clean install' 37 | become: yes 38 | become_user: debian 39 | 40 | - name: Recore, clone octoprint Refactor plugin 41 | git: 42 | repo: https://github.com/intelligent-agent/octoprint_refactor.git 43 | dest: /usr/src/octoprint_refactor 44 | version: main 45 | 46 | - name: Recore, Change ownership 47 | file: 48 | path: /usr/src/octoprint_refactor 49 | owner: debian 50 | group: debian 51 | state: directory 52 | recurse: yes 53 | 54 | - name: Recore, install octoprint refactor plugin in Octoprint virtual env 55 | shell: 56 | cmd: 'cd /usr/src/octoprint_refactor ; {{ octoprint_home }}/venv/bin/python setup.py clean install' 57 | become: yes 58 | become_user: debian 59 | -------------------------------------------------------------------------------- /roles/install_toggle/files/toggle-runfirst: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import configparser 4 | import yaml 5 | import secrets 6 | import string 7 | import hashlib 8 | import os 9 | import time 10 | 11 | def make_key(length): 12 | alphabet = string.ascii_letters + string.digits 13 | return ''.join(secrets.choice(alphabet) for i in range(length)) 14 | 15 | def hash_password(password): 16 | salt = get_salt() 17 | return hashlib.sha512((password + salt).encode()).hexdigest() 18 | 19 | def get_salt(): 20 | fname = '/home/debian/.octoprint/config.yaml' 21 | with open(fname, "r") as f_in: 22 | config = yaml.safe_load(f_in) 23 | salt = config.get("accessControl", {}).get("salt", make_key(32)) 24 | config.setdefault("accessControl", {})["salt"] = salt 25 | with open(fname, "w") as f_out: 26 | yaml.safe_dump(config, f_out, default_flow_style=False) 27 | return salt 28 | 29 | def get_password(): 30 | local = configparser.ConfigParser() 31 | local.read('/etc/toggle/local.cfg') 32 | return local.get("OctoPrint", 'password', fallback=make_key(10)) 33 | 34 | def update_toggle_config(password, apikey): 35 | local = configparser.ConfigParser() 36 | local["OctoPrint"] = { 37 | 'user': 'toggle', 38 | 'password': password, 39 | 'authentication': apikey 40 | } 41 | with open('/etc/toggle/local.cfg', 'w') as configfile: 42 | local.write(configfile) 43 | 44 | def update_user_config(password, fname): 45 | password_hash = hash_password(password) 46 | with open(fname, 'r') as f_in: 47 | users = yaml.safe_load(f_in) or {} 48 | toggle = users.get('toggle', {}) 49 | apikey = toggle.get('apikey', make_key(30)) 50 | toggle = { 51 | 'active': True, 52 | 'apikey': apikey, 53 | 'groups': ['users'], 54 | 'password': password_hash, 55 | 'permissions': [], 56 | 'roles': ['user'], 57 | 'settings': {} 58 | } 59 | users['toggle'] = toggle 60 | with open(fname, 'w') as f_out: 61 | yaml.safe_dump(users, f_out, default_flow_style=False) 62 | return apikey 63 | 64 | fname = '/home/debian/.octoprint/users.yaml' 65 | 66 | while True: 67 | if os.path.exists(fname): 68 | passwd = get_password() 69 | apikey = update_user_config(passwd, fname) 70 | update_toggle_config(passwd, apikey) 71 | os.system("systemctl disable toggle-runfirst") 72 | exit(0) 73 | else: 74 | time.sleep(1) 75 | -------------------------------------------------------------------------------- /roles/install_toggle/files/toggle-runfirst.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Allow Toggle to register access to OctoPrint 3 | Before=octoprint.service toggle.service 4 | 5 | [Service] 6 | Type=simple 7 | RemainAfterExit=yes 8 | ExecStart=/usr/lib/toggle-runfirst 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /roles/install_toggle/files/toggle.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=The Redeem/Replicape Graphical user interface 3 | After=octoprint.service sgx-startup.service 4 | Requires=octoprint.service sgx-startup.service 5 | 6 | [Service] 7 | Type=simple 8 | ExecStartPre=/bin/systemctl stop getty@tty1.service 9 | ExecStartPre=/bin/bash -c '/bin/echo 0 > /sys/class/graphics/fbcon/cursor_blink' 10 | ExecStart=/usr/local/toggle/bin/toggle 11 | ExecStopPost=/bin/systemctl start getty@tty1.service 12 | ExecStopPost=/bin/bash -c '/bin/echo 1 > /sys/class/graphics/fbcon/cursor_blink' 13 | 14 | [Install] 15 | WantedBy=basic.target 16 | -------------------------------------------------------------------------------- /roles/install_toggle/files/toggle_recore.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=3D-printer user interface 3 | After=weston.service 4 | Requires=weston.service 5 | StartLimitIntervalSec=5 6 | StartLimitBurst=3 7 | 8 | [Service] 9 | Environment="XDG_RUNTIME_DIR=/run/user/1000" 10 | Environment=MX_RC_FILE=/etc/toggle/styles/Plain/style.css 11 | ExecStart=/usr/local/bin/toggle 12 | Restart=on-failure 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /roles/install_toggle/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: linux_preparation } 4 | - { role: install_octoprint } 5 | - { role: install_weston } -------------------------------------------------------------------------------- /roles/install_toggle/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install Toggle 3 | include: recore.yml 4 | when: platform == 'recore' 5 | -------------------------------------------------------------------------------- /roles/install_toggle/tasks/pi.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dependencies 3 | apt: 4 | pkg: 5 | - gir1.2-clutter-1.0=1.26.0+dfsg-10.1 6 | - gir1.2-cogl-1.0=1.22.2-2.1 7 | - gir1.2-coglpango-1.0=1.22.2-2.1 8 | - gir1.2-mash-0.3-0=0.3.0-1 9 | - gir1.2-mx-2.0=1.99.4-1.1 10 | - libcairo2-dev 11 | - libclutter-1.0-0=1.26.0+dfsg-10.1 12 | - libclutter-1.0-common=1.26.0+dfsg-10.1 13 | - libclutter-imcontext-0.1-0=0.1.4-3.1 14 | - libclutter-imcontext-0.1-bin=0.1.4-3.1 15 | - libcluttergesture-0.0.2-0=0.0.2.1-7.2 16 | - libcogl-common=1.22.2-2.1 17 | - libcogl-pango20=1.22.2-2.1 18 | - libcogl-path20=1.22.2-2.1 19 | - libcogl20=1.22.2-2.1 20 | - libmash-0.3-0=0.3.0-1 21 | - libmx-2.0-0=1.99.4-1.1 22 | - libmx-bin=1.99.4-1.1 23 | - libmx-common=1.99.4-1.1 24 | - python3-networkmanager 25 | - python3-cairo 26 | - python3-gi-cairo 27 | - python3-tornado 28 | - python3-pip 29 | - python3-venv 30 | - python3-dbus 31 | - libdbus-1-dev 32 | - libglib2.0-dev 33 | state: present 34 | force: yes 35 | 36 | - name: clone toggle from git 37 | git: 38 | repo: https://github.com/intelligent-agent/toggle 39 | dest: '{{ toggle_home }}/src/toggle' 40 | version: dev 41 | depth: 1 42 | 43 | - name: copy toggle service file 44 | copy: 45 | src: '{{ role_path }}/files/toggle.service' 46 | dest: /lib/systemd/system/toggle.service 47 | 48 | - name: grant sudo to octo user for restarting toggle service 49 | lineinfile: 50 | path: /etc/sudoers.d/octo 51 | line: '%octo ALL=NOPASSWD: /bin/systemctl restart toggle.service' 52 | state: present 53 | 54 | - name: install pip3 dependencies 55 | pip: 56 | virtualenv: '{{ toggle_home }}' 57 | virtualenv_python: python3.6 58 | requirements: '{{ toggle_home }}/src/toggle/requirements.txt' 59 | 60 | - name: install pip3 dependencies 61 | pip: 62 | virtualenv: '{{ toggle_home }}' 63 | virtualenv_python: python3.6 64 | name: 65 | - gobject 66 | - PyGObject 67 | 68 | - name: clone pyconnman 69 | git: 70 | repo: https://github.com/liamw9534/pyconnman 71 | dest: '{{ toggle_home }}/src/pyconnman' 72 | depth: 1 73 | 74 | - name: install pyconnman in venv 75 | shell: 76 | cmd: 'cd {{ toggle_home }}/src/pyconnman ; ../../bin/python setup.py clean install' 77 | 78 | - name: install toggle in venv 79 | shell: 80 | cmd: 'cd {{ toggle_home }}/src/toggle ; {{ toggle_home }}/bin/pip install -e . -r requirements.txt ; {{ toggle_home }}/bin/python setup.py clean install' 81 | 82 | - name: make config directory 83 | file: 84 | path: /etc/toggle 85 | state: directory 86 | owner: octo 87 | group: octo 88 | 89 | - name: copy toggle configs 90 | copy: 91 | src: '{{ toggle_home }}/src/toggle/configs/' 92 | dest: /etc/toggle 93 | owner: octo 94 | group: octo 95 | 96 | - name: touch the local.cfg file 97 | file: 98 | path: /etc/toggle/local.cfg 99 | state: touch 100 | owner: octo 101 | group: octo 102 | 103 | - name: enable the toggle service 104 | service: 105 | name: toggle 106 | enabled: yes 107 | 108 | - name: clone octoprint toggle plugin from git 109 | git: 110 | repo: https://github.com/intelligent-agent/octoprint_toggle 111 | dest: /usr/src/octoprint_toggle 112 | 113 | - name: install octoprint toggle plugin in virtualenv 114 | shell: 115 | cmd: 'cd /usr/src/octoprint_toggle; {{ octoprint_home }}/venv/bin/python setup.py clean install' 116 | 117 | - name: install sudoers entry for toggle restart 118 | lineinfile: 119 | path: /etc/sudoers.d/octo 120 | line: '%octo ALL=NOPASSWD: /usr/bin/make -C /usr/src/toggle install' 121 | state: present 122 | 123 | - name: setup FB rotation in uEnv 124 | replace: 125 | regexp: "(cmdline=.*)" 126 | replace: "\\1 fbcon=rotate:1" 127 | path: /boot/uEnv.txt 128 | 129 | - name: enable toggle service 130 | service: 131 | name: toggle 132 | enabled: yes 133 | -------------------------------------------------------------------------------- /roles/install_toggle/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: add iagent feeds 3 | apt_key: 4 | url: http://feeds.iagent.no/debian/iagent.public.key 5 | state: present 6 | 7 | - name: Add specified repository into sources list 8 | apt_repository: 9 | repo: deb [arch=arm64] http://feeds.iagent.no/debian buster main 10 | state: present 11 | 12 | - name: update package list 13 | apt: 14 | update_cache: yes 15 | 16 | - name: install dependencies 17 | apt: 18 | pkg: 19 | - python3-setuptools 20 | - python3-gi 21 | - python3-pip 22 | - python3-dev 23 | - libdbus-1-dev 24 | - libglib2.0-dev 25 | - python3-cairo 26 | - python3-gi-cairo 27 | - python3-networkmanager 28 | - python3-tornado 29 | - python3-requests 30 | - gir1.2-mx-2.0-0 31 | - gir1.2-mash-0.3-0 32 | state: present 33 | force: yes 34 | 35 | - name: clone toggle from git 36 | git: 37 | repo: https://github.com/intelligent-agent/toggle 38 | dest: '{{ toggle_home }}' 39 | depth: 1 40 | 41 | - name: copy toggle service file 42 | copy: 43 | src: '{{ role_path }}/files/toggle_recore.service' 44 | dest: /etc/systemd/system/toggle.service 45 | 46 | - name: grant sudo to debian user for restarting toggle service 47 | lineinfile: 48 | path: /etc/sudoers.d/debian 49 | line: '%debian ALL=NOPASSWD: /bin/systemctl restart toggle.service' 50 | state: present 51 | 52 | - name: Use pip to install toggle 53 | pip: 54 | chdir: '{{ toggle_home }}' 55 | requirements: '{{ toggle_home }}/requirements.txt' 56 | executable: pip3 57 | 58 | - name: Use pip to install toggle data files 59 | shell: 60 | chdir: "{{ toggle_home }}" 61 | cmd: "python3 setup.py install_data" 62 | 63 | - name: Set up the local.cfg file 64 | copy: 65 | dest: /etc/toggle/local.cfg 66 | owner: debian 67 | group: debian 68 | content: | 69 | [OctoPrint] 70 | user = toggle 71 | authentication = 72 | 73 | - name: clone octoprint toggle plugin from git 74 | git: 75 | repo: https://github.com/intelligent-agent/octoprint_toggle 76 | dest: /home/debian/octoprint_toggle 77 | 78 | - name: install octoprint toggle plugin in virtualenv 79 | shell: 80 | cmd: 'cd /home/debian/octoprint_toggle; {{ octoprint_home }}/venv/bin/python setup.py clean install' 81 | 82 | - name: Make toggle config files changeble from OctoPrint 83 | file: 84 | path: /etc/toggle 85 | recurse: yes 86 | owner: debian 87 | group: debian 88 | 89 | - name: enable the toggle service 90 | block: 91 | - name: Attempt to enable toggle with systemd module 92 | systemd: 93 | name: toggle 94 | daemon_reload: yes 95 | enabled: yes 96 | rescue: 97 | - name: Fallback to shell 98 | shell: systemctl enable toggle 99 | 100 | - name: Recore - copy toggle-runfirst service file 101 | copy: 102 | src: '{{ role_path }}/files/toggle-runfirst.service' 103 | dest: /etc/systemd/system/toggle-runfirst.service 104 | 105 | - name: Recore - Script - install toggle-runfirst 106 | copy: 107 | src: '{{ role_path }}/files/toggle-runfirst' 108 | dest: /usr/lib/ 109 | mode: +x 110 | 111 | - name: Recore - enable the toggle-runfirst service 112 | block: 113 | - name: Attempt to enable toggle-runfirst service normally 114 | systemd: 115 | name: toggle-runfirst 116 | daemon_reload: yes 117 | enabled: yes 118 | rescue: 119 | - name: Fallback to shell 120 | shell: systemctl enable toggle-runfirst 121 | -------------------------------------------------------------------------------- /roles/install_toggle/tasks/replicape.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dependencies 3 | apt: 4 | pkg: 5 | - gir1.2-clutter-1.0=1.26.0+dfsg-10.1 6 | - gir1.2-cogl-1.0=1.22.2-2.1 7 | - gir1.2-coglpango-1.0=1.22.2-2.1 8 | - gir1.2-mash-0.3-0=0.3.0-1 9 | - gir1.2-mx-2.0=1.99.4-1.1 10 | - libcairo2-dev 11 | - libclutter-1.0-0=1.26.0+dfsg-10.1 12 | - libclutter-1.0-common=1.26.0+dfsg-10.1 13 | - libclutter-imcontext-0.1-0=0.1.4-3.1 14 | - libclutter-imcontext-0.1-bin=0.1.4-3.1 15 | - libcluttergesture-0.0.2-0=0.0.2.1-7.2 16 | - libcogl-common=1.22.2-2.1 17 | - libcogl-pango20=1.22.2-2.1 18 | - libcogl-path20=1.22.2-2.1 19 | - libcogl20=1.22.2-2.1 20 | - libmash-0.3-0=0.3.0-1 21 | - libmx-2.0-0=1.99.4-1.1 22 | - libmx-bin=1.99.4-1.1 23 | - libmx-common=1.99.4-1.1 24 | - python3-networkmanager 25 | - python3-cairo 26 | - python3-gi-cairo 27 | - python3-tornado 28 | - python3-pip 29 | - python3-venv 30 | - python3-dbus 31 | - libdbus-1-dev 32 | - libglib2.0-dev 33 | state: present 34 | force: yes 35 | 36 | - name: clone toggle from git 37 | git: 38 | repo: https://github.com/intelligent-agent/toggle 39 | dest: '{{ toggle_home }}/src/toggle' 40 | version: dev 41 | depth: 1 42 | 43 | - name: copy toggle service file 44 | copy: 45 | src: '{{ role_path }}/files/toggle.service' 46 | dest: /lib/systemd/system/toggle.service 47 | 48 | - name: grant sudo to octo user for restarting toggle service 49 | lineinfile: 50 | path: /etc/sudoers.d/octo 51 | line: '%octo ALL=NOPASSWD: /bin/systemctl restart toggle.service' 52 | state: present 53 | 54 | - name: install pip3 dependencies 55 | pip: 56 | virtualenv: '{{ toggle_home }}' 57 | virtualenv_python: python3.6 58 | requirements: '{{ toggle_home }}/src/toggle/requirements.txt' 59 | 60 | - name: install pip3 dependencies 61 | pip: 62 | virtualenv: '{{ toggle_home }}' 63 | virtualenv_python: python3.6 64 | name: 65 | - gobject 66 | - PyGObject 67 | 68 | - name: clone pyconnman 69 | git: 70 | repo: https://github.com/liamw9534/pyconnman 71 | dest: '{{ toggle_home }}/src/pyconnman' 72 | depth: 1 73 | 74 | - name: install pyconnman in venv 75 | shell: 76 | cmd: 'cd {{ toggle_home }}/src/pyconnman ; ../../bin/python setup.py clean install' 77 | 78 | - name: install toggle in venv 79 | shell: 80 | cmd: 'cd {{ toggle_home }}/src/toggle ; {{ toggle_home }}/bin/pip install -e . -r requirements.txt ; {{ toggle_home }}/bin/python setup.py clean install' 81 | 82 | - name: make config directory 83 | file: 84 | path: /etc/toggle 85 | state: directory 86 | owner: octo 87 | group: octo 88 | 89 | - name: copy toggle configs 90 | copy: 91 | src: '{{ toggle_home }}/src/toggle/configs/' 92 | dest: /etc/toggle 93 | owner: octo 94 | group: octo 95 | 96 | - name: touch the local.cfg file 97 | file: 98 | path: /etc/toggle/local.cfg 99 | state: touch 100 | owner: octo 101 | group: octo 102 | 103 | - name: enable the toggle service 104 | service: 105 | name: toggle 106 | enabled: yes 107 | 108 | - name: clone octoprint toggle plugin from git 109 | git: 110 | repo: https://github.com/intelligent-agent/octoprint_toggle 111 | dest: /usr/src/octoprint_toggle 112 | 113 | - name: install octoprint toggle plugin in virtualenv 114 | shell: 115 | cmd: 'cd /usr/src/octoprint_toggle; {{ octoprint_home }}/venv/bin/python setup.py clean install' 116 | 117 | - name: install sudoers entry for toggle restart 118 | lineinfile: 119 | path: /etc/sudoers.d/octo 120 | line: '%octo ALL=NOPASSWD: /usr/bin/make -C /usr/src/toggle install' 121 | state: present 122 | 123 | - name: setup FB rotation in uEnv 124 | replace: 125 | regexp: "(cmdline=.*)" 126 | replace: "\\1 fbcon=rotate:1" 127 | path: /boot/uEnv.txt 128 | 129 | - name: enable toggle service 130 | service: 131 | name: toggle 132 | enabled: yes 133 | -------------------------------------------------------------------------------- /roles/install_toggle/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | toggle_home: /home/debian/toggle -------------------------------------------------------------------------------- /roles/install_ustreamer/files/ustreamer.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=streams webcam data 3 | 4 | [Service] 5 | ExecStart=/home/debian/ustreamer/ustreamer --device /dev/webcam --host=0.0.0.0 --port=8080 -m MJPEG 6 | 7 | [Install] 8 | WantedBy=dev-webcam.device 9 | -------------------------------------------------------------------------------- /roles/install_ustreamer/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: linux_preparation } -------------------------------------------------------------------------------- /roles/install_ustreamer/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install Mjpg 3 | include: recore.yml 4 | when: platform == 'recore' 5 | -------------------------------------------------------------------------------- /roles/install_ustreamer/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dependencies 3 | apt: 4 | pkg: 5 | - build-essential 6 | - libevent-dev 7 | - libjpeg-dev 8 | - libbsd-dev 9 | state: latest 10 | 11 | - name: clone git repo 12 | git: 13 | repo: https://github.com/pikvm/ustreamer 14 | dest: /home/debian/ustreamer 15 | depth: 1 16 | 17 | - name: compile ustreamer 18 | shell: make -j 19 | args: 20 | chdir: /home/debian/ustreamer 21 | creates: /home/debian/ustreamer/ustreamer 22 | 23 | - name: add video udev rule file 24 | file: 25 | path: /etc/udev/rules.d/50-video.rules 26 | state: touch 27 | 28 | - name: add video udev rules 29 | lineinfile: 30 | path: /etc/udev/rules.d/50-video.rules 31 | line: 'SUBSYSTEM=="video4linux", ATTR{name}!="cedrus", ATTR{index}=="0", SYMLINK+="webcam", TAG+="systemd"' 32 | state: present 33 | 34 | - name: add debian sudo permission to restart the service 35 | lineinfile: 36 | path: /etc/sudoers.d/debian 37 | line: '%debian ALL=NOPASSWD: /bin/systemctl restart ustreamer.service' 38 | state: present 39 | 40 | - name: deploy service file 41 | copy: 42 | src: '{{ role_path }}/files/ustreamer.service' 43 | dest: /etc/systemd/system/ustreamer.service 44 | 45 | - name: enable the video streaming service 46 | service: 47 | name: ustreamer.service 48 | enabled: yes 49 | -------------------------------------------------------------------------------- /roles/install_weston/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - { role: linux_preparation } -------------------------------------------------------------------------------- /roles/install_weston/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Recore - Install Weston 3 | include: recore.yml 4 | when: platform == 'recore' 5 | -------------------------------------------------------------------------------- /roles/install_weston/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install weston 3 | tags: weston 4 | apt: 5 | pkg: 6 | - weston 7 | - librsvg2-common 8 | 9 | - name: make weston ini directory 10 | tags: weston 11 | file: 12 | path: /etc/xdg/weston 13 | state: directory 14 | mode: '0755' 15 | 16 | - name: make weston ini file 17 | tags: weston 18 | copy: 19 | dest: /etc/xdg/weston/weston.ini 20 | content: | 21 | [core] 22 | idle-time=0 23 | 24 | [shell] 25 | locking=false 26 | panel-position=none 27 | 28 | [output] 29 | name=HDMI-A-1 30 | transform=normal 31 | 32 | - name: make weston service file 33 | tags: weston 34 | copy: 35 | dest: /etc/systemd/system/weston.service 36 | content: | 37 | [Unit] 38 | Description=Weston Wayland Compositor 39 | 40 | [Service] 41 | Environment="XDG_RUNTIME_DIR=/run/user/1000" 42 | ExecStart=/usr/bin/weston-launch --user debian 43 | 44 | [Install] 45 | WantedBy=multi-user.target 46 | 47 | - name: Enable service weston 48 | shell: systemctl enable weston 49 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/100update: -------------------------------------------------------------------------------- 1 | DPkg::Pre-Invoke {"mount -o remount,rw /boot";}; 2 | DPkg::Post-Invoke {"mount -o remount,ro /boot; /usr/local/bin/update-recore-revision";}; 3 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/cpufreq.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=cpufreq-set to force the CPU governor to performance on boot 3 | 4 | [Service] 5 | ExecStart=/opt/cpufreq.sh 6 | 7 | [Install] 8 | WantedBy=multi-user.target 9 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/cpufreq.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cpufreq-set -g performance 4 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/get-boot-media: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PATH_EMMC="/dev/mmcblk0p2" 4 | PATH_USB="/dev/sda2" 5 | UUID_EMMC=`lsblk -o UUID -n /dev/mmcblk0p2 2>/dev/null` 6 | UUID_USB=`lsblk -o UUID -n /dev/sda2 2>/dev/null` 7 | 8 | DEV=`grep "^rootdev=" /boot/armbianEnv.txt | sed 's:rootdev=::' | sed 's:UUID=::'` 9 | 10 | case $DEV in 11 | $PATH_EMMC | $UUID_EMMC) 12 | echo "emmc" 13 | ;; 14 | 15 | $PATH_USB | $UUID_USB) 16 | echo "usb" 17 | ;; 18 | 19 | *) 20 | echo "unknown" 21 | ;; 22 | 23 | esac 24 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/get-recore-config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | partprobe 4 | mkdir -p /mnt/config 5 | if ! grep -qs '/mnt/config ' /proc/mounts; then 6 | mount -r /dev/mmcblk0boot0p1 /mnt/config/ 7 | fi 8 | 9 | CONFIG=`ls /mnt/config/*.json` 10 | 11 | SENSOR=$1 12 | INPUT=$2 13 | SENSORS="thermocouple thermistor pt100 pt1000" 14 | INPUTS="T0 T1 T2 T3" 15 | 16 | usage() { 17 | echo "Usage: $0 " 18 | echo -e "\twhere sensor is one of '$SENSORS'" 19 | echo -e "\tand input is one of '$INPUTS'" 20 | } 21 | 22 | if ! echo $INPUTS | grep -w -q "$INPUT"; then 23 | usage 24 | exit 1 25 | fi 26 | 27 | GAIN=`cat "$CONFIG" | jq -r ".Opamps.$INPUT.\"100\".gain"` 28 | OFFSET=`cat "$CONFIG" | jq -r ".Opamps.$INPUT.\"100\".offset"` 29 | OFFSET_SCALED=`echo "$OFFSET * 0.01" | bc -l` 30 | ADC_VDD=`cat "$CONFIG" | jq -r ".Voltages.\"3.3V_AREF\""` 31 | PULLUP=`cat "$CONFIG" | jq -r ".Opamps.pullups.$INPUT.resistance"` 32 | 33 | case $SENSOR in 34 | thermocouple) 35 | echo "[extruder]" 36 | echo "sensor_type: Type K" 37 | echo "gain: $GAIN" 38 | echo "offset: $OFFSET_SCALED" 39 | echo "adc_voltage: $ADC_VDD" 40 | ;; 41 | 42 | thermistor) 43 | echo "[extruder]" 44 | echo "sensor_type: EPCOS 100K B57560G104F" 45 | echo "pullup_resistor: $PULLUP" 46 | ;; 47 | 48 | pt100) 49 | echo "[extruder]" 50 | echo "sensor_type: PT100 INA826" 51 | echo "adc_voltage: $ADC_VDD" 52 | ;; 53 | 54 | pt1000) 55 | echo "[extruder]" 56 | echo "sensor_type: PT1000" 57 | echo "pullup_resistor: $PULLUP" 58 | ;; 59 | 60 | *) 61 | usage 62 | ;; 63 | esac 64 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/get-recore-revision: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | OUTFILE="/dev/"`lsblk -n -o NAME | grep 'mmcblk[0-2]$'` 4 | 5 | if ! test -b ${OUTFILE}boot0p1; then 6 | partx -a ${OUTFILE}boot0 7 | fi 8 | 9 | mkdir -p /mnt/config 10 | if ! grep -qs '/mnt/config ' /proc/mounts; then 11 | mount -r ${OUTFILE}boot0p1 /mnt/config/ 12 | fi 13 | 14 | CONFIG=`ls /mnt/config/*.json` 15 | REVISION=`cat "$CONFIG" | jq -r ".Revision" | tr '[:upper:]' '[:lower:]'` 16 | 17 | echo $REVISION 18 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/get-recore-serial-number: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | partprobe 4 | mkdir -p /mnt/config 5 | if ! grep -qs '/mnt/config ' /proc/mounts; then 6 | mount -r /dev/mmcblk0boot0p1 /mnt/config/ 7 | fi 8 | cat /mnt/config/serial_number 9 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/get-rootfs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROOTFS=`cat /proc/mounts | grep "/ "` 4 | 5 | if [[ "$ROOTFS" == *"sda"* ]]; then 6 | echo "usb" 7 | elif [[ "$ROOTFS" == *"mmc"* ]]; then 8 | echo "emmc" 9 | fi 10 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/get_refactor_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | TAG=$(git log -n1 --pretty="format:%d" | sed "s/, /\n/g" | grep tag: | grep -v origin | sed "s/tag: \|)//g" | tr -d '\n') 5 | 6 | if [[ $TAG == "" ]]; then 7 | TAG=$(git reflog --decorate -1 | awk -F' ' '{print $1}' | tr -d '\n') 8 | fi 9 | 10 | echo $TAG 11 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/is-media-present: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MEDIA=$1 4 | 5 | case $MEDIA in 6 | usb) 7 | if test -b "/dev/sda1"; then 8 | echo "yes" 9 | else 10 | echo "no" 11 | fi 12 | ;; 13 | 14 | emmc) 15 | if test -b "/dev/mmcblk0"; then 16 | echo "yes" 17 | else 18 | echo "no" 19 | fi 20 | ;; 21 | 22 | *) 23 | echo "usage $0 " 24 | ;; 25 | 26 | esac 27 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/is-ssh-enabled: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if systemctl is-active --quiet ssh; then 3 | echo "yes" 4 | else 5 | echo "no" 6 | fi 7 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/refactor-apt-upgrade: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | partprobe 4 | mkdir -p /mnt/config 5 | if ! grep -qs '/mnt/config ' /proc/mounts; then 6 | echo 0 > /sys/block/mmcblk0boot0/force_ro 7 | mount -rw /dev/mmcblk0boot0p1 /mnt/config/ 8 | fi 9 | 10 | cp /boot/dtb/allwinner/sun50i-a64-recore*.dtb /mnt/config/ 11 | 12 | mount -o remount,rw /boot 13 | apt update 14 | apt upgrade 15 | cp /mnt/config/sun50i-a64-recore*.dtb /boot/dtb/allwinner/ 16 | sync 17 | mount -o remount,ro /boot 18 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/set-boot-media: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | NEW_MEDIA=$1 4 | 5 | if [ "x${NEW_MEDIA}" == "xusb" ]; then 6 | NEW_DEV="/dev/sda2" 7 | elif [ "x${NEW_MEDIA}" == "xemmc" ]; then 8 | NEW_DEV="/dev/mmcblk0p2" 9 | else 10 | echo "usage $0 usb/emmc" 11 | exit 1 12 | fi 13 | 14 | KEY="^rootdev=.*$" 15 | REPLACE="rootdev=${NEW_DEV}" 16 | 17 | mount -o remount -rw /boot 18 | sed -i "s:${KEY}:${REPLACE}:g" /boot/armbianEnv.txt 19 | sync 20 | mount -o remount -r /boot 21 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/set-recore-revision: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | revision="$1" 4 | 5 | case $revision in 6 | a3|a4|a5|a6|a7) 7 | echo "Using recore revision ${revision}" 8 | mount -o remount,rw /dev/mmcblk0p1 /boot 9 | cd /boot/dtb/allwinner/ 10 | ln -sf sun50i-a64-recore-$revision.dtb sun50i-a64-recore.dtb 11 | mount -o remount,ro /dev/mmcblk0p1 /boot 12 | ;; 13 | *) 14 | echo "usage: $0 a3|a4|a5|a6|a7" 15 | exit 1 16 | ;; 17 | esac 18 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/set-ssh-access: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | IS_ENABLED=$1 4 | 5 | if [ "x${IS_ENABLED}" == "xtrue" ]; then 6 | systemctl enable ssh 7 | systemctl start ssh 8 | elif [ "x${IS_ENABLED}" == "xfalse" ]; then 9 | systemctl stop ssh 10 | systemctl disable ssh 11 | else 12 | echo "usage $0 true/false" 13 | exit 1 14 | fi 15 | -------------------------------------------------------------------------------- /roles/linux_preparation/files/update-recore-revision: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if ! lscpu | grep -q Cortex-A53; then 4 | exit 0 5 | fi 6 | 7 | REVISION=`get-recore-revision` 8 | set-recore-revision $REVISION 9 | -------------------------------------------------------------------------------- /roles/linux_preparation/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Replicape - Prepare Linux 3 | include: replicape.yml 4 | when: platform == 'replicape' 5 | 6 | - name: Recore - Prepare Linux 7 | include: recore.yml 8 | when: platform == 'recore' 9 | 10 | - name: Pi - Prepare Linux 11 | include: pi.yml 12 | when: platform == 'pi' 13 | 14 | - name: Pi64 - Prepare Linux 15 | include: pi.yml 16 | when: platform == 'pi64' 17 | -------------------------------------------------------------------------------- /roles/linux_preparation/tasks/pi.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: remove login info 3 | file: 4 | path: "{{ item }}" 5 | state: absent 6 | with_items: 7 | - /etc/issue.net 8 | - /etc/issue 9 | 10 | - name: Register ReFactor version 11 | script: 12 | cmd: '{{ role_path }}/files/get_refactor_version.sh' 13 | register: version 14 | 15 | - name: upgrade packages 16 | apt: 17 | upgrade: dist 18 | 19 | - name: remove unneeded packages 20 | apt: 21 | pkg: 22 | - nginx 23 | - hostapd 24 | - libgtk3-common 25 | - grub 26 | - javascript-common 27 | state: absent 28 | autoremove: yes 29 | 30 | - name: install debconf-utils and curl 31 | apt: 32 | pkg: 33 | - debconf-utils 34 | - curl 35 | - firmware-realtek 36 | state: present 37 | 38 | - name: update package list 39 | apt: 40 | update_cache: yes 41 | 42 | - name: install packages 43 | apt: 44 | pkg: 45 | - unzip 46 | - iptables 47 | - iptables-persistent 48 | - python-pip 49 | - python3-pip 50 | - python-dev 51 | - libavahi-compat-libdnssd1 52 | - libnss-mdns 53 | - byobu 54 | - htop 55 | - unzip 56 | - cpufrequtils 57 | - pkg-config 58 | - python3-dev 59 | - pkg-config 60 | state: present 61 | autoremove: yes 62 | autoclean: yes 63 | 64 | - name: enable root login via ssh 65 | lineinfile: 66 | path: /etc/ssh/sshd_config 67 | line: 'PermitRootLogin yes' 68 | state: present 69 | 70 | - name: remove unneeded files 71 | file: 72 | path: "{{ item }}" 73 | state: absent 74 | with_items: 75 | - /etc/apache2/ 76 | - /root/.c9 77 | - /usr/lib/node_modules 78 | - /usr/local/lib/node_modules 79 | - /var/lib/cloud9 80 | - /var/cache/doc* 81 | 82 | - name: create dogtag 83 | file: 84 | path: '/etc/{{ dogtag }}' 85 | state: touch 86 | 87 | - name: get date 88 | command: 'date --iso-8601' 89 | register: build_date 90 | 91 | - name: write dogtag 92 | lineinfile: 93 | line: '{{ version.stdout }} {{ build_date.stdout }}' 94 | state: present 95 | path: '/etc/{{ dogtag }}' 96 | 97 | - name: remove hostname 98 | file: 99 | path: /etc/hostname 100 | state: absent 101 | 102 | - name: create hostname 103 | file: 104 | path: /etc/hostname 105 | state: touch 106 | 107 | - name: set hostname 108 | lineinfile: 109 | path: /etc/hostname 110 | line: '{{ platform }}' 111 | 112 | - name: set root password 113 | shell: 114 | cmd: "echo 'root:kamikaze' | chpasswd" 115 | 116 | - name: force user to change debian password on first login 117 | shell: 118 | cmd: "chage -d 0 debian" 119 | 120 | - name: force user to change root password on first login 121 | shell: 122 | cmd: "chage -d 0 root" 123 | 124 | - name: create issue and issue.net file 125 | file: 126 | path: '{{ item }}' 127 | state: touch 128 | with_items: 129 | - /etc/issue 130 | - /etc/issue.net 131 | 132 | - name: write issue and issue.net 133 | copy: 134 | dest: '{{ item }}' 135 | content: | 136 | {{ version.stdout }} 137 | 138 | Check that nothing is printing before any intensive operation! 139 | with_items: 140 | - /etc/issue.net 141 | - /etc/issue 142 | 143 | - name: enable ssh 144 | service: 145 | name: ssh 146 | enabled: yes 147 | 148 | - name: remove connman 149 | apt: 150 | name: connman 151 | state: absent 152 | 153 | - name: create resolv.conf 154 | file: 155 | path: /etc/resolv.conf 156 | state: touch 157 | mode: 0644 158 | owner: root 159 | group: root 160 | 161 | - name: reset the resolv.conf file 162 | lineinfile: 163 | path: /etc/resolv.conf 164 | line: nameserver 1.1.1.1 165 | state: present 166 | 167 | - name: install NetworkManager 168 | apt: 169 | name: network-manager 170 | state: latest 171 | 172 | -------------------------------------------------------------------------------- /roles/linux_preparation/tasks/recore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: remove unneeded packages 3 | apt: 4 | pkg: 5 | - smartmontools 6 | state: absent 7 | autoremove: yes 8 | 9 | - name: install packages 10 | apt: 11 | pkg: 12 | - unzip 13 | - libavahi-compat-libdnssd1 14 | - libnss-mdns 15 | - byobu 16 | - htop 17 | - cpufrequtils 18 | - pv 19 | - git 20 | state: present 21 | autoremove: yes 22 | autoclean: yes 23 | 24 | - name: Recore - ensure the debian user exists 25 | user: 26 | name: debian 27 | comment: Default user for OctoPrint 28 | shell: /bin/bash 29 | groups: tty,dialout 30 | append: yes 31 | expires: -1 32 | home: /home/debian 33 | 34 | - name: Recore - make sure the sudoers.d/debian file exists 35 | file: 36 | path: /etc/sudoers.d/debian 37 | owner: root 38 | group: root 39 | state: touch 40 | 41 | - name: Recore - create folder for klipper logs in /var/log 42 | file: 43 | path: /var/log/klipper_logs 44 | state: directory 45 | mode: '0755' 46 | owner: debian 47 | group: debian 48 | 49 | - name: Recore - create folder printer_data in /home/debian 50 | file: 51 | path: /home/debian/printer_data 52 | state: directory 53 | mode: '0755' 54 | owner: debian 55 | group: debian 56 | 57 | - name: Recore - create a symlink for the /home/debian/printer_data/logs to store them in /var/log 58 | file: 59 | src: /var/log/klipper_logs 60 | dest: /home/debian/printer_data/logs 61 | state: link 62 | owner: debian 63 | group: debian 64 | 65 | - name: enable ssh 66 | service: 67 | name: ssh 68 | enabled: no 69 | 70 | - name: Recore - disable root login 71 | replace: 72 | path: /etc/ssh/sshd_config 73 | regexp: '^.*PermitRootLogin.*$' 74 | replace: '#PermitRootLogin' 75 | 76 | - name: get date 77 | command: 'date --iso-8601' 78 | register: build_date 79 | 80 | - name: Register ReFactor version 81 | script: 82 | cmd: '{{ role_path }}/files/get_refactor_version.sh' 83 | register: version 84 | 85 | - name: write dogtag 86 | copy: 87 | dest: '/etc/{{ dogtag }}' 88 | content: '{{ version.stdout }} {{ build_date.stdout }}' 89 | 90 | - name: set hostname 91 | copy: 92 | dest: /etc/hostname 93 | content: "{{ platform }}\n" 94 | 95 | - name: set root password 96 | user: 97 | name: root 98 | password: "{{ 'kamikaze' | password_hash('sha512') }}" 99 | 100 | - name: set debian password 101 | user: 102 | name: debian 103 | password: "{{ 'temppwd' | password_hash('sha512') }}" 104 | 105 | - name: write issue and issue.net 106 | copy: 107 | dest: '{{ item }}' 108 | content: | 109 | {{ version.stdout }} 110 | 111 | Check that nothing is printing before any intensive operation! 112 | with_items: 113 | - /etc/issue.net 114 | - /etc/issue 115 | 116 | - name: Recore - fix home ownership 117 | command: chown -R debian:debian /home/debian 118 | 119 | - name: Recore - Add ttyGS0 to /etc/securetty 120 | lineinfile: 121 | path: /etc/securetty 122 | line: ttyGS0 123 | state: present 124 | 125 | - name: Recore - Enable ttyGS0 getty service 126 | service: 127 | name: serial-getty@ttyGS0.service 128 | enabled: yes 129 | 130 | - name: Recore - force debian password reset 131 | shell: chage -d 0 debian 132 | 133 | - name: Recore - install script to set CPU to use performance governor 134 | copy: 135 | src: '{{ role_path }}/files/cpufreq.sh' 136 | dest: /opt/cpufreq.sh 137 | mode: '0755' 138 | owner: debian 139 | group: debian 140 | 141 | - name: Recore - install service for CPU performance governor use 142 | copy: 143 | src: '{{ role_path }}/files/cpufreq.service' 144 | dest: /etc/systemd/system/cpufreq.service 145 | mode: '0644' 146 | owner: root 147 | group: root 148 | 149 | - name: Recore - enable the CPU performance governor usage 150 | systemd: 151 | daemon-reload: true 152 | enabled: true 153 | name: cpufreq 154 | 155 | - name: Recore - add support for system upgrade 156 | copy: 157 | src: 100update 158 | dest: /etc/apt/apt.conf.d/100update 159 | mode: '0644' 160 | 161 | - name: Recore - add files for updating dtb 162 | copy: 163 | src: '{{item}}' 164 | dest: /usr/local/bin 165 | mode: '0755' 166 | loop: 167 | - get-recore-revision 168 | - set-recore-revision 169 | - update-recore-revision 170 | -------------------------------------------------------------------------------- /roles/linux_preparation/tasks/replicape.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: remove login info 3 | file: 4 | path: "{{ item }}" 5 | state: absent 6 | with_items: 7 | - /etc/issue.net 8 | - /etc/issue 9 | 10 | - name: Register ReFactor version 11 | script: 12 | cmd: '{{ role_path }}/files/get_refactor_version.sh' 13 | register: version 14 | 15 | - name: upgrade packages 16 | apt: 17 | upgrade: dist 18 | 19 | - name: remove unneeded packages 20 | apt: 21 | pkg: 22 | - nginx 23 | - hostapd 24 | - libgtk3-common 25 | - grub 26 | - javascript-common 27 | state: absent 28 | autoremove: yes 29 | 30 | - name: install debconf-utils and curl 31 | apt: 32 | pkg: 33 | - debconf-utils 34 | - curl 35 | - firmware-realtek 36 | - git 37 | - usbutils 38 | state: present 39 | 40 | - name: Replicape - update RCN scripts 41 | command: 42 | chdir: /opt/scripts 43 | cmd: 'git pull' 44 | 45 | - name: update package list 46 | apt: 47 | update_cache: yes 48 | 49 | - name: install packages 50 | apt: 51 | pkg: 52 | - unzip 53 | - libavahi-compat-libdnssd1 54 | - libnss-mdns 55 | - byobu 56 | - htop 57 | - cpufrequtils 58 | - pkg-config 59 | state: present 60 | autoremove: yes 61 | autoclean: yes 62 | 63 | - name: enable root login via ssh 64 | lineinfile: 65 | path: /etc/ssh/sshd_config 66 | line: 'PermitRootLogin yes' 67 | state: present 68 | 69 | - name: remove unneeded files 70 | file: 71 | path: "{{ item }}" 72 | state: absent 73 | with_items: 74 | - /etc/apache2/ 75 | - /root/.c9 76 | - /usr/lib/node_modules 77 | - /usr/local/lib/node_modules 78 | - /var/lib/cloud9 79 | - /var/cache/doc* 80 | 81 | - name: create dogtag 82 | file: 83 | path: '/etc/{{ dogtag }}' 84 | state: touch 85 | 86 | - name: get date 87 | command: 'date --iso-8601' 88 | register: build_date 89 | 90 | - name: write dogtag 91 | lineinfile: 92 | line: '{{ version.stdout }} {{ build_date.stdout }}' 93 | state: present 94 | path: '/etc/{{ dogtag }}' 95 | 96 | - name: remove hostname 97 | file: 98 | path: /etc/hostname 99 | state: absent 100 | 101 | - name: create hostname 102 | file: 103 | path: /etc/hostname 104 | state: touch 105 | 106 | - name: set hostname 107 | lineinfile: 108 | path: /etc/hostname 109 | line: '{{ platform }}' 110 | 111 | - name: set root password 112 | user: 113 | name: root 114 | password: "{{ 'kamikaze' | password_hash('sha512') }}" 115 | 116 | - name: force user to change debian password on first login 117 | shell: 118 | cmd: "chage -d 0 debian" 119 | 120 | - name: force user to change root password on first login 121 | shell: 122 | cmd: "chage -d 0 root" 123 | 124 | - name: create issue and issue.net file 125 | file: 126 | path: '{{ item }}' 127 | state: touch 128 | with_items: 129 | - /etc/issue 130 | - /etc/issue.net 131 | 132 | - name: write issue and issue.net 133 | copy: 134 | dest: '{{ item }}' 135 | content: | 136 | {{ version.stdout }} 137 | 138 | Check that nothing is printing before any intensive operation! 139 | with_items: 140 | - /etc/issue.net 141 | - /etc/issue 142 | 143 | - name: enable ssh 144 | service: 145 | name: ssh 146 | enabled: yes 147 | 148 | - name: remove connman 149 | apt: 150 | name: connman 151 | state: absent 152 | 153 | - name: create resolv.conf 154 | file: 155 | path: /etc/resolv.conf 156 | state: touch 157 | mode: 0644 158 | owner: root 159 | group: root 160 | 161 | - name: reset the resolv.conf file 162 | lineinfile: 163 | path: /etc/resolv.conf 164 | line: nameserver 1.1.1.1 165 | state: present 166 | 167 | - name: install NetworkManager 168 | apt: 169 | name: network-manager 170 | state: latest 171 | 172 | - name: Disable audio 173 | lineinfile: 174 | path: /boot/uEnv.txt 175 | line: disable_uboot_overlay_audio=1 176 | state: present 177 | 178 | - name: Reflash pru firmware 179 | command: 180 | chdir: /home/debian/klipper 181 | cmd: ./scripts/flash-pru.sh 182 | 183 | - name: Replicape - fix home ownership 184 | command: chown -R debian:debian /home/debian 185 | -------------------------------------------------------------------------------- /roles/linux_preparation/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dogtag: refactor.version 3 | --------------------------------------------------------------------------------