# -*- coding: utf-8 -*- """ CNC Bağlantı Sihirbazı (GUI) — komut satırı YOK. IP + port + tip gir → "Bağlan" → laptop IP otomatik ayarlanır + dosyalar iner + okuyucu çalışır. Çalıştırmak için sağ tık → "Yönetici olarak çalıştır" (laptop IP'sini değiştirmek için admin gerekir). """ import tkinter as tk from tkinter import messagebox import subprocess import urllib.request import zipfile import os import threading import ctypes VPS = "https://cnc.sifirmakina.com.tr" MASAUSTU = os.path.join(os.path.expanduser("~"), "Desktop") def admin_mi(): try: return ctypes.windll.shell32.IsUserAnAdmin() == 1 except Exception: return False def ethernet_bul(): try: c = subprocess.run('netsh interface show interface', shell=True, capture_output=True, text=True).stdout for s in c.splitlines(): if 'Ethernet' in s and ('Etkin' in s or 'Bağlı' in s or 'Enabled' in s): p = s.split() if len(p) >= 4: return p[3] except Exception: pass return 'Ethernet' def ip_ayarla(ip, subnet='255.255.128.0'): a = ethernet_bul() r = subprocess.run(f'netsh interface ipv4 set address name="{a}" static {ip} {subnet}', shell=True, capture_output=True, text=True) return r.returncode == 0, a, r.stderr.strip()[:150] def indir(url, dosya): urllib.request.urlretrieve(url, dosya) def dosya_ip_yaz(yol, ip, port): try: with open(yol, encoding='utf-8') as f: c = f.read() c = c.replace('MAKINE_IP = "192.168.5.91"', f'MAKINE_IP = "{ip}"') c = c.replace('MAKINE_IP = "192.168.1.1"', f'MAKINE_IP = "{ip}"') c = c.replace('FOCAS_PORT = 9999', f'FOCAS_PORT = {port}') c = c.replace('FOCAS_PORT = 8193', f'FOCAS_PORT = {port}') c = c.replace('PORT = 5007', f'PORT = {port}') c = c.replace('PORT = 5001', f'PORT = {port}') with open(yol, 'w', encoding='utf-8') as f: f.write(c) except Exception: pass def calistir(tip, ip, port, log): laptop_ip = '.'.join(ip.split('.')[:3]) + '.100' log('1/3 · Laptop IP aynı ağa ayarlanıyor: ' + laptop_ip) ok, adapter, hata = ip_ayarla(laptop_ip) if ok: log(' ✓ Laptop IP: ' + laptop_ip + ' (' + adapter + ')') else: log(' ! IP ayarlanamadı (admin gerekli): ' + hata) log(' → Programı "Yönetici olarak çalıştır" ile aç.') log('2/3 · Dosyalar indiriliyor...') if tip == '1': z = os.path.join(MASAUSTU, 'fwlib_tum.zip') indir(VPS + '/fwlib_tum.zip', z) with zipfile.ZipFile(z) as zf: zf.extractall(MASAUSTU) log(' ✓ 14 DLL çıkarıldı') oku = os.path.join(MASAUSTU, 'focas_okuyucu.py') indir(VPS + '/focas_okuyucu.py', oku) dosya_ip_yaz(oku, ip, port) log(' ✓ focas_okuyucu.py hazır') log('3/3 · Okuyucu başlatılıyor (devir + alarm + eksen + I/O)...') subprocess.Popen('start "CNC Okuyucu" cmd /k py -3-32 "' + oku + '"', shell=True, cwd=MASAUSTU) else: oku = os.path.join(MASAUSTU, 'melsec_test.py') indir(VPS + '/melsec_test.py', oku) dosya_ip_yaz(oku, ip, port) log(' ✓ melsec_test.py hazır') log('3/3 · Okuyucu başlatılıyor...') subprocess.Popen('start "CNC Okuyucu" cmd /k python "' + oku + '"', shell=True, cwd=MASAUSTU) log('✓ Tamam. Dashboard → Canlı Makine Verisi → makineyi seç.') def baglan_click(): tip = tip_var.get() ip = ip_entry.get().strip() port = port_entry.get().strip() if not ip or not port: messagebox.showwarning('Eksik bilgi', 'Makine IP ve port girin.') return durum.set('Bağlanıyor...') btn.config(state='disabled') def is_(): try: calistir(tip, ip, port, log) except Exception as e: log('HATA: ' + str(e)) btn.config(state='normal') durum.set('Hazır') threading.Thread(target=is_, daemon=True).start() def log(m): txt.config(state='normal') txt.insert('end', m + '\n') txt.see('end') txt.config(state='disabled') # ============ ARAYÜZ ============ root = tk.Tk() root.title('CNC Bağlantı Sihirbazı') root.geometry('500x440') root.configure(bg='#0f172a') f = tk.Frame(root, bg='#0f172a') f.pack(pady=20, padx=20, fill='x') tk.Label(f, text='CNC Bağlantı Sihirbazı', font=('Segoe UI', 16, 'bold'), bg='#0f172a', fg='#fbbf24').pack(anchor='w') tk.Label(f, text='Makine bilgilerini gir, Bağlan\'a bas — gerisi otomatik.', font=('Segoe UI', 10), bg='#0f172a', fg='#94a3b8').pack(anchor='w', pady=(0, 14)) tk.Label(f, text='Bağlantı tipi', font=('Segoe UI', 10), bg='#0f172a', fg='#cbd5e1').pack(anchor='w') tip_var = tk.StringVar(value='2') tip_menu = tk.OptionMenu(f, tip_var, '1', '2') tip_menu.config(bg='#1e293b', fg='#e2e8f0', activebackground='#2563eb', width=28) tip_menu['menu'].config(bg='#1e293b', fg='#e2e8f0') tip_menu.pack(anchor='w', fill='x', pady=(2, 8)) # tip etiketi ayrı göster tk.Label(f, text='(1 = Fanuc FOCAS · 2 = Mitsubishi MELSEC)', font=('Segoe UI', 9), bg='#0f172a', fg='#64748b').pack(anchor='w', pady=(0, 10)) tk.Label(f, text='Makine IP', font=('Segoe UI', 10), bg='#0f172a', fg='#cbd5e1').pack(anchor='w') ip_entry = tk.Entry(f, bg='#1e293b', fg='#e2e8f0', insertbackground='#e2e8f0', relief='flat', font=('Segoe UI', 11)) ip_entry.pack(anchor='w', fill='x', ipady=6, pady=(2, 8)) ip_entry.insert(0, '192.168.200.1') tk.Label(f, text='Port', font=('Segoe UI', 10), bg='#0f172a', fg='#cbd5e1').pack(anchor='w') port_entry = tk.Entry(f, bg='#1e293b', fg='#e2e8f0', insertbackground='#e2e8f0', relief='flat', font=('Segoe UI', 11)) port_entry.pack(anchor='w', fill='x', ipady=6, pady=(2, 14)) port_entry.insert(0, '5007') durum = tk.StringVar(value='Hazır') btn = tk.Button(f, text='🔌 Bağlan', command=baglan_click, bg='#2563eb', fg='#ffffff', font=('Segoe UI', 12, 'bold'), relief='flat', activebackground='#1d4ed8', activeforeground='#ffffff', cursor='hand2', pady=8) btn.pack(anchor='w', fill='x') tk.Label(root, textvariable=durum, font=('Segoe UI', 9), bg='#0f172a', fg='#4ade80').pack(anchor='w', padx=20) log_frame = tk.Frame(root, bg='#0f172a') log_frame.pack(fill='both', expand=True, padx=20, pady=(8, 16)) txt = tk.Text(log_frame, bg='#1e293b', fg='#e2e8f0', relief='flat', font=('Consolas', 9), state='disabled', height=10) txt.pack(fill='both', expand=True) if not admin_mi(): log('UYARI: Yönetici değil. IP değiştirme için programı sağ tık → "Yönetici olarak çalıştır" ile aç.') root.mainloop()