messing around, im good at git hehe jk
This commit is contained in:
BIN
drawing (copy 1).png
Normal file
BIN
drawing (copy 1).png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
1507
kiosk-pre-curosr.py
Normal file
1507
kiosk-pre-curosr.py
Normal file
File diff suppressed because it is too large
Load Diff
175
kiosk.py
175
kiosk.py
@ -20,6 +20,78 @@ import re # Import re for regular expression matching
|
||||
import os
|
||||
import shutil
|
||||
import hashlib
|
||||
import glob
|
||||
import traceback
|
||||
|
||||
|
||||
def get_preferred_camera_index(preferred_name_fragment=None):
|
||||
"""
|
||||
Try to find a stable camera index for an external webcam.
|
||||
|
||||
Strategy (Linux):
|
||||
- Look in /dev/v4l/by-id, which has stable, human‑readable symlinks.
|
||||
- If `preferred_name_fragment` is provided, pick the first device whose
|
||||
name contains that fragment.
|
||||
- Otherwise, prefer devices whose name looks like an external USB webcam.
|
||||
- Fall back to the lowest working index (usually the built‑in camera).
|
||||
|
||||
You can customize behaviour by passing a string like "Logitech" or by
|
||||
changing the heuristics below.
|
||||
"""
|
||||
by_id_dir = "/dev/v4l/by-id"
|
||||
|
||||
try:
|
||||
if os.path.isdir(by_id_dir):
|
||||
paths = sorted(glob.glob(os.path.join(by_id_dir, "*")))
|
||||
if paths:
|
||||
# Optionally filter by a user‑specified name fragment
|
||||
if preferred_name_fragment:
|
||||
name_fragment = preferred_name_fragment.lower()
|
||||
candidate_paths = [
|
||||
p for p in paths if name_fragment in os.path.basename(p).lower()
|
||||
]
|
||||
if not candidate_paths:
|
||||
candidate_paths = paths
|
||||
else:
|
||||
candidate_paths = paths
|
||||
|
||||
# Heuristic: prefer names that look like external USB webcams
|
||||
# (often contain "usb-" but are not clearly an integrated camera)
|
||||
usb_like = [
|
||||
p
|
||||
for p in candidate_paths
|
||||
if "usb-" in os.path.basename(p).lower()
|
||||
]
|
||||
# If that filter gives us something, use it, otherwise use all
|
||||
candidate_paths = usb_like or candidate_paths
|
||||
|
||||
for path in candidate_paths:
|
||||
target = os.path.realpath(path) # e.g. /dev/video2
|
||||
m = re.search(r"video(\d+)", target)
|
||||
if not m:
|
||||
continue
|
||||
idx = int(m.group(1))
|
||||
cap = cv2.VideoCapture(idx)
|
||||
if cap.isOpened():
|
||||
cap.release()
|
||||
print(f"Selected camera index {idx} from {path}")
|
||||
return idx
|
||||
cap.release()
|
||||
except Exception as e:
|
||||
print(f"Error while trying to select preferred camera: {e}")
|
||||
|
||||
# Fallback: probe a small range of indices and pick the first that works
|
||||
for idx in range(0, 6):
|
||||
cap = cv2.VideoCapture(idx)
|
||||
if cap.isOpened():
|
||||
cap.release()
|
||||
print(f"Falling back to first working camera index: {idx}")
|
||||
return idx
|
||||
cap.release()
|
||||
|
||||
# Absolute fallback if nothing opens
|
||||
print("No working camera found; defaulting to index 0")
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@ -46,7 +118,7 @@ class Kiosk(tk.Tk):
|
||||
self.config(cursor="crosshair")
|
||||
self.QRX = None
|
||||
self.QRY = None
|
||||
self.QRscale = 1
|
||||
self.QRscale = 3
|
||||
|
||||
# Initialize fonts
|
||||
GlobalVars.BUTTON_FONT = tkfont.Font(size=24, family='Helvetica')
|
||||
@ -79,19 +151,19 @@ class Kiosk(tk.Tk):
|
||||
global MIGRATION_ITEMS_DIR
|
||||
|
||||
# Check if migration_ticket is defined
|
||||
if 'migration_ticket' in globals():
|
||||
#if 'migration_ticket' in globals():
|
||||
# Delete any existing migration files
|
||||
if migration_ticket:
|
||||
text_file = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
image_file = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
# if migration_ticket:
|
||||
# text_file = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
# image_file = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
|
||||
if os.path.exists(text_file):
|
||||
os.remove(text_file)
|
||||
if os.path.exists(image_file):
|
||||
os.remove(image_file)
|
||||
# if os.path.exists(text_file):
|
||||
# os.remove(text_file)
|
||||
# if os.path.exists(image_file):
|
||||
# os.remove(image_file)
|
||||
|
||||
# Reset migration_ticket
|
||||
migration_ticket = ""
|
||||
# migration_ticket = ""
|
||||
|
||||
# Reset other global variables
|
||||
GlobalVars.qr_code_value = None
|
||||
@ -127,10 +199,11 @@ class Screen0(tk.Frame):
|
||||
|
||||
|
||||
|
||||
# tk.Button(right_frame, text="Create Item", command=lambda: master.switch_frame(Screen1), height=4, width=75, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
tk.Button(right_frame, text="Create Item", command=lambda: master.switch_frame(Screen1), height=4, width=75, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
|
||||
# Button for Migration mode
|
||||
tk.Button(right_frame, text="Create Item", command=lambda: master.switch_frame(Screen15), height=4, width=75, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
#tk.Button(right_frame, text="Create Item", command=lambda: master.switch_frame(Screen15), height=4, width=75, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
|
||||
tk.Button(right_frame, text="Lookup Item", command=lambda: master.switch_frame(Screen14), height=4, width=75, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
|
||||
# Create the quit button
|
||||
@ -426,7 +499,8 @@ class Screen3(tk.Frame):
|
||||
home_button = tk.Button(text="Start Over", command=self.show_warning_dialog, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
home_button.place(x=0, y=0) # top-left corner
|
||||
|
||||
self.vid = cv2.VideoCapture(2)
|
||||
# Prefer the external NexiGo USB webcam when available
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index("NexiGo"))
|
||||
self.is_capturing = True
|
||||
self.freeze_frame = None
|
||||
|
||||
@ -455,7 +529,8 @@ class Screen3(tk.Frame):
|
||||
self.__del__()
|
||||
self.master.switch_frame(Screen0)
|
||||
|
||||
self.vid = cv2.VideoCapture(2)
|
||||
# Prefer the external NexiGo USB webcam when available
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index("NexiGo"))
|
||||
self.is_capturing = True
|
||||
self.freeze_frame = None
|
||||
|
||||
@ -488,7 +563,8 @@ class Screen3(tk.Frame):
|
||||
home_button = tk.Button(text="Start Over", command=self.show_warning_dialog, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
home_button.place(x=0, y=0) # top-left corner
|
||||
|
||||
self.vid = cv2.VideoCapture(2)
|
||||
# Prefer the external NexiGo USB webcam when available
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index("NexiGo"))
|
||||
self.is_capturing = True
|
||||
self.freeze_frame = None
|
||||
self.countdown_text = None
|
||||
@ -575,14 +651,14 @@ class Screen3(tk.Frame):
|
||||
global MIGRATION_ITEMS_DIR
|
||||
|
||||
# If migration_ticket is set, copy the photo to MIGRATION_ITEMS_DIR
|
||||
if migration_ticket:
|
||||
source_path = 'freeze_frame.jpg'
|
||||
destination_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
try:
|
||||
shutil.copy2(source_path, destination_path)
|
||||
print(f"Photo saved as {destination_path}")
|
||||
except Exception as e:
|
||||
print(f"Error saving photo: {e}")
|
||||
#if migration_ticket:
|
||||
# source_path = 'freeze_frame.jpg'
|
||||
# destination_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
# try:
|
||||
# shutil.copy2(source_path, destination_path)
|
||||
# print(f"Photo saved as {destination_path}")
|
||||
#except Exception as e:
|
||||
# print(f"Error saving photo: {e}")
|
||||
|
||||
self.release_resources()
|
||||
self.master.switch_frame(Screen5)
|
||||
@ -632,7 +708,7 @@ class Screen4(tk.Frame):
|
||||
|
||||
# Set initial drawing color to black and size to 1
|
||||
self.draw_color = 'black'
|
||||
self.draw_size = 1
|
||||
self.draw_size = 3
|
||||
|
||||
# Creating the Canvas for drawing
|
||||
self.canvas = Canvas(self.left_frame, width=650, height=360, bg='white')
|
||||
@ -751,7 +827,7 @@ class Screen4(tk.Frame):
|
||||
self.draw = ImageDraw.Draw(self.drawing)
|
||||
self.add_qr_box()
|
||||
|
||||
def add_qr_box(self, x=506, y=217, size=1):
|
||||
def add_qr_box(self, x=506, y=217, size=3):
|
||||
box_size = 37 * size
|
||||
self.canvas.create_rectangle(x, y, x + box_size, y + box_size, outline='black', fill='white')
|
||||
self.canvas.create_text(x + box_size/2, y + box_size/2, text="QR", fill="black")
|
||||
@ -831,24 +907,24 @@ class Screen5(tk.Frame):
|
||||
info_text = info_text.replace('\n', '\\n')
|
||||
|
||||
# If migration_ticket is set (not empty), save the text and image to MIGRATION_ITEMS_DIR
|
||||
if migration_ticket:
|
||||
#if migration_ticket:
|
||||
# Save text
|
||||
text_file_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
try:
|
||||
with open(text_file_path, 'w') as f:
|
||||
f.write(info_text)
|
||||
print(f"Text saved as {text_file_path}")
|
||||
except Exception as e:
|
||||
print(f"Error saving text: {e}")
|
||||
# text_file_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
# try:
|
||||
# with open(text_file_path, 'w') as f:
|
||||
# f.write(info_text)
|
||||
# print(f"Text saved as {text_file_path}")
|
||||
# except Exception as e:
|
||||
# print(f"Error saving text: {e}")
|
||||
|
||||
# Save image
|
||||
source_image_path = 'freeze_frame.jpg'
|
||||
destination_image_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
try:
|
||||
shutil.copy2(source_image_path, destination_image_path)
|
||||
print(f"Photo saved as {destination_image_path}")
|
||||
except Exception as e:
|
||||
print(f"Error saving photo: {e}")
|
||||
# source_image_path = 'freeze_frame.jpg'
|
||||
# destination_image_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
# try:
|
||||
# shutil.copy2(source_image_path, destination_image_path)
|
||||
# print(f"Photo saved as {destination_image_path}")
|
||||
# except Exception as e:
|
||||
# print(f"Error saving photo: {e}")
|
||||
|
||||
self.master.switch_frame(Screen11)
|
||||
|
||||
@ -1271,14 +1347,14 @@ class Screen13(tk.Frame):
|
||||
key = addtoDB.addToSSB(path_to_image, info_text, 1)
|
||||
|
||||
# If we have a migration ticket, append the message ID to the description file
|
||||
if migration_ticket:
|
||||
description_file_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
try:
|
||||
with open(description_file_path, 'a') as f:
|
||||
f.write(f"\n\n\n{key}")
|
||||
print(f"Appended message ID to description file: {description_file_path}")
|
||||
except Exception as e:
|
||||
print(f"Error appending message ID to description file: {e}")
|
||||
#if migration_ticket:
|
||||
# description_file_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
# try:
|
||||
# with open(description_file_path, 'a') as f:
|
||||
# f.write(f"\n\n\n{key}")
|
||||
# print(f"Appended message ID to description file: {description_file_path}")
|
||||
# except Exception as e:
|
||||
# print(f"Error appending message ID to description file: {e}")
|
||||
|
||||
# ssb give! (make sure we have a UID to give to first)
|
||||
if GlobalVars.selected_user and GlobalVars.selected_user.strip() != "":
|
||||
@ -1404,7 +1480,8 @@ class Screen14(tk.Frame):
|
||||
self.cancel_button.pack(pady=20)
|
||||
|
||||
self.qreader = QReader()
|
||||
self.cap = cv2.VideoCapture(2)
|
||||
# Prefer the external NexiGo USB webcam when available
|
||||
self.cap = cv2.VideoCapture(get_preferred_camera_index("NexiGo"))
|
||||
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
|
||||
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
|
||||
|
||||
|
||||
135
tozpl (copy 1).py
Normal file
135
tozpl (copy 1).py
Normal file
@ -0,0 +1,135 @@
|
||||
#this code was converted to python from http://www.jcgonzalez.com/java-image-to-zpl-example by chatgpt and trav. We modified it together a bit to only accept black and white images :)
|
||||
|
||||
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
|
||||
class ZPLConveter:
|
||||
def __init__(self):
|
||||
self.total = 0
|
||||
self.width_bytes = 0
|
||||
self.compress_hex = False
|
||||
self.map_code = {1: 'G', 2: 'H', 3: 'I', 4: 'J', 5: 'K', 6: 'L', 7: 'M', 8: 'N',
|
||||
9: 'O', 10: 'P', 11: 'Q', 12: 'R', 13: 'S', 14: 'T', 15: 'U', 16: 'V',
|
||||
17: 'W', 18: 'X', 19: 'Y', 20: 'g', 40: 'h', 60: 'i', 80: 'j', 100: 'k',
|
||||
120: 'l', 140: 'm', 160: 'n', 180: 'o', 200: 'p', 220: 'q', 240: 'r',
|
||||
260: 's', 280: 't', 300: 'u', 320: 'v', 340: 'w', 360: 'x', 380: 'y',
|
||||
400: 'z'}
|
||||
|
||||
def convert_from_img(self, img_path):
|
||||
image = Image.open(img_path)
|
||||
cuerpo = self.create_body(image)
|
||||
if self.compress_hex:
|
||||
cuerpo = self.encode_hex_ascii(cuerpo)
|
||||
return self.head_doc() + cuerpo + self.foot_doc()
|
||||
|
||||
def create_body(self, image):
|
||||
width, height = image.size
|
||||
orginal_image = np.array(image)
|
||||
index = 0
|
||||
aux_binary_char = ['0', '0', '0', '0', '0', '0', '0', '0']
|
||||
self.width_bytes = width // 8
|
||||
if width % 8 > 0:
|
||||
self.width_bytes = ((width // 8) + 1)
|
||||
else:
|
||||
self.width_bytes = width // 8
|
||||
self.total = self.width_bytes * height
|
||||
sb = []
|
||||
for h in range(height):
|
||||
for w in range(width):
|
||||
pixel = orginal_image[h, w]
|
||||
aux_char = '1' if pixel == 0 else '0' # 0 for black, 1 for white
|
||||
aux_binary_char[index] = aux_char
|
||||
index += 1
|
||||
if index == 8 or w == (width - 1):
|
||||
sb.append(self.four_byte_binary(''.join(aux_binary_char)))
|
||||
aux_binary_char = ['0', '0', '0', '0', '0', '0', '0', '0']
|
||||
index = 0
|
||||
sb.append("\n")
|
||||
return ''.join(sb)
|
||||
|
||||
@staticmethod
|
||||
def four_byte_binary(binary_str):
|
||||
decimal = int(binary_str, 2)
|
||||
if decimal > 15:
|
||||
return hex(decimal)[2:].upper()
|
||||
else:
|
||||
return "0" + hex(decimal)[2:].upper()
|
||||
|
||||
|
||||
def encode_hex_ascii(self, code):
|
||||
maxlinea = self.width_bytes * 2
|
||||
sb_code = []
|
||||
sb_linea = []
|
||||
previous_line = None
|
||||
counter = 1
|
||||
aux = code[0]
|
||||
first_char = False
|
||||
for i in range(1, len(code)):
|
||||
if first_char:
|
||||
aux = code[i]
|
||||
first_char = False
|
||||
continue
|
||||
if code[i] == '\n':
|
||||
if counter >= maxlinea and aux == '0':
|
||||
sb_linea.append(",")
|
||||
elif counter >= maxlinea and aux == 'F':
|
||||
sb_linea.append("!")
|
||||
elif counter > 20:
|
||||
multi20 = (counter // 20) * 20
|
||||
resto20 = (counter % 20)
|
||||
sb_linea.append(self.map_code[multi20])
|
||||
if resto20 != 0:
|
||||
sb_linea.append(self.map_code[resto20] + aux)
|
||||
else:
|
||||
sb_linea.append(aux)
|
||||
else:
|
||||
sb_linea.append(self.map_code[counter] + aux)
|
||||
counter = 1
|
||||
first_char = True
|
||||
if ''.join(sb_linea) == previous_line:
|
||||
sb_code.append(":")
|
||||
else:
|
||||
sb_code.append(''.join(sb_linea))
|
||||
previous_line = ''.join(sb_linea)
|
||||
sb_linea = []
|
||||
continue
|
||||
if aux == code[i]:
|
||||
counter += 1
|
||||
else:
|
||||
if counter > 20:
|
||||
multi20 = (counter // 20) * 20
|
||||
resto20 = (counter % 20)
|
||||
sb_linea.append(self.map_code[multi20])
|
||||
if resto20 != 0:
|
||||
sb_linea.append(self.map_code[resto20] + aux)
|
||||
else:
|
||||
sb_linea.append(aux)
|
||||
else:
|
||||
sb_linea.append(self.map_code[counter] + aux)
|
||||
counter = 1
|
||||
aux = code[i]
|
||||
return ''.join(sb_code)
|
||||
|
||||
def head_doc(self):
|
||||
return "^XA " + "^FO0,0^GFA," + str(self.total) + "," + str(self.total) + "," + str(self.width_bytes) + ", "
|
||||
|
||||
@staticmethod
|
||||
def foot_doc():
|
||||
return "^FS" + "^XZ"
|
||||
|
||||
def set_compress_hex(self, compress_hex):
|
||||
self.compress_hex = compress_hex
|
||||
|
||||
def set_blackness_limit_percentage(self, percentage):
|
||||
self.black_limit = (percentage * 768 // 100)
|
||||
|
||||
def print_to_zpl(img_path):
|
||||
converter = ZPLConveter()
|
||||
converter.set_compress_hex(True)
|
||||
return converter.convert_from_img(img_path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
zp = ZPLConveter()
|
||||
zp.set_compress_hex(True)
|
||||
#print(zp.convert_from_img("drawing.png"))
|
||||
Reference in New Issue
Block a user