| | |
| | import sys |
| | import os |
| | import platform |
| | import subprocess |
| | import shutil |
| | from pathlib import Path |
| | import socket |
| | from fastapi import FastAPI,Body |
| | import uvicorn |
| | from smartcard.System import readers |
| |
|
| | |
| | |
| | |
| | if sys.stdout is None: |
| | sys.stdout = open(os.devnull, 'w') |
| | if sys.stderr is None: |
| | sys.stderr = open(os.devnull, 'w') |
| |
|
| | |
| | |
| | |
| | def add_to_login_items(app_path): |
| | """Add macOS app to Login Items using AppleScript.""" |
| | absolute_app_path = os.path.abspath(app_path) |
| | if not os.path.exists(absolute_app_path): |
| | print(f"Error: Application not found at '{absolute_app_path}'") |
| | return |
| |
|
| | script = f''' |
| | tell application "System Events" |
| | make new login item at end with properties {{path:"{absolute_app_path}", hidden:false}} |
| | end tell |
| | ''' |
| | try: |
| | subprocess.run( |
| | ['osascript', '-e', script], |
| | check=True, |
| | capture_output=True, |
| | text=True |
| | ) |
| | print("✅ Successfully added to Login Items.") |
| | except subprocess.CalledProcessError as e: |
| | print(f"Error adding to Login Items: {e.stderr}") |
| | except FileNotFoundError: |
| | print("Error: 'osascript' not found. Must be run on macOS.") |
| |
|
| | |
| | |
| | |
| | def thai2unicode(data): |
| | resp = '' |
| | if isinstance(data, list): |
| | resp = bytes(data).decode('tis-620').replace('#', ' ') |
| | return resp.strip() |
| | else: |
| | return data |
| |
|
| | def getData(connection, cmd, req=[0x00, 0xc0, 0x00, 0x00]): |
| | data, sw1, sw2 = connection.transmit(cmd) |
| | data, sw1, sw2 = connection.transmit(req + [cmd[-1]]) |
| | return [data, sw1, sw2] |
| |
|
| | |
| | SELECT = [0x00, 0xA4, 0x04, 0x00, 0x08] |
| | THAI_CARD = [0xA0, 0x00, 0x00, 0x00, 0x54, 0x48, 0x00, 0x01] |
| | CMD_CID = [0x80, 0xb0, 0x00, 0x04, 0x02, 0x00, 0x0d] |
| | CMD_THFULLNAME = [0x80, 0xb0, 0x00, 0x11, 0x02, 0x00, 0x64] |
| | CMD_ENFULLNAME = [0x80, 0xb0, 0x00, 0x75, 0x02, 0x00, 0x64] |
| | CMD_BIRTH = [0x80, 0xb0, 0x00, 0xD9, 0x02, 0x00, 0x08] |
| | CMD_GENDER = [0x80, 0xb0, 0x00, 0xE1, 0x02, 0x00, 0x01] |
| | CMD_ISSUER = [0x80, 0xb0, 0x00, 0xF6, 0x02, 0x00, 0x64] |
| | CMD_ISSUE = [0x80, 0xb0, 0x01, 0x67, 0x02, 0x00, 0x08] |
| | CMD_EXPIRE = [0x80, 0xb0, 0x01, 0x6F, 0x02, 0x00, 0x08] |
| | CMD_ADDRESS = [0x80, 0xb0, 0x15, 0x79, 0x02, 0x00, 0x64] |
| |
|
| | |
| | |
| | |
| | def read_card_value(): |
| | try: |
| | readerList = readers() |
| | reader = readerList[0] |
| | connection = reader.createConnection() |
| | connection.connect() |
| | except Exception as e: |
| | print(e) |
| | return False |
| |
|
| | atr = connection.getATR() |
| | req = [0x00, 0xc0, 0x00, 0x01] if (atr[0] == 0x3B & atr[1] == 0x67) else [0x00, 0xc0, 0x00, 0x00] |
| | connection.transmit(SELECT + THAI_CARD) |
| |
|
| | def read_field(cmd): |
| | try: |
| | return thai2unicode(getData(connection, cmd, req)[0]) |
| | except: |
| | return '' |
| |
|
| | cid = read_field(CMD_CID) |
| | th_fullname = read_field(CMD_THFULLNAME) |
| | en_fullname = read_field(CMD_ENFULLNAME) |
| | date_birth = read_field(CMD_BIRTH) |
| | gender = read_field(CMD_GENDER) |
| | card_issuer = read_field(CMD_ISSUER) |
| | issue_date = read_field(CMD_ISSUE) |
| | expire_date = read_field(CMD_EXPIRE) |
| | address = read_field(CMD_ADDRESS) |
| |
|
| | address_list = address.split(' ') |
| | if not address_list or address_list[0] == '': |
| | return False |
| |
|
| | val1 = val2 = val3 = val4 = '' |
| | for e_addr in address_list: |
| | if 'ตำบล' in e_addr: |
| | val1 = e_addr.replace('ตำบล', '') |
| | elif 'อำเภอ' in e_addr: |
| | val2 = e_addr.replace('อำเภอ', '') |
| | elif 'จังหวัด' in e_addr: |
| | val3 = e_addr.replace('จังหวัด', '') |
| | val4 = ' '.join(address_list[:-3]).strip() |
| |
|
| | if cid == '': |
| | return False |
| |
|
| | return { |
| | 'id13': cid, |
| | 'th_fullname': th_fullname, |
| | 'en_fullname': en_fullname, |
| | 'date_birth': date_birth, |
| | 'gender': gender, |
| | 'card_issuer': card_issuer, |
| | 'issue_date': issue_date, |
| | 'expire_date': expire_date, |
| | 'address': val4, |
| | 'subdistrict': val1, |
| | 'district': val2, |
| | 'province': val3 |
| | } |
| |
|
| | |
| | |
| | |
| | def run_initial(): |
| | system = platform.system() |
| | if system == "Windows": |
| | new_folder = Path("C:/Adviceprinter") |
| | new_folder.mkdir(parents=True, exist_ok=True) |
| |
|
| | exe_file = Path.home() / "Downloads" / "Adviceprinter2.exe" |
| | start_path = Path.home() / "AppData" / "Roaming" / "Microsoft" / "Windows" / "Start Menu" / "Programs" / "Startup" |
| | if exe_file.exists(): |
| | shutil.copy(exe_file, new_folder) |
| | shutil.copy(exe_file, start_path) |
| | print(f"✅ Copied {exe_file.name} to {new_folder}") |
| | else: |
| | print(f"⚠️ {exe_file} not found in Downloads.") |
| | elif system == "Darwin": |
| | app_path = "/Applications/Adviceprinter2.app" |
| | add_to_login_items(app_path) |
| | else: |
| | print("Unsupported OS detected. Exiting.") |
| | exit() |
| |
|
| | |
| | |
| | |
| | app = FastAPI(title="Adviceprinter2") |
| |
|
| | @app.get("/") |
| | def service_active(): |
| | return {"status": "running", "message": "Adviceprinter2 is running."} |
| |
|
| | @app.get("/check_card") |
| | def check_card(): |
| | try: |
| | out = read_card_value() |
| | return {"status": "success", "value": out} if out else {"status": "warning", "message": "No smart card inserted."} |
| | except Exception as e: |
| | return {"status": "error", "message": f"Unexpected error: {str(e)}"} |
| |
|
| | @app.get("/get_computername") |
| | def device_hostname(): |
| | try: |
| | hostname = socket.gethostname() |
| | return {"status": "success", "computername": hostname} |
| | except Exception as e: |
| | return {"status": "error", "message": f"Unexpected error: {str(e)}"} |
| |
|
| | |
| | |
| | |
| | if __name__ == "__main__": |
| | system = platform.system() |
| | if system == "Windows": |
| | config_folder = Path("C:/Adviceprinter") |
| | elif system == "Darwin": |
| | config_folder = Path.home() / "Library/Application Support/Adviceprinter" |
| | else: |
| | print("Unsupported OS.") |
| | sys.exit(0) |
| |
|
| | if not config_folder.exists(): |
| | run_initial() |
| | else: |
| | print("Configuration folder already exists. Skipping setup.") |
| |
|
| | print("🚀 Starting FastAPI server on port 5555...") |
| | uvicorn.run(app, port=5555) |