A guide to get Klipper with fluidd, Mainsail or Duet-Web-Control on OpenWrt embeded devices like the Creality Wi-Fi Box.
If you are new to all this, you should checkout the Wiki
IMPORTANT: Switch to the tag of the version you want to install BEFORE using the information in this document to ensure you are syncronised to the core packages, scripts and instructions!
Click to expand!
( 🔴 Click to expand!)
- OpenWrt is so much more efficient than other linux distros.
- On a single core 580MHz cpu (with moonraker, klippy, nginx and mjpg-streamer) I get ~20-25% cpu load while idle/not printing and max 35-40% cpu load while printing and watching stream (640x480 30fps mjpeg).
- I've tried octoprint on this box as well but unfortunately it was too resource intensive. Test prints speak for themselves.
What is the Creality Wi-Fi Box?
(Click to expand!)
-
A router box device released by Creality in 2020 meant to add cloud based remote control to your printer. Creality Cloud App is a contraption between social media and 3d printing that you have to use to be able to print and monitor.
Sounded like a good idea. Unfortunately, the unpolished idea was not very well received by the public. Creality recently (July 2021) added Cura integration and custom gcode upload. Webcam support finally got released but it seems to only work with their new proprietary webcam. Everything is still cloud based and you can't use it offline. This raised a lot of concerns in terms of privacy and transparency. Putting all your trust in a company is not necesarily the best idea and although they seemed to have improved the app and user experience the full control is not in the user's hands yet.
It's hard to please everybody when creating a product/service but actually listening to the public's feedback is a good start. People need privacy, full control and reliability to actually consider using the product over the alternatives. Klipper and it's UI clients come as open source and 100% transparent alternatives to remote printing.
Specifications (Click to expand!)
(taken form figgyc's commit)
-
SoC: MediaTek MT7688AN @ 580 MHz
-
Flash: BoyaMicro BY25Q128AS (16 MiB, SPI NOR)
-
RAM: 128 MiB DDR2 (Winbond W971GG6SB-25)
-
Peripheral: Genesys Logic GL850G 2 port USB 2.0 hub
-
I/O: 1x 10/100 Ethernet port, microSD SD-XC Class 10 slot, 4x LEDs, 2x USB 2.0 ports, micro USB input (for power only), reset button
-
FCC ID: 2AXH6CREALITY-BOX
-
UART: test pads: (square on silkscreen) 3V3, TX, RX, GND; default baudrate: 57600
What is OpenWrt?
(Click to expand!)
- A Linux OS built for embeded devices, routers especially. Light, Open Source with a great community and
packages that gives your device the freedom it deserves.
What is Klipper?
(Click to expand!)
- A 3d-printer firmware. It runs on any kind of computer taking advantage of the host cpu. Extremely light on cpu, lots of features
(Click to expand!)
- These are free and open-source Klipper web interface clients for managing your 3d printer.
What is Moonraker?
(Click to expand!)
- A Python 3 based web server that exposes APIs with which client applications (fluidd or mainsail) may use to interact with Klipper. Communcation between the Klippy host and Moonraker is done over a Unix Domain Socket. Tornado is used to provide Moonraker's server functionality.
What is duet-web-control
(Click to expand!)
- Duet Web Control is a fully-responsive HTML5-based web interface for RepRapFirmware. Stephan3 built a socket to make it communicate with klipper as well (klipper is not a RepRapFirmware). This is a standalone webserver and client interface - so no need for moonraker or nginx.
🎬 Check out the latest video tutorial by Kruze17 on his Hyper Makes YouTube channel.
❗ Open issues or join the
server for extra support.
Click to expand!
Fresh installation of the chosen firmware release using latest releases of Klipper & Moonraker. Inevitably, because of this, it is a potential point of failure
Click for STEPS!
This method uses 2 scripts, one to format a micro sd card <= 8GB and make it extroot, and another one that fetches and installs everything from the internet.
-
Make sure you've flahsed/sysupgraded latest
.binfile from/Firmware/OpenWrt_snapshot/or from latest release. -
Connect to the
OpenWrtaccess point -
Access LuCi web interface and log in on
192.168.1.1:81 -
(optional but recommended) Add a password to the
OpenWrtaccess point:Wireless-> Under wireless overviewEDITtheOpenWrtinterface ->Wireless Security-> Choose an encryption -> set a password ->Save->Save & Apply -
(optional but recommended) Add a password:
System->Administration->Router Password -
❗If your home network subnet is on 1 (192.168.1.x), in order to avoid any ip conflicts, change the static ip of the box LAN from 192.168.1.1 to something like 192.168.3.1. To do that access the luci webinterface ->
Network->Interfacesand edit the static ip ->Save-> press the down arow on the Save&Apply button ->Apply Unchecked. You can now access luci on the new ip and continue configuring Client setup. -
Connect as a client to your Internet router:
Network->Wireless->SCAN->Join Network-> checkLock to BSSID->Create/Assign Firewall zonethen undercustomtypewwanenter ->Submit->Save->Save & Apply -
Connect back to your router and either find the new box's ip inside the
DHCPlist. -
❗ Access the terminal tab (
Services->Terminal) ❗ If terminal tab is not working go toConfigtab and changeInterfaceto the interface you are connecting through the box (your wireless router SSID for example) ->Save & Apply. -
Use these commands to download and run the
1_format_extroot.shscript:cd ~ wget https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/scripts/1_format_extroot.sh chmod +x 1_format_extroot.sh ./1_format_extroot.sh -
You'll be prompted to reboot: type
reboot -
Use these commands to download and run the
2_script_manual.shscript:cd ~ wget https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/scripts/2_script_manual.sh chmod +x 2_script_manual.sh ./2_script_manual.sh -
Follow the prompted instructions and wait for everything to be installed. If the script exits before installation is complete, complaining about missing resources, try running it again.
-
You can remove the scripts, if you want, when done:
rm -rf /root/*.sh -
When done and rebooted use
http://openwrt.localorhttp://<your-box-ip>to access the Klipper client. Depending on your network configuration the no-ip may work, but the ip will always connect, providing nginx is up and running!
-
Use Mainsail or Fluidd to upload your
printer.cfgOr use your method of choice to place it in/root/printer_data/config -
delete these blocks from your
printer.cfg:[virtual_sdcard],[display_status],[pause_resume]since they're included insidefluidd.cfg/mainsail.cfg -
add these lines inside your
printer.cfgdepending on your klipper client (mainsail/fluidd): -
Fluidd:
[include fluidd.cfg][include timelapse.cfg] -
Mainsail:
[include mainsail.cfg][include timelapse.cfg] -
Under
[mcu]block change your serial port path according to this[Optional] -
Build your
klippper.binmainboard firmware using a linux operating system. It cannot be built using OpenWrt on the box (followprinter.cfgheader for instructions) -
Flash your mainboard according to the
printer.cfgheader -
Do a
FIRMWARE RESTARTinside fluidd/Mainsail -
Done
Notes:
- If the box doesn't connect back to your router wirelessly connect to it with an ethernet cable and setup/troubleshoot wifi.
- Check here for how to set your
TIMELAPSE_TAKE_FRAMEmacro inside your slicer layer change.
Click to expand!
Click for STEPS!
❗ Although this is an OpenWrt snapshot, it works seamlessly as long as the core package feed points at the correct tag for the firmware version in this repo.
Click to expand!
-
Creality WB-01 was merged in this commit PR to main. It should be available in the OpenWrt v25 release, when that eventually comes.
-
Until then I strongly advise you to use the firmware releases available in this repo. They are built to use the signed kernel modules provided for these tags, and everything else comes from OpenWrt servers. This means you can install any kernel module I made available, without disabling signature checking. This results in fewer problems and smaller firmware binaries, no need to worry about missing drivers.
Click to expand!
Flashing:
- Rename factory.bin to cxsw_update.tar.bz2 if it isn't already
- Copy it to the root of a FAT32 formatted microSD card.
- Turn on the device, wait for it to start, then insert the card. The stock firmware reads the install.sh script from this archive, the build script added creates one that works in a similar way. Web firmware update didn't work in Ihrapsa's testing.
Click to expand!
- If flashing was successful you should be able to connect to the box via the OpenWrt wireless access point. Because the firmware runs a dhcp server by default, ethernet connections may clash with your router, depending on your setup. You can circumnavigate any issues by using an ethernet connection from the box to your computer. This convineantely means the radio is free to scan for the a wireless connection. Plug the cable in to the box and your PC and use
ssh [email protected]inWindows PowerShellor anyunix terminalor useputty. - Edit
/etc/config/network,/etc/config/wirelessand/etc/config/firewall. I've uploaded these to follow as a model (insideWi-Fi). - Use
iw dev wlan0 scanto scan for near wi-fi networks and look for the bssid specific to your 2.4Ghz SSID.
4. Enable extroot (to expand the storage on the TF card) and enable swap.
Click to expand!
- Extroot
opkg update && opkg install block-mount kmod-fs-ext4 kmod-usb-storage kmod-usb-ohci kmod-usb-uhci e2fsprogs fdisk
DEVICE=$(awk '$2 == "/overlay" {print $1}' /etc/mtab)
uci -q delete fstab.rwm
uci set fstab.rwm="mount"
uci set fstab.rwm.device="${DEVICE}"
uci set fstab.rwm.target="/rwm"
uci commit fstab
mkfs.ext4 /dev/mmcblk0p1
DEVICE="/dev/mmcblk0p1"
eval $(block info "${DEVICE}" | grep -o -e "UUID=\S*")
uci -q delete fstab.overlay
uci set fstab.overlay="mount"
uci set fstab.overlay.uuid="${UUID}"
uci set fstab.overlay.target="/overlay"
uci commit fstab
mount /dev/mmcblk0p1 /mnt
cp -f -a /overlay/. /mnt
umount /mnt
reboot
- swap
run this once:
opkg update && opkg install swap-utils
dd if=/dev/zero of=/overlay/swap.page bs=1M count=512
mkswap /overlay/swap.page
swapon /overlay/swap.page
mount -o remount,size=256M /tmp
update /etc/rc.local so that swap is enabled at boot:
rm /etc/rc.local;
cat << "EOF" > /etc/rc.local
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.
###activate the swap file on the SD card
swapon /overlay/swap.page
###expand /tmp space
mount -o remount,size=256M /tmp
exit 0
EOF
Click for STEPS!
Click to expand!
- for Klipper and moonraker - check the respective
requirements.txtin the repository requirements folder. - Install
git-httpwithopkg update && opkg install git-http gcc unzip htop
opkg install git-http htop unzip;
opkg install --force-overwrite gcc;
opkg install patch;
opkg install python3 python3-pip python3-cffi python3-dev python3-greenlet python3-pillow python3-yaml;
pip install --upgrade pip;
pip install --upgrade setuptools;
pip install python-can configparser;
opkg install python3-tornado python3-distro python3-curl python3-zeroconf python3-paho-mqtt python3-requests ip-full libsodium;
pip install pyserial-asyncio lmdb streaming-form-data==1.15.0 inotify-simple libnacl preprocess-cancellation apprise ldap3 dbus-next importlib-metadata;
- Install nginx with
opkg install nginx-ssl
Click to expand!
- 6.1 Clone Klipper inside
~/-git clone --depth 1 https://github.com/Klipper3D/klipper.git. - 6.2 Use provided klipper service and place inside
/etc/init.d/
wget -q -O /etc/init.d/klipper https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/Services/klipper
chmod 755 /etc/init.d/klipper
- 6.3 Enable klipper service:
/etc/init.d/klipper enable
- 6.4 Prepare your
printer.cfgfile:
mkdir ~/klipper_config ~/klipper_logs ~/gcode_files
-
Locate your
.cfgfile inside~/klipper/config/copy it to~/klipper_configand rename it toprinter.cfg -
Inside
printer.cfgunder[mcu]replace serial line withserial: /dev/ttyUSB0 -
Add either
[include mainsail.cfg]or[include fluidd.cfg]to the top of theprinter.cfgfile depending on which front end you chose -
6.5 Restart klipper - do
service klipper restartor/etc/init.d/klipper restart -
6.6 Build
klipper.binfile - Building is not mandatory to be done on the device that hosts klippy. To build it on this box you would need a lot of dependencies that are not available for OpenWrt so I just used my pc running ubuntu: On a different computer running linux (or VM or live USB) -> Clone klipper just like you did before ->cd klipper->make menuconfig-> use the configurations specific to your mainboard (Check the header inside yourprinter.cfgfile for details). :exclamation: use custom baud:230400. By default 250000 is selected. If you want/need that baud, remove thepython-pyserialpackage and install this version of pyserial instead - checkRequirementsdirectory for details about installation process. -> once configured runmake-> if succesfull the firmware will be inside./out/klipper.bin-> flash the mainboard:(check header ofprinter.cfgagain - some mainboards need the.binfile renamed a certain way) copy the.binfile on a sd card -> plug the card with the printer off -> turn printer on and wait a minute -> Done (Depending on your mainboard/printer/lcd you will probably not have a sign that the mainboard got flashed so don't worry) - if at the end of this guide the client cannot connect to the klipper firmware usually the problem is with the.binfile building or flashing process.
Click to expand!
- 7.1 Clone Moonraker
cd ~
git clone https://github.com/Arksine/moonraker.git
- 7.2 Use provided moonraker.conf file and download chosen client
For fluidd:
mkdir ~/fluidd
wget -q -O /root/fluidd/fluidd.zip https://github.com/cadriel/fluidd/releases/latest/download/fluidd.zip && unzip /root/fluidd/fluidd.zip -d /root/fluidd/ && rm /root/fluidd/fluidd.zip
wget -q -O /root/klipper_config/moonraker.conf https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/moonraker/fluidd_moonraker.conf
wget -q -O /etc/nginx/conf.d/fluidd.conf https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/nginx/fluidd.conf
For Mainsail:
mkdir ~/mainsail
wget -q -O /root/mainsail/mainsail.zip https://github.com/meteyou/mainsail/releases/latest/download/mainsail.zip && unzip /root/mainsail/mainsail.zip -d /root/mainsail/ && rm /root/mainsail/mainsail.zip
wget -q -O /root/klipper_config/moonraker.conf https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/moonraker/mainsail_moonraker.conf
wget -q -O /etc/nginx/conf.d/mainsail.conf https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/nginx/mainsail.conf
Note: The [update_manager] plugin was commented out since this is curently only supported for debian distros only. For now, updating moonraker, klipper, fluidd or mainsail should be done manaully.
Don't forget to edit(if necessary) the moonraker.conf file you copied inside ~/klipper_config under trusted_clients: with your client ip or ip range (client meaning the device you want to access fluidd/mainsail from). Check the moonraker configuration doc for details.
- 7.3 Use provided moonraker service and place inside
/etc/init.d/
wget -q -O /etc/init.d/moonraker https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/Services/moonraker
chmod 755 /etc/init.d/moonraker
/etc/init.d/moonraker enable
/etc/init.d/moonraker restart
- 7.4 Download the rest of the nginx files inside
/etc/nginx/conf.d*
wget -q -O /etc/nginx/conf.d/upstreams.conf https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/nginx/upstreams.conf
wget -q -O /etc/nginx/conf.d/common_vars.conf https://raw.githubusercontent.com/shivajiva101/KlipperWrt/v4.4/nginx/common_vars.conf
Inside /etc/nginx/conf.d you should have fluidd.conf OR mainsail.conf alongside common_vars.conf AND upstreams.conf (those 2 files are common for mainsail and fluidd)
Note!
You need to use either fluidd.conf or mainsail.conf file depending on your chosen client. Don't use both .conf files inside /etc/nginx/conf.d/. If you want to test both clients and easly switch between them check the ! How to switch between fluidd and mainsail: below.
Note!
It's ok to keep both client directories inside /root/ as these are static files. Careful with the .conf file inside /etc/nginx/conf.d.
- 7.6 Restart nginx with
service nginx restartand check browser ifhttp://your-ipbrings you the client interface (fluidd or mainsail).
❗ How to switch between fluidd and mainsail:
- switch between
mainsail.confandfluidd.conffile inside/etc/nginx/conf.d(make sure the other one gets renamed to a differentextension. eg:*.conf_offor moved to a different folder.) - Switch between mainsail and fluidd
moonraker.conffiles inside~/klipper_config. Find them inside my repo undermoonrakerdirectory. - Restart moonraker and nginx services:
service moonraker restartandservice nginx restart
Click to expand!
- install video4linux utilities:
opkg update && opkg install v4l-utils - use commands:
opkg update && opkg install mjpg-streamer-input-uvc mjpg-streamer-output-http mjpg-streamer-www - connect a uvc webcam, configure
/etc/config/mjpg-streamerto your likings, enable and restart service:
/etc/init.d/mjpg-streamer enable/etc/init.d/mjpg-streamer restart
- put the stream link inside the client(fluidd/mainsail) camera setting:
http://<your_ip>/webcam/?action=stream
Click to expand!
- To change your hostname go to
/etc/config/systemand modifyoption hostname 'OpenWrt'to your likings. - To use your hostname in browser and ssh instead of the ip do:
opkg update
opkg install avahi-daemon-service-ssh avahi-daemon-service-http
reboot
- Instead of
http://your-ipusehttp://your_hostname.local
Click for STEPS!
Click to expand!
- for Klipper - check the
requirements.txtfile.
Click to expand!
- 6.1 Clone Klipper inside
~/- doopkg install git-http unzipthengit clone --depth 1 https://github.com/KevinOConnor/klipper.git. - 6.2 Use provided klipper service and place inside
/etc/init.d/- find it insideServices -> klipper - 6.3 Enable klipper service: Everytime you create a service file you need to give it executable permissions before enabling it. For klipper do
chmod 755 klipper. You can enable it now by/etc/init.d/klipper enable - 6.4 Prepare your
printer.cfgfile - domkdir ~/klipper_configandmkdir ~/gcode_files. Locate your.cfgfile inside~/klipper/config/copy it to~/klipper_configand rename it toprinter.cfg- Insideprinter.cfgunder[mcu]replace serial line withserial: /dev/ttyUSB0and add a new line:baud: 230400- (check requirements if you want/need 250000 baud) - 6.5 Restart klipper - do
service klipper restartor/etc/init.d/klipper restart - 6.6 Build
klipper.binfile - Building is not mandatory to be done on the device that hosts klippy. To build it on this box you would need a lot of dependencies that are not available for OpenWrt so I just used my pc running ubuntu: On a different computer running linux (or VM or live USB) -> Clone klipper just like you did before ->cd klipper->make menuconfig-> use the configurations specific to your mainboard (Check the header inside yourprinter.cfgfile for details). :exclamation: use custom baud:230400. By default 250000 is selected. If you want/need that baud, remove thepython-pyserialpackage and install this version of pyserial instead - checkRequirementsdirectory for details about installation process. -> once configured runmake-> if succesfull the firmware will be inside./out/klipper.bin-> flash the mainboard:(check header ofprinter.cfgagain - some mainboards need the.binfile renamed a certain way) copy the.binfile on a sd card -> plug the card with the printer off -> turn printer on and wait a minute -> Done (Depending on your mainboard/printer/lcd you will probably not have a sign that the mainboard got flashed so don't worry) - if at the end of this guide the client cannot connect to the klipper firmware usually the problem is with the.binfile building or flashing process.
Click to expand!
-
Download
cd ~git clone https://github.com/Stephan3/dwc2-for-klipper-socket -
Edit
dwc2.cfg- set theweb_root:path to absolute path:/root/sdcard/web -
Create dwc socket service Create a
dwcfile inside/etc/init.d/with the contents of thedwcfile inside my repo:Services->dwcGive it executable permissions:chmod 755 /etc/init.s/dwcEnable it:/etc/init.d/dwc enable
Click to expand!
- Download dwc version 3 web interface
mkdir -p ~/sdcard/web
cd ~/sdcard/web
wget -O DuetWebControl-SD.zip https://github.com/Duet3D/DuetWebControl/releases/download/3.1.1/DuetWebControl-SD.zip
unzip *.zip && for f_ in $(find . | grep '.gz');do gunzip ${f_};done
rm DuetWebControl-SD.zip
- Restart dwc socket service:
service dwc restartor/etc/init.d/dwc restart - Test:
https:://<your_ip>:4750
Click to expand!
- To change your hostname go to
/etc/config/systemand modifyoption hostname 'OpenWrt'to your likings. - To use your hostname in browser and ssh instead of the ip do:
opkg update
opkg install avahi-daemon-service-ssh avahi-daemon-service-http
reboot
- Instead of
http://your-ipusehttp://your_hostname.local
(aka Sysupgrading)
Click to expand!
- Downloadthe sysupgrade.bin file to your computer
- Connect the box to your pc and make sure it's reachable by ssh
- Transfer it to the box inside
/tmpdirectory with WinSCP or through command in Powershell/UNIX Terminal:scp /path/to/sysupgrade.bin [email protected]:/tmp - ssh to the box and navigate to
/tmpmake sure the bin is there - Do
sysupgrade -n -v *bin
Click to expand!
- Open a separate
sshinstance and runlogread -f- you'll get real time log data of the running process. - You can always open an issue or contact me if you get stuck or something doesn't work.
Click to expand!
-
Creating a non-privileged user Check this guide All the tests I did were as root - some modifications would be necessary to not run everything as root.
- Packages needed:
shadow-useradd,sudo,shadow-groupadd,shadow-usermod
- Packages needed:
-
Copy files to the box
scp /path/file.ext root@<your_box_ip>:/tmp -
Watch realtime CommandLine log (open an aditional terminal instance for this)
logread -f -
Services commands (Replace
servicewithklipper/moonraker/nginx/mjpg-streamerrespectively)/etc/init.d/service enable/etc/init.d/service start/etc/init.d/service restart -
Check CPU/system resources usage
top -
Check webcam specifcations
v4l2-ctl --allv4l2-ctl --list-formats -
List installed packages
opkg list-installed -
Reboot, Poweroff
rebootpoweroff
Click to expand!
-
If enabling the services returns an error, do:
ls -linside/etc/init.d/and check if the service has executable permissions (x flag). If not do:chmod 755 service- replaceserviceaccordingly. -
I didn't manage to get the printer to communicate on 250000 baudrate (Official version of pyserial is unable to set a custom nonstandard baudrate - I found the fix by ckielstra has been merged but isn't currently being used by pip. Use forked pyserial as well which is updated more often. If you don't want to use 250k baudrate you can solve this issue by using 230400 instead (you need to change this both while building the mcu klipper firmware AND inside printer.cfg under [mcu]:
[mcu]baud: 230400 -
The Host and Services commands (
Reboot,Shutdown,Restart Moonraker,Restart Klipperetc.) inside fluidd/mainsail did not work at first due to moonraker using debian syntax. I solved this by editing the~moonraker/moonraker/components/machine.py. Use these commands insideself._execute_cmd("command"):"poweroff","reboot",f'/etc/init.d/{service_name} restart'for host poweroff, reboot and services restart respectively.
Click to expand!
- Download a previowsly working SYSUPGRADE OpenWrt image.
- Rename it to
root_uImage - Put it on a FAT32 formatted USB stick (NOT sd card)
- Insert it in the box while off
- Press and hold the reset button
- Power on the box while still holding the reset button for about 6-10 sec.
- Release the button and wait for a couple of minutes. After a couple of seconds you should find the KlipperWrt AP. You should be able to ssh into it through ethernet or connected to it's wifi (
ssh [email protected])
Click to expand!
- Download a stock image (found inside
Firmware/Creality_Stockfolder as well) - Unzip the stock
tar.bz2and get theroot_uImagefile - Put it on a FAT32 formatted USB stick (NOT sd card)
- Insert it in the box while off
- Press and hold the reset button
- Power on the box while still holding the reset button for about 6-10 sec.
- Release the button and wait for a couple of minutes. After a few seconds you should find it on network.
- the idea: Hackaday.com - for the article that set me on this journey
- the hard part: figgyc - for porting OpenWrt to the Creality Wi-Fi Box
- the essentials:
- Kevin O'Connor - for Klipper
- cadriel - for fluidd
- mateyou - for mainsail
- Eric Callahan - for Moonraker
- Stephan3 - for dwc socket
- Duet3D - for DuetWebControl
- the fine tuning: andryblack - for the OpenWrt Klipper service
- the encouragement: Tom Hensel- for supporting Ihrapsa in creating this











