Skip to content

3D printing sentry

The sentry below needs an accompanying calender/database backend to keep track of prints. For that backend I'm using Google Apps Script (code not shared here).

Bambu Calendar Print Watcher for Sonic Pad

This utilizes OctoEverywhere's local MQTT relay ports. It uses one Python process for every configured printer, performs calendar requests outside the MQTT callbacks, reconnects automatically, and remembers a submitted print across watcher restarts.

I'm using a creality sonic pad I previously configured

1. Verify the relay-to-printer mapping

SSH into the sonic pad and run:

for f in /usr/share/.octoeverywhere-bambu*/octoeverywhere.conf
do
    echo
    echo "$f"
    grep -E '^(ip_or_hostname|printer_serial_number)[[:space:]]*=' "$f"
    sed -n '/^\[mqtt\]/,/^\[/p' "$f" | grep '^port[[:space:]]*='
done

Match each printer label to its OctoEverywhere configuration directory. All relay ports must be unique and listening before starting the watcher.

2. Configure the watcher

Download the 3 files:
- print-watcher.init
- print_watcher_config.example.json
- print_watcher_sonicpad.py

Rename print-watcher.init to print_watcher (no extensions)

Rename print_watcher_config.example.json to config.json. Fill in:

  • the existing Google Apps Script endpoint;
  • each printer label; and
  • the path to that printer's existing OctoEverywhere configuration file.

The watcher reads the serial number, access code, authentication mode, and relay port directly from that OctoEverywhere file. It checks for changes every 10 seconds and recreates its local connection when any of them changes. Thus, after changing a printer access code, update only OctoEverywhere's config and restart that OctoEverywhere connector; this watcher requires no edit or manual restart.

The relay host defaults to 127.0.0.1. The local relay uses ordinary MQTT/TCP, so the watcher deliberately does not enable TLS.

3. Place the files in the correct locations

mkdir -p /usr/share/print-watcher

then either:
A) transfer print_watcher_sonicpad.py and config.json into this folder via SCP
OR
B) use vi to paste in the contents of the file

place (scp) print_watcher in /etc/init.d/ (or use vi to create /etc/init.d/print_watcher)

adjust the permissions:

chmod 700 /usr/share/print-watcher/print_watcher_sonicpad.py
chmod 600 /usr/share/print-watcher/config.json
chmod 755 /etc/init.d/print_watcher

4. Test it interactively

/usr/share/octoeverywhere-env/bin/python3 \
    /usr/share/print-watcher/print_watcher_sonicpad.py \
    --config /usr/share/print-watcher/config.json

Expected messages include one Connected to local MQTT relay line per printer. Stop the test with Ctrl+C.

If authentication is rejected, verify that the relevant OctoEverywhere connector has been restarted since its access code was changed. If a connection is refused, confirm the relevant port is listening:

netstat -lntp 2>/dev/null | grep -E ':(1883|1884|1885|1886)[[:space:]]'

5. Enable automatic startup

/etc/init.d/print_watcher enable
/etc/init.d/print_watcher start

Verify the process:

ps w | grep '[p]rint_watcher_sonicpad.py'

Follow its dedicated log:

tail -f /usr/share/print-watcher/print_watcher.log

Restart after changing config.json:

/etc/init.d/print_watcher restart

Stop or disable it:

/etc/init.d/print_watcher stop
/etc/init.d/print_watcher disable

Centauri Calendar Print Watcher for Sonic Pad

This is for the original CC 1, not CC2, CC2 uses MQTT instead of SDCP.

The CC I'm using has OpenCentauri installed, in theory it works the same at the OEM firmware, but I'm not 100% sure.
In Theory, with OC, I can run the script on the printer itself, since I have root access, but CC1 have very limited RAM available, so it's probably best not to do that.

1. Copy the archive from Windows

Download cc1-calendar-watcher-sonicpad.tar.gz to Windows. In PowerShell, replace SONIC_PAD_IP with the Sonic Pad address:

scp -O -o HostKeyAlgorithms=+ssh-rsa -o MACs=+hmac-sha1,hmac-md5 "$env:USERPROFILE\Downloads\cc1-calendar-watcher-sonicpad.tar.gz" root@SONIC_PAD_IP:/tmp/

password should be cxsw-sonic_2023

2. Extract and install

SSH into the pad, then:

cd /tmp
tar -xzf cc1-calendar-watcher-sonicpad.tar.gz
rm cc1-calendar-watcher-sonicpad.tar.gz
cd cc1-calendar-watcher-sonicpad
sh install.sh

The installer reuses OctoEverywhere's existing WebSocket library when available. It does not modify the OctoEverywhere virtual environment. If that library is unavailable, it installs the small Python-3.7-compatible dependency into this watcher's own vendor directory.

