printer troubleshooting etc
This commit is contained in:
@ -43,6 +43,12 @@ class Screen10(tk.Frame):
|
||||
self.running = True
|
||||
self._update_frame()
|
||||
|
||||
# Sticker tip - only show when a sticker was printed
|
||||
if GlobalVars.print_type == "sticker":
|
||||
RoundedLabel(container,
|
||||
text="You might like to add some packing tape on top\nof your sticker to make it more permanent",
|
||||
bg='white', font=('Georgia', 16)).pack(pady=(10, 0))
|
||||
|
||||
# Button container for side-by-side layout
|
||||
button_frame = tk.Frame(container, bg=BG_COLOR)
|
||||
button_frame.pack(pady=10)
|
||||
|
||||
@ -51,7 +51,7 @@ class Screen4(tk.Frame, DrawingMixin):
|
||||
|
||||
# Initialize drawing via mixin (grid_size=1 for stickers)
|
||||
self.init_drawing(597, 360, grid_size=1)
|
||||
self.draw_size = 3 # Override default size for stickers
|
||||
self.draw_size = 4 # Override default size for stickers
|
||||
self.imported_img = None
|
||||
|
||||
# QR size positions and defaults
|
||||
@ -217,6 +217,7 @@ class Screen8(tk.Frame, DrawingMixin):
|
||||
|
||||
# Initialize drawing via mixin
|
||||
self.init_drawing(width, height, grid_size=scale_factor)
|
||||
self.draw_size = 4 # Second-from-largest pen size
|
||||
|
||||
# Right panel: Pen tools (grid layout) + action buttons
|
||||
right_panel = tk.Frame(main_container, bg=BG_COLOR)
|
||||
|
||||
@ -77,12 +77,32 @@ It can print stickers and ribbons to affix to an item you care about."""
|
||||
wraplength=500, justify='left', padx=20, pady=20)
|
||||
text_label.pack(expand=True)
|
||||
|
||||
# Bottom: Forward button only
|
||||
# Bottom: Forward button only (delayed)
|
||||
nav_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
nav_frame.grid(row=1, column=0, columnspan=2, sticky='ew', pady=20)
|
||||
|
||||
tk.Button(nav_frame, text="Forward →", command=lambda: master.switch_frame(InfoPage2),
|
||||
height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='right', padx=40)
|
||||
# Dot progress indicator
|
||||
self.dots_label = tk.Label(nav_frame, text="", font=GlobalVars.TEXT_FONT, bg=BG_COLOR)
|
||||
self.dots_label.pack(side='left', expand=True)
|
||||
self.dot_count = 0
|
||||
|
||||
def add_dot():
|
||||
self.dot_count += 1
|
||||
self.dots_label.config(text="." * self.dot_count)
|
||||
if self.dot_count < 8:
|
||||
self.after(1000, add_dot)
|
||||
|
||||
self.after(1000, add_dot)
|
||||
|
||||
self.forward_btn = tk.Button(nav_frame, text="Forward →", command=lambda: master.switch_frame(InfoPage2),
|
||||
height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
|
||||
def show_forward():
|
||||
self.dots_label.pack_forget()
|
||||
self.forward_btn.pack(side='right', padx=40)
|
||||
|
||||
# Show forward button after 8 second delay
|
||||
self.after(8000, show_forward)
|
||||
|
||||
|
||||
class InfoPage2(tk.Frame):
|
||||
@ -123,14 +143,35 @@ by tagging an item you are saying to it, 'you matter, I will take care of you'""
|
||||
wraplength=500, justify='left', padx=20, pady=20)
|
||||
text_label.pack(expand=True)
|
||||
|
||||
# Bottom: Back and Forward buttons
|
||||
# Bottom: Back and Forward buttons (forward delayed)
|
||||
nav_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
nav_frame.grid(row=1, column=0, columnspan=2, sticky='ew', pady=20)
|
||||
|
||||
tk.Button(nav_frame, text="← Back", command=lambda: master.switch_frame(InfoPage1),
|
||||
height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='left', padx=40)
|
||||
tk.Button(nav_frame, text="Forward →", command=lambda: master.switch_frame(InfoPage3),
|
||||
height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='right', padx=40)
|
||||
|
||||
# Dot progress indicator (centered)
|
||||
self.dots_label = tk.Label(nav_frame, text="", font=GlobalVars.TEXT_FONT, bg=BG_COLOR)
|
||||
self.dots_label.pack(side='left', expand=True)
|
||||
self.dot_count = 0
|
||||
|
||||
def add_dot():
|
||||
self.dot_count += 1
|
||||
self.dots_label.config(text="." * self.dot_count)
|
||||
if self.dot_count < 8:
|
||||
self.after(1000, add_dot)
|
||||
|
||||
self.after(1000, add_dot)
|
||||
|
||||
self.forward_btn = tk.Button(nav_frame, text="Forward →", command=lambda: master.switch_frame(InfoPage3),
|
||||
height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
|
||||
def show_forward():
|
||||
self.dots_label.pack_forget()
|
||||
self.forward_btn.pack(side='right', padx=40)
|
||||
|
||||
# Show forward button after 8 second delay
|
||||
self.after(8000, show_forward)
|
||||
|
||||
|
||||
class InfoPage3(tk.Frame):
|
||||
@ -147,14 +188,14 @@ class InfoPage3(tk.Frame):
|
||||
|
||||
All generated items are stored permanently and replicated across the Scuttlebutt network. Once published, it cannot be deleted.
|
||||
|
||||
Please do not create imaginary items or shitpost.
|
||||
Please post with care and with positive and constructive intentions.
|
||||
|
||||
The QR codes contain a Scuttlebutt messageID, scanning it works best at www.cust.ooo or any Scuttlebutt client.
|
||||
"""
|
||||
|
||||
text_label = RoundedLabel(container, text=mindful_text,
|
||||
font=GlobalVars.TEXT_FONT, bg='white',
|
||||
wraplength=700, justify='center', padx=30, pady=30)
|
||||
font=("Helvetica", 20), bg='white',
|
||||
wraplength=900, justify='center', padx=30, pady=30)
|
||||
text_label.pack()
|
||||
|
||||
# Deferred import
|
||||
@ -162,11 +203,32 @@ The QR codes contain a Scuttlebutt messageID, scanning it works best at www.cust
|
||||
from kiosk.screens.ssb_selection import Screen1
|
||||
master.switch_frame(Screen1)
|
||||
|
||||
# Bottom: Back and Forward buttons
|
||||
# Bottom: Back and Forward buttons (forward delayed)
|
||||
nav_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
nav_frame.place(relx=0.5, rely=0.9, anchor='center')
|
||||
|
||||
tk.Button(nav_frame, text="← Back", command=lambda: master.switch_frame(InfoPage2),
|
||||
height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='left', padx=40)
|
||||
tk.Button(nav_frame, text="Forward →", command=go_to_screen1,
|
||||
height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='right', padx=40)
|
||||
|
||||
# Dot progress indicator (centered)
|
||||
self.dots_label = tk.Label(nav_frame, text="", font=GlobalVars.TEXT_FONT, bg=BG_COLOR)
|
||||
self.dots_label.pack(side='left', expand=True)
|
||||
self.dot_count = 0
|
||||
|
||||
def add_dot():
|
||||
self.dot_count += 1
|
||||
self.dots_label.config(text="." * self.dot_count)
|
||||
if self.dot_count < 8:
|
||||
self.after(1000, add_dot)
|
||||
|
||||
self.after(1000, add_dot)
|
||||
|
||||
self.forward_btn = tk.Button(nav_frame, text="Forward →", command=go_to_screen1,
|
||||
height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
|
||||
def show_forward():
|
||||
self.dots_label.pack_forget()
|
||||
self.forward_btn.pack(side='right', padx=40)
|
||||
|
||||
# Show forward button after 8 second delay
|
||||
self.after(8000, show_forward)
|
||||
|
||||
@ -110,15 +110,20 @@ class Screen13(tk.Frame):
|
||||
|
||||
# Load and rotate scan-tag 90 degrees clockwise
|
||||
scan_tag = Image.open("scan-tag.png").convert("L")
|
||||
scan_tag_rotated = scan_tag.rotate(-90, expand=True) # -90 = clockwise
|
||||
scan_tag_rotated = scan_tag.rotate(-90, expand=True) # -90 = clockwise, 53×357
|
||||
|
||||
merged_image = Image.new('L', (675, 375), "white")
|
||||
# 300 DPI printer, 2.25" label = 675 dots
|
||||
# Drawing: 597px, scan-tag rotated: 53px = 650px total (no gap)
|
||||
sticker_width = 650
|
||||
sticker_height = 375
|
||||
|
||||
merged_image = Image.new('L', (sticker_width, sticker_height), "white")
|
||||
merged_image.paste(drawing, (0, 8))
|
||||
merged_image.paste(qr_img, (QRX, QRY + 8))
|
||||
|
||||
# Paste rotated scan-tag right after drawing, vertically centered
|
||||
scan_tag_x = 597 # Right edge of drawing
|
||||
scan_tag_y = (375 - scan_tag_rotated.height) // 2 # Center vertically
|
||||
scan_tag_y = (sticker_height - scan_tag_rotated.height) // 2 # Center vertically
|
||||
merged_image.paste(scan_tag_rotated, (scan_tag_x, scan_tag_y))
|
||||
|
||||
merged_image.save("merged_image.png")
|
||||
@ -161,7 +166,10 @@ class Screen13(tk.Frame):
|
||||
print_width=ribbon_width,
|
||||
label_length=total_height)
|
||||
else:
|
||||
zpl_code = tozpl.print_to_zpl("merged_image.png")
|
||||
# Sticker: specify dimensions for proper positioning on 2.25" (675 dot @ 300 DPI) label
|
||||
zpl_code = tozpl.print_to_zpl("merged_image.png",
|
||||
print_width=sticker_width,
|
||||
label_length=sticker_height)
|
||||
|
||||
# save the zpl
|
||||
# Open the file in write mode
|
||||
@ -214,20 +222,21 @@ AND OR
|
||||
please email maintenance@cust.ooo
|
||||
|
||||
thanks!"""
|
||||
RoundedLabel(container, text=troubleshoot_text, bg='white', font=('Georgia', 22),
|
||||
RoundedLabel(container, text=troubleshoot_text, bg='white', font=('Georgia', 18),
|
||||
wraplength=900, justify='left').pack(pady=10)
|
||||
|
||||
# Re-print button
|
||||
tk.Button(container, text="Re-print", command=self._reprint,
|
||||
height=2, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=5)
|
||||
|
||||
# Done button
|
||||
# Button container for side-by-side layout
|
||||
def go_home():
|
||||
from kiosk.screens.home import Screen0
|
||||
master.switch_frame(Screen0)
|
||||
|
||||
tk.Button(container, text="Done", command=go_home,
|
||||
height=2, width=30, bg='light gray', font=GlobalVars.BUTTON_FONT).pack(pady=5)
|
||||
button_frame = tk.Frame(container, bg=BG_COLOR)
|
||||
button_frame.pack(pady=10)
|
||||
|
||||
tk.Button(button_frame, text="Re-print", command=self._reprint,
|
||||
height=2, width=20, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='left', padx=10)
|
||||
tk.Button(button_frame, text="Done", command=go_home,
|
||||
height=2, width=20, bg='light gray', font=GlobalVars.BUTTON_FONT).pack(side='left', padx=10)
|
||||
|
||||
def _reprint(self):
|
||||
"""Re-send the last print job."""
|
||||
|
||||
@ -54,6 +54,7 @@ class Screen2(tk.Frame):
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
self.selected_label = None
|
||||
self.filtered_users = []
|
||||
self._search_after_id = None # For debouncing search input
|
||||
|
||||
# Create a new frame at the top for the label and text box
|
||||
self.top_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
@ -61,7 +62,7 @@ class Screen2(tk.Frame):
|
||||
|
||||
# Add a label with text wrapping
|
||||
self.label = RoundedLabel(self.top_frame,
|
||||
text="slowly type your public key or alias one letter at a time to find yourself in the list then click on your key to select it.",
|
||||
text="Type your public key or alias to find yourself in the list, then click on your key to select it.",
|
||||
font=GlobalVars.TEXT_FONT,
|
||||
wraplength=800,
|
||||
bg='white')
|
||||
@ -69,7 +70,7 @@ class Screen2(tk.Frame):
|
||||
|
||||
# Add text box to the top frame
|
||||
self.entry = tk.Entry(self.top_frame, font=GlobalVars.TEXT_FONT)
|
||||
self.entry.bind('<KeyRelease>', lambda e: self.update_users_list())
|
||||
self.entry.bind('<KeyRelease>', self._debounced_search)
|
||||
self.entry.pack(side="top", fill="x", padx=20)
|
||||
|
||||
# Focus on the entry box
|
||||
@ -113,20 +114,51 @@ class Screen2(tk.Frame):
|
||||
from kiosk.screens.camera import Screen3
|
||||
master.switch_frame(Screen3)
|
||||
|
||||
def cancel_selection():
|
||||
GlobalVars.selected_user = None
|
||||
go_to_screen3()
|
||||
|
||||
# The 'Cancel' button to skip without selecting a user
|
||||
self.cancel_button = tk.Button(self.button_frame, text="Cancel", command=cancel_selection,
|
||||
height=2, width=20, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
self.cancel_button.pack(side="left", padx=(10, 10))
|
||||
|
||||
# The 'Done' button to navigate to next screen
|
||||
self.done_button = tk.Button(self.button_frame, text="Done", command=go_to_screen3,
|
||||
height=2, width=20, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
self.done_button.pack(side="right", padx=(10, 20))
|
||||
|
||||
# Initialize users list from users.json
|
||||
self.users = self.get_users_from_file()
|
||||
self.update_users_list()
|
||||
# Loading label (shown during initial load)
|
||||
self.loading_label = tk.Label(self.scrollable_frame, text="Loading...",
|
||||
font=GlobalVars.TEXT_FONT, bg=BG_COLOR)
|
||||
self.loading_label.pack(pady=20)
|
||||
|
||||
# Defer loading to allow UI to render first
|
||||
self.users = []
|
||||
self.after(10, self._load_users)
|
||||
|
||||
master.add_home_button(self)
|
||||
|
||||
def _debounced_search(self, event=None):
|
||||
"""Debounce search input - wait 250ms after last keystroke before searching."""
|
||||
if self._search_after_id:
|
||||
self.after_cancel(self._search_after_id)
|
||||
self._search_after_id = self.after(250, self.update_users_list)
|
||||
|
||||
def _load_users(self):
|
||||
"""Load users from file and display them."""
|
||||
self.users = self.get_users_from_file()
|
||||
self.loading_label.destroy()
|
||||
self.update_users_list()
|
||||
|
||||
def update_users_list(self):
|
||||
search_text = self.entry.get().lower()
|
||||
self.filtered_users = [user for user in self.users if search_text in user['id'].lower() or search_text in self.unescape_unicode(user.get('alias', '')).lower()]
|
||||
# Use cached _search_alias and _search_id for fast filtering
|
||||
self.filtered_users = [
|
||||
user for user in self.users
|
||||
if search_text in user.get('_search_id', user['id'].lower())
|
||||
or search_text in user.get('_search_alias', '')
|
||||
]
|
||||
self.display_users()
|
||||
|
||||
# Preserve selection after filtering
|
||||
@ -148,7 +180,8 @@ class Screen2(tk.Frame):
|
||||
frame = tk.Frame(self.scrollable_frame, bg=BG_COLOR)
|
||||
frame.pack(fill='x', expand=True, pady=2)
|
||||
|
||||
alias = self.unescape_unicode(user.get('alias', ''))
|
||||
# Use cached _display_alias if available, otherwise compute it
|
||||
alias = user.get('_display_alias', self.unescape_unicode(user.get('alias', '')))
|
||||
id = user.get('id', '')
|
||||
|
||||
alias_label = tk.Label(frame, text=alias, font=('Georgia', 14, 'bold'), width=20, anchor='w', bg='white')
|
||||
@ -221,14 +254,28 @@ class Screen2(tk.Frame):
|
||||
return False
|
||||
|
||||
def refresh_users(self):
|
||||
# Show loading state
|
||||
self.refresh_button.configure(state="disabled", text="Loading...")
|
||||
self.update_idletasks()
|
||||
|
||||
try:
|
||||
self.users = self.get_scuttlebutt_users()
|
||||
users = self.get_scuttlebutt_users()
|
||||
# Pre-process aliases for the new users
|
||||
for user in users:
|
||||
display_alias = self.unescape_unicode(user.get('alias', ''))
|
||||
user['_display_alias'] = display_alias
|
||||
user['_search_alias'] = display_alias.lower()
|
||||
user['_search_id'] = user['id'].lower()
|
||||
self.users = users
|
||||
self.update_users_list()
|
||||
self.save_users_to_file(self.users)
|
||||
self.save_users_to_file(users)
|
||||
messagebox.showinfo("Success", "User list has been refreshed and updated with aliases.")
|
||||
except Exception as e:
|
||||
print(f"An error occurred while refreshing the user list: {e}")
|
||||
messagebox.showerror("Error", "An error occurred while refreshing the user list. Please try again later.")
|
||||
finally:
|
||||
# Restore button state
|
||||
self.refresh_button.configure(state="normal", text="Refresh List")
|
||||
|
||||
def get_scuttlebutt_users(self):
|
||||
try:
|
||||
@ -253,6 +300,12 @@ class Screen2(tk.Frame):
|
||||
try:
|
||||
with open('users.json') as f:
|
||||
users = json.load(f)
|
||||
# Pre-process and cache unescaped aliases for fast search and display
|
||||
for user in users:
|
||||
display_alias = self.unescape_unicode(user.get('alias', ''))
|
||||
user['_display_alias'] = display_alias
|
||||
user['_search_alias'] = display_alias.lower()
|
||||
user['_search_id'] = user['id'].lower()
|
||||
return users
|
||||
except FileNotFoundError:
|
||||
return []
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
^XA
|
||||
^PW675
|
||||
^LL375
|
||||
^LH0,0
|
||||
^LT0
|
||||
^LS0
|
||||
^JUS
|
||||
^XZ
|
||||
@ -1,8 +0,0 @@
|
||||
^XA
|
||||
^PW675
|
||||
^LL375
|
||||
^LH10,10
|
||||
^LT0
|
||||
^LS0
|
||||
^JUS
|
||||
^XZ
|
||||
@ -1,8 +0,0 @@
|
||||
^XA
|
||||
^PW675
|
||||
^LL375
|
||||
^LH5,5
|
||||
^LT0
|
||||
^LS0
|
||||
^JUS
|
||||
^XZ
|
||||
@ -1,7 +0,0 @@
|
||||
^XA
|
||||
^FO0,0^GB50,50,50^FS
|
||||
^FO605,0^GB50,50,50^FS
|
||||
^FO0,305^GB50,50,50^FS
|
||||
^FO605,305^GB50,50,50^FS
|
||||
^FO280,155^A0N,30,30^FDCENTER^FS
|
||||
^XZ
|
||||
@ -1,7 +0,0 @@
|
||||
^XA
|
||||
^FO0,0^GB40,40,40^FS
|
||||
^FO625,0^GB40,40,40^FS
|
||||
^FO0,325^GB40,40,40^FS
|
||||
^FO625,325^GB40,40,40^FS
|
||||
^FO290,160^A0N,30,30^FDCENTER^FS
|
||||
^XZ
|
||||
@ -1,7 +0,0 @@
|
||||
^XA
|
||||
^FO0,0^GB40,40,40^FS
|
||||
^FO605,0^GB40,40,40^FS
|
||||
^FO0,305^GB40,40,40^FS
|
||||
^FO605,305^GB40,40,40^FS
|
||||
^FO285,155^A0N,30,30^FDCENTER^FS
|
||||
^XZ
|
||||
@ -1,3 +0,0 @@
|
||||
^XA
|
||||
~HQ
|
||||
^XZ
|
||||
@ -1,6 +0,0 @@
|
||||
^XA
|
||||
^LT0
|
||||
^LS0
|
||||
^LH0,0
|
||||
^JUS
|
||||
^XZ
|
||||
@ -1,4 +0,0 @@
|
||||
^XA
|
||||
^LH50,50
|
||||
^JUS
|
||||
^XZ
|
||||
@ -1,5 +0,0 @@
|
||||
^XA
|
||||
^LT50
|
||||
^LS50
|
||||
^JUS
|
||||
^XZ
|
||||
@ -1,6 +0,0 @@
|
||||
^XA
|
||||
^FO10,10
|
||||
^GB200,100,3^FS
|
||||
^FO30,50
|
||||
^A0N,30,30^FDTest^FS
|
||||
^XZ
|
||||
@ -1,7 +0,0 @@
|
||||
^XA
|
||||
^LH50,50
|
||||
^FO0,0
|
||||
^GB100,100,3^FS
|
||||
^FO50,50
|
||||
^A0N,30,30^FDCenter Test^FS
|
||||
^XZ
|
||||
@ -1,8 +0,0 @@
|
||||
^XA
|
||||
^LT50
|
||||
^LS50
|
||||
^FO0,0
|
||||
^GB200,200,3^FS
|
||||
^FO20,80
|
||||
^A0N,40,40^FDShift Test^FS
|
||||
^XZ
|
||||
129
printer-troubleshooting/darkness-troubleshooting.md
Normal file
129
printer-troubleshooting/darkness-troubleshooting.md
Normal file
@ -0,0 +1,129 @@
|
||||
# Zebra Printer Darkness Troubleshooting
|
||||
|
||||
## Understanding Darkness Settings
|
||||
|
||||
The Zebra GX430t has **two darkness settings that add together**:
|
||||
|
||||
| Command | Type | Range | Persists? |
|
||||
|---------|------|-------|-----------|
|
||||
| `~SD##` | Absolute base darkness | 0-30 | Yes (with `^JUS`) |
|
||||
| `^MD##` | Relative offset | -30 to +30 | Yes (with `^JUS`) |
|
||||
|
||||
**Effective darkness = ~SD value + ^MD offset**
|
||||
|
||||
### Critical Warning: ^MD Stacks!
|
||||
|
||||
The `^MD` command is **relative** - it adds/subtracts from the current saved offset. If you run:
|
||||
```bash
|
||||
echo "^XA^MD-5^JUS^XZ" | lp -d printer # offset now -5
|
||||
echo "^XA^MD-2^JUS^XZ" | lp -d printer # offset now -7 (not -2!)
|
||||
```
|
||||
|
||||
This can quickly result in an extremely low effective darkness, causing blank labels even at high `~SD` values.
|
||||
|
||||
### How to Reset
|
||||
|
||||
To fix stacked ^MD issues:
|
||||
```bash
|
||||
# Option 1: Factory reset (WARNING: loses all calibration)
|
||||
echo "^XA^JUF^XZ" | lp -d printer
|
||||
|
||||
# Option 2: Try setting high ~SD to compensate
|
||||
# If prints are blank at ~SD15, try ~SD25 or ~SD30
|
||||
echo "^XA~SD25^JUS^XZ" | lp -d printer
|
||||
```
|
||||
|
||||
## Symptoms and Solutions
|
||||
|
||||
### Checkerboard/dithered areas print DARKER than solid black
|
||||
**Cause:** Too much heat - solid areas need sustained heat, but you're overheating
|
||||
**Solution:** DECREASE darkness (counterintuitive!)
|
||||
```bash
|
||||
echo "^XA~SD10^JUS^XZ" | lp -d printer # try lower values
|
||||
```
|
||||
|
||||
### Ribbon tears or sticks to labels
|
||||
**Cause:** Way too much heat
|
||||
**Solution:** Significantly decrease darkness
|
||||
```bash
|
||||
echo "^XA~SD5^JUS^XZ" | lp -d printer
|
||||
```
|
||||
|
||||
### Text edges dark but centers are gray/muddled
|
||||
**Cause:** Slightly too much heat
|
||||
**Solution:** Decrease darkness incrementally
|
||||
|
||||
### Prints are faint/gray overall
|
||||
**Cause:** Not enough heat (or extreme overheat causing poor transfer)
|
||||
**Solution:** Increase darkness, but if you've been adjusting ^MD, the offset may be very negative
|
||||
|
||||
### Completely blank labels
|
||||
**Cause:**
|
||||
1. Darkness too low (check for stacked ^MD issue)
|
||||
2. Wrong print mode (direct thermal vs thermal transfer)
|
||||
3. Ribbon not making contact
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Ensure thermal transfer mode
|
||||
echo "^XA^MTT^JUS^XZ" | lp -d printer
|
||||
|
||||
# Try high darkness to rule out ^MD stacking
|
||||
echo "^XA~SD25^JUS^XZ" | lp -d printer
|
||||
```
|
||||
|
||||
## Finding the Right Darkness
|
||||
|
||||
Start low and work up - it's easier to recover from too-light than too-dark:
|
||||
|
||||
1. Set a known baseline:
|
||||
```bash
|
||||
echo "^XA~SD5^JUS^XZ" | lp -d printer
|
||||
```
|
||||
|
||||
2. Print test pattern (see test-prints/ directory)
|
||||
|
||||
3. If too light, increment by 2-3:
|
||||
```bash
|
||||
echo "^XA~SD8^JUS^XZ" | lp -d printer
|
||||
```
|
||||
|
||||
4. Stop when black is solid black and gray is distinguishable
|
||||
|
||||
**For full resin ribbon on this setup, ~SD25 worked well (after ^MD offset issues).**
|
||||
**Originally, ~SD2-6 was optimal before ^MD commands corrupted the offset.**
|
||||
|
||||
## Printing ZPL Files
|
||||
|
||||
Always use `-o raw` flag:
|
||||
```bash
|
||||
lp -d printer -o raw /path/to/file.zpl
|
||||
```
|
||||
|
||||
Without `-o raw`, large ZPL files may not print.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
# Set absolute darkness (0-30)
|
||||
echo "^XA~SD15^JUS^XZ" | lp -d printer
|
||||
|
||||
# Check thermal transfer mode is enabled
|
||||
echo "^XA^MTT^JUS^XZ" | lp -d printer
|
||||
|
||||
# Set print speed (1=slowest, higher=faster)
|
||||
echo "^XA^PR2^JUS^XZ" | lp -d printer
|
||||
|
||||
# Factory reset (last resort - loses calibration!)
|
||||
echo "^XA^JUF^XZ" | lp -d printer
|
||||
```
|
||||
|
||||
## Session Log: 2026-01-28
|
||||
|
||||
Started with checkerboard-darker-than-solid symptom. Discovered:
|
||||
- Original darkness was way too high
|
||||
- Optimal was around ~SD2-6
|
||||
- Accidentally used ^MD-5 and ^MD-2 which stacked to create large negative offset
|
||||
- Even after power cycle, blank labels persisted (saved to EEPROM)
|
||||
- Had to use ~SD25 to compensate for the negative ^MD offset
|
||||
- Lesson: Avoid ^MD commands, stick to ~SD for absolute control
|
||||
@ -3,5 +3,5 @@
|
||||
^FO625,0^GB50,50,50^FS
|
||||
^FO0,325^GB50,50,50^FS
|
||||
^FO625,325^GB50,50,50^FS
|
||||
^FO300,170^A0N,30,30^FDCENTER^FS
|
||||
^FO280,160^A0N,40,40^FDCENTER^FS
|
||||
^XZ
|
||||
12
printer-troubleshooting/test-darkness.zpl
Normal file
12
printer-troubleshooting/test-darkness.zpl
Normal file
@ -0,0 +1,12 @@
|
||||
^XA
|
||||
^FO30,20^A0N,30,30^FDSolid Black:^FS
|
||||
^FO30,55^GB120,60,60^FS
|
||||
^FO200,20^A0N,30,30^FDCheckerboard:^FS
|
||||
^FO200,55^GFA,480,480,8,AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555AAAA5555^FS
|
||||
^FO400,20^A0N,30,30^FD50% Gray:^FS
|
||||
^FO400,55^GFA,480,480,8,F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0^FS
|
||||
^FO30,140^A0N,40,40^FDTest Text Here^FS
|
||||
^FO30,200^A0N,24,24^FDIf checkerboard is darker than solid = too hot^FS
|
||||
^FO30,230^A0N,24,24^FDIf everything is gray = too cold^FS
|
||||
^FO30,260^A0N,24,24^FDIdeal: solid=black, checker=medium gray^FS
|
||||
^XZ
|
||||
3
printer-troubleshooting/test-simple.zpl
Normal file
3
printer-troubleshooting/test-simple.zpl
Normal file
@ -0,0 +1,3 @@
|
||||
^XA
|
||||
^FO50,50^A0N,50,50^FDTest^FS
|
||||
^XZ
|
||||
BIN
qr.png
BIN
qr.png
Binary file not shown.
|
Before Width: | Height: | Size: 993 B After Width: | Height: | Size: 709 B |
63
ssb-troubleshooting-2026-01-27.md
Normal file
63
ssb-troubleshooting-2026-01-27.md
Normal file
@ -0,0 +1,63 @@
|
||||
# SSB Troubleshooting Notes - January 27, 2026
|
||||
|
||||
## Problem
|
||||
Kiosk ssb-server posts were not propagating to the pub over the internet.
|
||||
|
||||
## Environment
|
||||
- Kiosk: `custo-kiosk-2` running ssb-server 15.3.0 as a user systemd service
|
||||
- Kiosk key: `@apIwMs+ElLT6h4d9nUqqFSWUXAHII1d+Wz9SopR26Lo=.ed25519`
|
||||
- Pub: `69.61.19.149:8807`
|
||||
- Pub key: `@jmnz08i4tzykqJ57B3BduqabcYSuDxTukOvihPlLkec=.ed25519`
|
||||
|
||||
## Findings
|
||||
|
||||
### 1. ekata.social pub is down
|
||||
The original pub at `ssb.ekata.social:8008` is not accepting connections:
|
||||
```
|
||||
Error: connect ECONNREFUSED 64.190.63.222:8008
|
||||
```
|
||||
- Server pings fine, but port 8008 refuses connections
|
||||
- The ssb-server process on that pub is likely not running
|
||||
|
||||
### 2. Personal pub at 69.61.19.149:8807 is reachable
|
||||
- Port 8807 confirmed open via netcat
|
||||
- Friends relationship confirmed (hops=1)
|
||||
|
||||
### 3. Manual gossip.connect triggered sync
|
||||
Running this command forced a connection and posts synced:
|
||||
```bash
|
||||
ssb-server gossip.connect 'net:69.61.19.149:8807~shs:jmnz08i4tzykqJ57B3BduqabcYSuDxTukOvihPlLkec='
|
||||
```
|
||||
|
||||
## Possible Root Causes (not fully diagnosed)
|
||||
- Wrong port cached in gossip table (8008 vs 8807)
|
||||
- Exponential backoff after failed connection attempts
|
||||
- Gossip scheduler not prioritizing the peer
|
||||
|
||||
## Useful Diagnostic Commands
|
||||
|
||||
```bash
|
||||
# Check ssb-server status
|
||||
systemctl --user status ssb-server
|
||||
|
||||
# View user-level logs
|
||||
journalctl --user -u ssb-server --no-pager -n 100
|
||||
|
||||
# Check identity
|
||||
ssb-server whoami
|
||||
|
||||
# List all gossip peers (large output)
|
||||
ssb-server gossip.peers
|
||||
|
||||
# Check friend relationship
|
||||
ssb-server friends.hops '@PUBKEY.ed25519'
|
||||
|
||||
# Manually trigger connection to a pub
|
||||
ssb-server gossip.connect 'net:HOST:PORT~shs:PUBKEY_WITHOUT_@_AND_.ed25519'
|
||||
|
||||
# Test if pub port is reachable
|
||||
nc -zv HOST PORT -w 5
|
||||
```
|
||||
|
||||
## Resolution
|
||||
Manually running `gossip.connect` triggered the sync. If this happens again, try forcing a connection with the command above.
|
||||
@ -85,14 +85,23 @@ echo "^XA^PW675^LL375^JUS^XZ" | lp -d sticker
|
||||
|
||||
### Step 5: Configure Darkness
|
||||
|
||||
Full resin ribbon needs moderate heat. Start with MD18:
|
||||
**Use `~SD` (absolute) instead of `^MD` (relative) to avoid stacking issues.**
|
||||
|
||||
Full resin ribbon heat requirements vary. Start LOW and work up:
|
||||
|
||||
```bash
|
||||
echo "^XA^MD18^JUS^XZ" | lp -d sticker
|
||||
# Start with low darkness
|
||||
echo "^XA~SD5^JUS^XZ" | lp -d sticker
|
||||
```
|
||||
|
||||
If prints are too light/gray, increase to MD20 or MD22.
|
||||
If resin sticks to labels when peeling, decrease to MD15.
|
||||
Test print and adjust:
|
||||
- If too light/gray: increase (`~SD8`, `~SD10`, etc.)
|
||||
- If resin sticks or ribbon tears: decrease
|
||||
- **If checkerboard prints darker than solid black: DECREASE darkness (counterintuitive!)**
|
||||
|
||||
See `printer-troubleshooting/darkness-troubleshooting.md` for detailed guidance.
|
||||
|
||||
**WARNING:** Avoid `^MD` commands - they stack and can corrupt saved settings. Stick to `~SD` for absolute control.
|
||||
|
||||
### Step 6: Physical Calibration
|
||||
|
||||
@ -111,13 +120,13 @@ The printer will feed several labels as it calibrates the gap sensor.
|
||||
Simple text test:
|
||||
|
||||
```bash
|
||||
echo "^XA^PW675^LL375^MD18^FO50,50^ADN,36,20^FDTest Print^FS^XZ" | lp -d sticker
|
||||
echo "^XA^PW675^LL375~SD10^FO50,50^ADN,36,20^FDTest Print^FS^XZ" | lp -d sticker
|
||||
```
|
||||
|
||||
Border alignment test:
|
||||
|
||||
```bash
|
||||
echo "^XA^PW675^LL375^MD18^FO10,10^GB655,355,5^FS^XZ" | lp -d sticker
|
||||
echo "^XA^PW675^LL375~SD10^FO10,10^GB655,355,5^FS^XZ" | lp -d sticker
|
||||
```
|
||||
|
||||
This prints a 5-dot border around the label edge. If misaligned, adjust with:
|
||||
@ -135,26 +144,38 @@ lp -d sticker your_file.zpl
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
See `printer-troubleshooting/` directory for detailed guides and test prints.
|
||||
|
||||
**Problem: Ribbon pools/doesn't wind onto uptake spool**
|
||||
- Solution: Make sure you ran `^MNN,Y` (uptake enabled)
|
||||
- Factory reset and reconfigure if needed
|
||||
|
||||
**Problem: Checkerboard/dithered areas darker than solid black**
|
||||
- Solution: DECREASE darkness (too much heat!)
|
||||
- See `printer-troubleshooting/darkness-troubleshooting.md`
|
||||
|
||||
**Problem: Prints are fuzzy or gray**
|
||||
- Solution: Increase darkness (`^MD20` or higher)
|
||||
- Solution: Increase darkness with `~SD` command (not `^MD`)
|
||||
- Check print head cleanliness (wipe with isopropyl alcohol)
|
||||
|
||||
**Problem: Printing across multiple labels**
|
||||
- Solution: Re-run physical calibration (2-blink method)
|
||||
- Verify label length matches actual label+gap size
|
||||
|
||||
**Problem: Resin sticks to label when peeling**
|
||||
- Solution: Decrease darkness (`^MD15` or lower)
|
||||
**Problem: Resin sticks to label or ribbon tears**
|
||||
- Solution: Decrease darkness significantly
|
||||
- Ensure print speed isn't too slow: `echo "^XA^PR4^JUS^XZ" | lp -d sticker`
|
||||
|
||||
**Problem: ZPL file doesn't print (but simple commands work)**
|
||||
- Solution: Use `-o raw` flag: `lp -d sticker -o raw file.zpl`
|
||||
|
||||
**Problem: ZPL commands print as literal text**
|
||||
- Solution: Printer isn't configured as raw queue
|
||||
- Reconfigure: `sudo lpadmin -p sticker -m raw`
|
||||
|
||||
**Problem: Blank labels after adjusting darkness**
|
||||
- Solution: May have corrupted ^MD offset - see darkness troubleshooting guide
|
||||
|
||||
### Complete Configuration Script
|
||||
|
||||
Save this as a shell script for easy re-setup:
|
||||
@ -175,12 +196,12 @@ echo "Setting label dimensions (2.25\" x 1.25\")..."
|
||||
echo "^XA^PW675^LL375^JUS^XZ" | lp -d $PRINTER_NAME
|
||||
sleep 2
|
||||
|
||||
echo "Setting darkness to 18..."
|
||||
echo "^XA^MD18^JUS^XZ" | lp -d $PRINTER_NAME
|
||||
echo "Setting darkness to 10 (adjust as needed)..."
|
||||
echo "^XA~SD10^JUS^XZ" | lp -d $PRINTER_NAME
|
||||
sleep 2
|
||||
|
||||
echo "Configuration complete. Run physical calibration (2-blink method) now."
|
||||
echo "Test with: echo \"^XA^PW675^LL375^MD18^FO50,50^ADN,36,20^FDTest^FS^XZ\" | lp -d $PRINTER_NAME"
|
||||
echo "Test with: echo \"^XA^PW675^LL375~SD10^FO50,50^ADN,36,20^FDTest^FS^XZ\" | lp -d $PRINTER_NAME"
|
||||
```
|
||||
|
||||
### Quick Reference: Common ZPL Commands
|
||||
@ -188,7 +209,8 @@ echo "Test with: echo \"^XA^PW675^LL375^MD18^FO50,50^ADN,36,20^FDTest^FS^XZ\" |
|
||||
- `^XA` / `^XZ` - Start/end ZPL command block
|
||||
- `^PW###` - Print width in dots
|
||||
- `^LL###` - Label length in dots
|
||||
- `^MD##` - Darkness (0-30)
|
||||
- `~SD##` - Darkness absolute (0-30) - USE THIS
|
||||
- `^MD##` - Darkness relative (-30 to +30) - AVOID (stacks!)
|
||||
- `^FO###,###` - Field origin (X,Y position in dots)
|
||||
- `^ADN,H,W` - Font: N=default, H=height, W=width
|
||||
- `^FD` - Field data (the actual text/content)
|
||||
|
||||
Reference in New Issue
Block a user