DESKTOP-064TTA1\Fai LUK 1 день назад
Родитель
Сommit
3efe301f8a
3 измененных файлов: 176 добавлений и 21 удалений
  1. +167
    -21
      python/Bag2.py
  2. Двоичные данные
      python/__pycache__/Bag2.cpython-313.pyc
  3. +9
    -0
      python/bag2_settings.json

+ 167
- 21
python/Bag2.py Просмотреть файл

@@ -730,6 +730,130 @@ def laser_push_loop(
pass


def run_laser_continuous_print(
root: tk.Tk,
laser_conn_ref: list,
laser_thread_ref: list,
laser_stop_ref: list,
ip: str,
port: int,
item_id: Optional[int],
stock_in_line_id: Optional[int],
item_code: str,
item_name: str,
set_status_message: Callable[[str, bool], None],
) -> None:
"""
Laser continuous send (連續 C) in a background thread.
User can stop via Stop button or keyboard: `Esc` / `Q`.
"""
# Stop any previous continuous run.
if laser_stop_ref[0] is not None:
try:
laser_stop_ref[0].set()
except Exception:
pass

stop_event = threading.Event()
laser_stop_ref[0] = stop_event

win = tk.Toplevel(root)
win.title("激光機 連續列印")
win.geometry("360x170")
win.transient(root)
win.configure(bg=BG_TOP)

ttk.Label(
win,
text="連續送出中,按「停止」或 Esc / Q 結束",
font=get_font(FONT_SIZE),
background=BG_TOP,
).pack(pady=(14, 8))

count_lbl = tk.Label(win, text="已送出:0 次", font=get_font(FONT_SIZE), bg=BG_TOP)
count_lbl.pack(pady=6)

# Ensure stop keys work even if focus is on the main window.
def _unbind_stop_keys() -> None:
try:
root.unbind_all("<Escape>")
root.unbind_all("<KeyPress-q>")
root.unbind_all("<KeyPress-Q>")
except Exception:
pass

def on_stop() -> None:
if stop_event.is_set():
return
stop_event.set()
_unbind_stop_keys()
try:
win.destroy()
except Exception:
pass

def _key_stop(_e: tk.Event) -> str:
on_stop()
return "break"

root.bind_all("<Escape>", _key_stop)
root.bind_all("<KeyPress-q>", _key_stop)
root.bind_all("<KeyPress-Q>", _key_stop)

ttk.Button(win, text="停止", command=on_stop, width=12).pack(pady=10)
win.protocol("WM_DELETE_WINDOW", on_stop)

def worker() -> None:
sent = 0
try:
while not stop_event.is_set():
ok, msg = send_job_to_laser_with_retry(
laser_conn_ref,
ip,
port,
item_id,
stock_in_line_id,
item_code,
item_name,
)
if not ok:
root.after(0, lambda m=msg: set_status_message(f"連續送出失敗:{m}", is_error=True))
break

sent += 1
root.after(0, lambda s=sent: count_lbl.configure(text=f"已送出:{s} 次"))

# Small delay between sends; check stop frequently.
for _ in range(4): # 4 * 0.05 = 0.20 sec
if stop_event.is_set():
break
time.sleep(0.05)
except Exception as e:
root.after(0, lambda err=str(e): set_status_message(f"連續送出意外錯誤:{err}", is_error=True))
finally:
_unbind_stop_keys()
if not stop_event.is_set():
# Failure path ended the worker; keep window close.
try:
win.destroy()
except Exception:
pass
else:
# Stopped intentionally.
root.after(0, lambda s=sent: set_status_message(f"已停止激光機連續送出:{s} 次", is_error=False))

laser_stop_ref[0] = None
laser_thread_ref[0] = None
try:
win.destroy()
except Exception:
pass

t = threading.Thread(target=worker, daemon=True)
laser_thread_ref[0] = t
t.start()


def send_job_to_laser(
conn_ref: list,
ip: str,
@@ -740,16 +864,23 @@ def send_job_to_laser(
item_name: str,
) -> tuple[bool, str]:
"""
Send to laser. Standard format: {"itemId": xxx, "stockInLineId": xxx}.
Send to laser using `;` separated 3 params:
{"itemID": itemId, "stockInLineId": stockInLineId} ; itemCode ; itemName ;;
conn_ref: [socket or None] - reused across calls; closed only when switching printer.
When both item_id and stock_in_line_id present, sends JSON; else fallback: 0;item_code;item_name;;
When both item_id and stock_in_line_id present, sends JSON first param; else fallback: 0;item_code;item_name;;
Returns (success, message).
"""
code_str = (item_code or "").strip().replace(";", ",")
name_str = (item_name or "").strip().replace(";", ",")

if item_id is not None and stock_in_line_id is not None:
reply = json.dumps({"itemId": item_id, "stockInLineId": stock_in_line_id})
# Use compact JSON so device-side parser doesn't get spaces.
json_part = json.dumps(
{"itemID": item_id, "stockInLineId": stock_in_line_id},
separators=(",", ":"),
)
reply = f"{json_part};{code_str};{name_str};;"
else:
code_str = (item_code or "").strip().replace(";", ",")
name_str = (item_name or "").strip().replace(";", ",")
reply = f"0;{code_str};{name_str};;"
conn = conn_ref[0]
try:
@@ -1487,23 +1618,38 @@ def main() -> None:
stock_in_line_id = j.get("stockInLineId")
item_code_val = j.get("itemCode") or ""
item_name_val = j.get("itemName") or ""
n = 100 if count == -1 else count
sent = 0
for i in range(n):
ok, msg = send_job_to_laser_with_retry(
laser_conn_ref, ip, port,
item_id, stock_in_line_id,
item_code_val, item_name_val,
if count == -1:
run_laser_continuous_print(
root=root,
laser_conn_ref=laser_conn_ref,
laser_thread_ref=laser_thread_ref,
laser_stop_ref=laser_stop_ref,
ip=ip,
port=port,
item_id=item_id,
stock_in_line_id=stock_in_line_id,
item_code=item_code_val,
item_name=item_name_val,
set_status_message=set_status_message,
)
if ok:
sent += 1
else:
set_status_message(f"已送出 {sent} 次,第 {sent + 1} 次失敗:{msg}", is_error=True)
break
if i < n - 1:
time.sleep(0.2)
if sent == n:
set_status_message(f"已送出激光機:{sent} 次", is_error=False)
else:
n = count
sent = 0
for i in range(n):
ok, msg = send_job_to_laser_with_retry(
laser_conn_ref, ip, port,
item_id, stock_in_line_id,
item_code_val, item_name_val,
)
if ok:
sent += 1
else:
set_status_message(f"已送出 {sent} 次,第 {sent + 1} 次失敗:{msg}", is_error=True)
break
if i < n - 1:
time.sleep(0.2)
if sent == n:
set_status_message(f"已送出激光機:{sent} 次", is_error=False)

for w in (row, left, batch_lbl, code_lbl, name_lbl):
w.bind("<Button-1>", _on_click)


Двоичные данные
python/__pycache__/Bag2.cpython-313.pyc Просмотреть файл


+ 9
- 0
python/bag2_settings.json Просмотреть файл

@@ -0,0 +1,9 @@
{
"api_ip": "10.10.0.81",
"api_port": "8090",
"dabag_ip": "192.168.18.27",
"dabag_port": "3008",
"laser_ip": "192.168.18.77",
"laser_port": "45678",
"label_com": "TSC TTP-246M Pro"
}

Загрузка…
Отмена
Сохранить