It preserves an existing config.json if you run it again during an update.

3. Configurations

vi /usr/share/cc-calendar-watcher/config.json

In vi, press i to edit. Confirm:

  • printer_host is the CC1 address: 192.168.1.XX.
  • printer_label is what prepends the google calendar event.
  • calendar_endpoint is the existing deployed Apps Script /exec URL.
  • stop_on_calendar_rejection is true when you are ready to enforce booking rejection.

Press Esc, type :wq, and press Enter. Then protect the file:

chmod 600 /usr/share/cc-calendar-watcher/config.json

Note

Reserve the CC1 address in your router if possible. The watcher can rediscover the same MainboardID after an IP change, but a DHCP reservation is simpler.

4. Sanity check

run the local check:

/usr/share/cc-calendar-watcher/run.sh --check

This opens the CC1 WebSocket and sends only status Cmd 0. It does not contact Google and cannot stop the printer. The output should contain:

{
  "ok": true,
  "host": "<IP_ADDRESS>",
  "print_status": {
    "name": "idle"
  }
}

5. Enable and start at boot

/etc/init.d/cc-calendar-watcher enable
/etc/init.d/cc-calendar-watcher start

Check that one process is running:

pgrep -af cc1_calendar_watcher.py

Follow the rotating application log:

tail -f /usr/share/cc-calendar-watcher/watcher.log

6. Service controls

/etc/init.d/cc-calendar-watcher stop
/etc/init.d/cc-calendar-watcher start
/etc/init.d/cc-calendar-watcher restart
/etc/init.d/cc-calendar-watcher disable

Stopping the watcher does not stop the printer.

Using vi

vi is like nano

cd /usr/share/print-watcher
vi print_watcher_sonicpad.py

press i to enter edit/insert mode, type/paste the text press esc to exit edit/insert mode

then :wq to save and exit

vi cheatsheet

Action Command
Exit without saving :q!
Save without exiting :w
Save and exit :wq
Delete current line dd
Undo u
Search /search-text, then Enter

Klipper (V400) Calendar Print Watcher on Speeder Pad

With V400, I installed stock Klippe and have root access to the speeder pad.

Stock Klipper on Speeder Pad

While Cyril has but in a lot of work into making the tutorial, I've found it to be a bit unreliable. speeder pad uses an very old CPU that's not really supported, so a lot of the dependencies don't install properly, especially if there's an update to anything. Installing stock klipper is honestly a pain and takes forever, just install v1.2.

For this sentry, it doesn't stop prints, it simply logs the prints to a calendar/database.

Verify

run the following command to verify that print state can be read

curl -s 'http://127.0.0.1:7125/printer/objects/query?webhooks&virtual_sdcard&print_stats' | python3 -m json.tool

When printing:

"vertual_sdcard":{
  "is_active": true
}
"print_stats": {
  "state": "printing"
}
When idle, is_active should be false, and state should be standby

Configure

Use the example config json, inside calendar_endpoint, printer label and id should be updated. (label is for internal use, ID is used on the calendar). Additionally calendar_token is used as a form as verification, to prevent anyone from randomly adding event to the calendar, token on GAS and json file has to match.

Gernerating a token

on the speeder paf or computer, run the command
python3 -c 'import secrets; print(secrets.token_urlsafe(32))'
or use online python compilers

moonraker_calendar_watcher.py and print-calendar-watcher.service are also needed

copy the files into the speeder pad, replace ip address with the appropriate one.

scp moonraker_calendar_watcher.py print-calendar-watcher.service config-v400.example.json pi@192.168.1.XX:/tmp/

then on the speeder pad place the files and install the service

sudo mkdir -p /opt/print-calendar-watcher

sudo cp /tmp/moonraker_calendar_watcher.py /opt/print-calendar-watcher/
sudo cp /tmp/config-v400-1.example.json /opt/print-calendar-watcher/config.json
sudo cp /tmp/print-calendar-watcher.service /etc/systemd/system/

sudo chmod 700 /opt/print-calendar-watcher/moonraker_calendar_watcher.py
sudo chmod 600 /opt/print-calendar-watcher/config.json
sudo chmod 644 /etc/systemd/system/print-calendar-watcher.service

check configuration is correct

sudo /usr/bin/python3 /opt/print-calendar-watcher/moonraker_calendar_watcher.py --config /opt/print-calendar-watcher/config.json --check

Enable the sentry

then enable the service

sudo systemctl daemon-reload
sudo systemctl enable --now print-calendar-watcher.service

logs are saved at /opt/print-calendar-watcher/watcher.log and can be checked using the command sudo journalctl -u print-calendar-watcher.service -f