advice_printer / adviceprinter.py
Autsadin's picture
Upload 4 files
a82dbc4 verified
# adviceprinter2.py
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
# ---------------------------
# Redirect stdout/stderr (for PyInstaller windowed)
# ---------------------------
if sys.stdout is None:
sys.stdout = open(os.devnull, 'w')
if sys.stderr is None:
sys.stderr = open(os.devnull, 'w')
# ---------------------------
# Utility for macOS login items
# ---------------------------
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.")
# ---------------------------
# Thai Smart Card Utilities
# ---------------------------
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]
# Command sets
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]
# ---------------------------
# Read Thai ID card data
# ---------------------------
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
}
# ---------------------------
# Setup for Windows & macOS
# ---------------------------
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": # macOS
app_path = "/Applications/Adviceprinter2.app"
add_to_login_items(app_path)
else:
print("Unsupported OS detected. Exiting.")
exit()
# ---------------------------
# FastAPI Application
# ---------------------------
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)}"}
# ---------------------------
# Main Entry
# ---------------------------
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)