Klipper print status
Shows Klipper 3D printer progress via Moonraker API
| System | AWTRIX NG Scripts |
|---|---|
| Firmware | AWTRIX NG |
| Topic | Miscellaneous |
| Built by | Set |
| File | mM4sasmjv7jT.ax · 3.8 KB |
| Icons | 2 |
| Published | 25 Aug 2026 · updated 25 Aug 2026 |
| Downloads | 5 |
You can set host, port, refresh period, icons, progress bar color, and work percent value correction.
mM4sasmjv7jT.ax
# @name Klipper
# @desc Shows Klipper 3D printer progress via Moonraker API
# @author Set
# @version 1.4
# @config host text "Moonraker IP / Host" default="192.168.1.50"
# @config port number "Port" default=7125 min=1 max=65535
# @config every number "Refresh (sec)" default=5 min=1 max=60 unit=s
# @config correction number "Percent correction" default=2 min=1 unit=% max=20 help="Positive only, Will be added to current value from Moonraker API"
# @config icon text "Print Icon ID" default="51841"
# @config dicon text "Done Icon ID" default="55186"
# @config pcol color "Progress Bar" default=#00FF00
class Klipper
var url, period
var state, prev_state, progress, label, correction
var ticks, in_flight
def init()
var h = store.get("host")
var p = store.get("port")
self.url = "http://" + h + ":" + str(p) + "/printer/objects/query?print_stats&display_status"
self.period = store.get("every")
self.state = nil
self.prev_state = nil
self.progress = 0
self.label = nil
self.ticks = 0
self.correction = 2
self.in_flight = false
end
def on_body(body, status)
self.in_flight = false
if body == nil return end
var m_state = re.search("\"state\":\\s*\"([^\"]+)\"", body)
if m_state == nil return end
self.prev_state = self.state
self.state = m_state[1]
if self.state == "printing"
var m_prog = re.search("\"progress\":\\s*([0-9.]+)", body)
if m_prog != nil
var p_val = num(m_prog[1])
if p_val != nil
self.progress = int(p_val * 100 + 0.5)
self.label = str(self.progress + self.correction) + "%"
end
else
self.label = "PRT"
end
elif self.state == "complete"
self.label = "Done!"
self.progress = 100
if self.prev_state == "printing"
rotation.show()
sound.rtttl("done:d=4,o=5,b=140:8c6,8e6,8g6,c7")
end
else
self.label = "Idle"
self.progress = 0
end
end
def loop()
if self.ticks <= 0
self.ticks = self.period
if !self.in_flight
self.in_flight = true
http.get(self.url, / b, st -> self.on_body(b, st),
{'find': "\"status\":", 'keep': 1024})
end
end
self.ticks -= 1
end
def draw_print_fallback()
rect_fill(1, 0, 6, 2, 0x888888)
pixel(3, 2, 0xFF8800)
pixel(4, 2, 0xFF8800)
pixel(3, 3, 0xFF4400)
rect_fill(0, 5, 8, 3, 0x555555)
rect_fill(1, 4, 6, 1, 0x00FF00)
end
def draw_done_fallback()
rect_fill(0, 0, 8, 8, 0x002200)
line(1, 4, 3, 6, 0x00FF00)
line(3, 6, 6, 1, 0x00FF00)
end
def draw()
clear()
var is_done = (self.state == "complete")
var ic_key = is_done ? "dicon" : "icon"
var ic = store.get(ic_key)
var has_icon = icon(ic, 0, 0)
if !has_icon
if is_done
self.draw_done_fallback()
else
self.draw_print_fallback()
end
end
var x_offset = 9
var avail_w = width() - x_offset
if self.label == nil
text(x_offset + (avail_w - text_ink_width("...")) / 2, 6, "...", 0x666666)
return
end
if self.state == "printing"
text(x_offset + (avail_w - text_ink_width(self.label)) / 2, 6, self.label, 0xFFFFFF)
progress(self.progress, store.get("pcol"))
elif is_done
text(x_offset + (avail_w - text_ink_width(self.label)) / 2, 6, self.label, 0x00FF00)
else
text(x_offset + (avail_w - text_ink_width(self.label)) / 2, 6, self.label, 0x888888)
end
end
def should_show()
return self.state == "printing" || self.state == "complete"
end
def on_button(btn)
if btn == "select"
self.ticks = 0
end
end
end
return Klipper()
Install it on your AWTRIX NG
Your browser writes the script straight to the device on your network. It joins the app rotation right away.
Some browsers refuse to talk to a device on your network from a public page. Download the flow and paste it into the Scripts tab of your device, or install it from a terminal:
These icons belong on the device, in /ICONS. Each one is at
most 32×8
pixels — shown here magnified, at their real proportions.
8×8 px
8×8 px
More flows for AWTRIX NG Scripts or Miscellaneous
Something wrong with this flow? Report it.