# -*- coding: utf-8 -*- import os import sys import csv from collections import OrderedDict from datetime import datetime from zk.finger import Finger import codecs CWD = os.path.dirname(os.path.realpath(__file__)) ROOT_DIR = os.path.dirname(CWD) sys.path.append(ROOT_DIR) from zk import ZK, const import zk print (zk.__file__) mesin_absen = [ { "lokasi":"Painting In", "ip":"10.35.14.14", "id":"1" }, { "lokasi":"Painting Out" , "ip":"10.35.14.13", "id":"2"}, { "lokasi":"Injection In", "ip":"10.35.7.10", "id":"3"}, { "lokasi":"Injection Out", "ip":"10.35.7.11", "id":"4"}, { "lokasi":"Office", "ip":"10.35.14.10", "id":"5"}, { "lokasi":"Hotpress in", "ip":"10.35.14.15", "id":"7"}, { "lokasi":"Hotpress out", "ip":"10.35.14.16", "id":"6"}, { "lokasi":"KIIC", "ip":"10.45.7.2", "id":"8"}, { "lokasi":"Injection 2 out", "ip":"10.35.7.12", "id":"9"}, { "lokasi":"Injection 2 in", "ip":"10.35.7.13", "id":"10"}, { "lokasi":"Test Machine", "ip":"10.35.7.14", "id":"11"}, { "lokasi":"ZK Gate1", "ip":"10.35.7.3", "id":"12"}, ] #print(mesin_absen[0]['lokasi']) def pilih_mesin(): print("Daftar mesin attendance : ") for i, mesin in enumerate(mesin_absen, start=1): print(f"{i}: {mesin['lokasi']} (IP: {mesin['ip']})") while True: try: choice = int(input("Pilih nomor mesin (1-12): ")) if 1 <= choice <= 12: mesin_dipilih = mesin_absen[choice - 1] ipaddress = mesin_dipilih["ip"] lokasi = mesin_dipilih["lokasi"] idmesin = mesin_dipilih["id"] print(f"Dipilih mesin {idmesin}, lokasi: {lokasi}, IP Address mesin absen: {ipaddress}") return ipaddress, idmesin else: print("Masukan angka 1-12") except ValueError: print("Invalid input. Masukan angka.") def koneksi_mesin(ipaddress): conn = None zk = ZK(ipaddress, port=4370, verbose=True, timeout=5, password=0, force_udp=True) # connect to device conn = zk.connect() device_info = conn.get_network_params() #device_id = device_info.get('MachineNumber', 'ID Tidak ditemukan') print(f"Device ID: {device_info}") # disable device, this method ensures no activity on the device while the process is run conn.disable_device() print("Koneksi tersambung dengan mesin ", ipaddress) return conn def menu(): operasi = [ "Input karyawan baru", "Import data karyawan", "Import data finger", "Tampilkan data karyawan", "Tampilkan data kehadiran", "Ekspor data karyawan", "Ekspor data kehadiran", "Ekspor data kehadiran per tanggal", 'Ekspor data finger', "Eksport data finger satuan", "Hapus data karyawan", "Hapus data finger", "Keluar" ] print("Operasi yang tersedia : ") for i, ops in enumerate(operasi, start=1): print(f"{i}: {ops}") while True: try: choice = int(input("Pilih operasi: ")) if 1 <= choice <= 12: operasi_dipilih = operasi[choice - 1] print(f"{operasi_dipilih} dipilih") return operasi_dipilih else: print("Masukan angka") except ValueError: print("Invalid input. Masukan angka.") def input_karyawan(conn): last_uid = get_latest_uid(conn) try: name = input("Masukkan nama karyawan: ") user_id = input("Masukkan user ID karyawan: ") privilege_input = int(input("Privilege, admin=0, user=1: ")) print(privilege_input) type(privilege_input) if privilege_input == 0: privilege = const.USER_ADMIN else: privilege = const.USER_DEFAULT password = input("Masukkan password (kosongkan jika tidak ada): ") conn.set_user(uid = last_uid + 1, name=name, privilege=privilege, password=password, user_id=user_id) print("Karyawan baru berhasil ditambahkan!") except Exception as e: print(f"Terjadi kesalahan: {e}") finally: if conn: conn.disconnect() def delete_karyawan(conn): uid = int(input("Masukkan UID: ")) conn.delete_user(uid=uid) print("Karyawan berhasil dihapus") if conn: conn.disconnect() def delete_finger(conn): uid = int(input("Masukkan UID: ")) temp_id = int(input("Masukkan Finger ID: ")) try: conn.delete_user_template(uid=uid, temp_id=temp_id, user_id='') print("Finger berhasil dihapus") except Exception as e: print(f"Terjadi kesalahan: {e}") if conn: conn.disconnect() def import_data_karyawan(conn): try: with open('karyawan_data/import_m10.csv', mode='r') as file: reader = csv.reader(file, delimiter=';') next(reader) column_index = [1, 4] # 1: nama, 4: user_id last_uid = get_latest_uid(conn) #Ambil UID terakhir for index, row in enumerate(reader): if not row or len(row) < max(column_index) + 1: print(f"Baris {index} kosong atau tidak valid, dilewati") continue selected_columns = [row[i] for i in column_index] print(selected_columns) #uid = row[0] #name = row[1] #user_id = row[4] #for row in reader: # Check if the row has enough columns # if all(i < len(row) for i in column_indices): # selected_columns = [row[i] for i in column_indices] # print(selected_columns) # else: # print(f"Skipping row with missing columns: {row}") try: name = row[column_index[0]] user_id = row[column_index[1]] print(f"Importing: {name} (User ID: {user_id})") conn.set_user(uid = last_uid + 1, name=name, privilege=const.USER_DEFAULT, password='', user_id=user_id)#(uid=uid, name=name, privilege=const.USER_DEFAULT, password='', user_id=user_id) #conn.test_voice(index=0) last_uid += 1 except Exception as e: #print ("Terjadi kesalahan : {}".format(e)) print(f"Error di baris {index} saat memproses {name}: {e}") except FileNotFoundError: print("File CSV tidak ditemukan") except Exception as e: print(f"Terjadi kesalahan: {e}") finally: if conn: conn.enable_device() conn.disconnect() def import_data_finger(conn): conn.disable_device() conn.free_data() conn.refresh_data() users = conn.get_users() try: #file csv harus encoding UTF-8, template finger jangan diquote with open('karyawan_data/finger_data/import_finger_data_m9_m10_huda.csv', mode='r', encoding='latin-1') as file: reader = csv.reader(file, delimiter=';', quotechar='รข') next(reader) column_index = [1, 2, 4] # 1: uid, 2: fid, 4: template for index, row in enumerate(reader): if not row or len(row) < max(column_index) + 1: print(f"Baris {index} kosong atau tidak valid, dilewati") continue selected_columns = [row[i] for i in column_index] print("Data csv: ", selected_columns) try: #template = codecs.decode(row[4].encode('latin-1'), 'unicode_escape') #akhirnya ketemu caranya T_T #template = bytes(row[4]) #template = bytes(template, 'latin-1') template_str = row[4].replace('""', '"') # Replace double quotes with a single quote template = eval(template_str) if not isinstance(template, bytes): raise ValueError(f"Data in row[4] is not in bytes format: {row[4]}") print('Data template:', template) uid = int(row[1]) fid = int(row[2]) fingerdata = Finger(uid=uid, fid=fid, valid=1, template=template) user1 = next((u for u in users if u.uid == uid), None) try: conn.save_user_template(user=user1, fingers=[fingerdata]) print('menyimpan data sidik jari:') print(user1) print(fingerdata) print('data berhasil disimpan') except: print(fingerdata.__dict__) print('data gagal disimpan') except: print('cannot encode fingerprint') except FileNotFoundError: print("File CSV tidak ditemukan") except Exception as e: print(f"Terjadi kesalahan: {e}") finally: if conn: conn.enable_device() conn.disconnect() def get_latest_uid(conn): users = conn.get_users() if users: return max(user.uid for user in users) print("Gara2 get users") return 0 def tampilkan_data_karyawan(): userdata = [] users = conn.get_users() last_uid = get_latest_uid(conn) for user in users: userdataset = OrderedDict() #pakai ordered dict supaya datanya berurutan privilege = 'User' if user.privilege == const.USER_ADMIN: privilege = 'Admin' '''print ('+ UID #{}'.format(user.uid)) print (' Name : {}'.format(user.name)) print (' Privilege : {}'.format(privilege)) print (' Password : {}'.format(user.password)) print (' Group ID : {}'.format(user.group_id)) print (' User ID : {}'.format(user.user_id))''' #print ('+ UID #{}'.format(user.uid)) userdataset["uid"] = user.uid userdataset["privilege"] = user.privilege #print (' Name : {}'.format(user.name)) userdataset["name"] = user.uid #print (' Name : {}'.format(user.name)) userdataset["name"] = user.name #print (' Password : {}'.format(user.password)) userdataset["password"] = user.password #print (' Group ID : {}'.format(user.group_id)) userdataset["group_id"] = user.group_id #print (' User ID : {}'.format(user.user_id)) userdataset["user_id"] = user.user_id userdata.append(userdataset) #print(userdata) for u in userdata: # print(u) for key, value in u.items(): print(f"{key.capitalize()}: {value}") #print("*" * 30) # 30 asterisks print("=" * 50) # 50 equal signs print("UID Terakhir: ", last_uid) if conn: conn.enable_device() conn.disconnect() def ekspor_data_karyawan(): userdata = [] users = conn.get_users() for user in users: userdataset = OrderedDict() #pakai ordered dict supaya datanya berurutan userdataset["uid"] = user.uid userdataset["name"] = user.name userdataset["password"] = user.password userdataset["group_id"] = user.group_id userdataset["user_id"] = user.user_id userdata.append(userdataset) fieldnames = ["uid", "name", "password", "group_id", "user_id"] current_time = datetime.now().strftime("%Y%m%d_%H%M") directory = "karyawan_data" if not os.path.exists(directory): os.makedirs(directory) filename = os.path.join(directory,f"karyawan_m{idmesin}_{current_time}.csv") with open(filename, 'w', newline='', encoding='utf-8') as csv_file: writer = csv.DictWriter(csv_file, delimiter=';', fieldnames=fieldnames) writer.writeheader() for u in userdata: writer.writerow(u) print("Data berhasil disimpan sebagai ", filename) if conn: conn.enable_device() conn.disconnect() def ekspor_data_finger(conn): #template = conn.get_user_template(uid=1, temp_id=0) fingers = conn.get_templates() #print(fingers) #print(type(fingers)) for finger in fingers: print(finger.__dict__) fieldnames = ["size", "uid", "fid", "valid", "template", "mark"] current_time = datetime.now().strftime("%Y%m%d_%H%M") directory = "karyawan_data/finger_data" if not os.path.exists(directory): os.makedirs(directory) filename = os.path.join(directory,f"finger_m{idmesin}_{current_time}.csv") with open(filename, 'w', newline='', encoding='utf-8') as csv_file: writer = csv.DictWriter(csv_file, delimiter=';', fieldnames=fieldnames) writer.writeheader() for f in fingers: writer.writerow(f.__dict__) print("Data finger berhasil disimpan sebagai ", filename) if conn: conn.enable_device() conn.disconnect() def ekspor_data_finger_satuan(conn): uid = int(input("Masukkan UID : ")) fingers = [] for i in range(10): fingers.append(conn.get_user_template(uid=uid, temp_id=i)) print(fingers) #fingers = conn.get_templates() #print(fingers) #print(type(fingers)) #for finger in fingers: # print(finger.__dict__) fieldnames = ["size", "uid", "fid", "valid", "template", "mark"] current_time = datetime.now().strftime("%Y%m%d_%H%M") directory = "karyawan_data/finger_data" if not os.path.exists(directory): os.makedirs(directory) filename = os.path.join(directory,f"finger_m{idmesin}_{uid}.csv") with open(filename, 'w', newline='', encoding='utf-8') as csv_file: writer = csv.DictWriter(csv_file, delimiter=';', fieldnames=fieldnames) writer.writeheader() for f in fingers: writer.writerow(f.__dict__) print("User data written to ", filename) if conn: conn.enable_device() conn.disconnect() def tampilkan_data_kehadiran(): attendances = conn.get_attendance() print(type(attendances)) for attendance in attendances: print(attendance) if conn: conn.disconnect() def ekspor_data_kehadiran(conn, idmesin): print(conn) attendances = conn.get_attendance() idmesin = str(idmesin).zfill(3) fieldnames = ["machineid", "uid", "datestamp", "timestamp", "type", "inout"] #current_time = datetime.now().strftime("%Y%m%d_%H%M") current_time = datetime.now().strftime("%Y%m%d") # Ensure the directory exists directory = "attendance_data" if not os.path.exists(directory): os.makedirs(directory) filename = os.path.join(directory,f"attendances_{current_time}.txt") #filename = os.path.join(directory,f"att_m{idmesin}_{current_time}.txt") #filename = input("Masukan nama file untuk menyimpan data kehadiran: ") + ".csv" #nama file disimpan #with open(filename, 'w', newline='', encoding='utf-8') as csv_file: with open(filename, 'a', newline='', encoding='utf-8') as csv_file: writer = csv.DictWriter(csv_file, delimiter=';', fieldnames=fieldnames) #writer.writeheader() for attendance in attendances: datestamp = attendance.timestamp.strftime("%d-%m-%Y") timestamp = attendance.timestamp.strftime("%H:%M") writer.writerow({ "machineid": idmesin, "uid": str(attendance.user_id).zfill(16), # biar 16 digit, diisi 0 di depan "datestamp": datestamp, "timestamp": timestamp, "type": str(attendance.punch).zfill(2), "inout": str(attendance.status).zfill(2), }) print("Data kehadiran berhasil disimpan di", filename) '''try: conn.clear_attendance() print("Data attendance berhasil dihapus dari mesin") except Exception as e: print(f"Gagal menghapus data attendance dari mesin {e}") ''' if conn: conn.disconnect() def ekspor_data_kehadiran_per_tanggal(conn, idmesin, fromdate, todate): print(conn) attendances = conn.get_attendance() idmesin = str(idmesin).zfill(3) fieldnames = ["machineid", "uid", "datestamp", "timestamp", "type", "inout"] current_time = datetime.now().strftime("%Y%m%d_%H%M") fromdate = datetime.strptime(fromdate, "%d-%m-%Y").date() todate = datetime.strptime(todate, "%d-%m-%Y").date() # Ensure the directory exists directory = "attendance_data" if not os.path.exists(directory): os.makedirs(directory) filename = os.path.join(directory,f"att_m{idmesin}_{current_time}.txt") #filename = input("Masukan nama file untuk menyimpan data kehadiran: ") + ".csv" #nama file disimpan with open(filename, 'w', newline='', encoding='utf-8') as csv_file: writer = csv.DictWriter(csv_file, delimiter=';', fieldnames=fieldnames) #writer.writeheader() print("From Date: ", fromdate, type(fromdate)) print("To Date: ", todate, type(todate)) for attendance in attendances: datestamp = attendance.timestamp.strftime("%d-%m-%Y") datestamp = datetime.strptime(datestamp, "%d-%m-%Y").date() #konversi ke date timestamp = attendance.timestamp.strftime("%H:%M") if fromdate <= datestamp <= todate: datestamp = attendance.timestamp.strftime("%d-%m-%Y") #kembalikan ke bentuk string untuk ditulis ke file writer.writerow({ "machineid": idmesin, "uid": str(attendance.user_id).zfill(16), # biar 16 digit, diisi 0 di depan "datestamp": datestamp, "timestamp": timestamp, "type": str(attendance.punch).zfill(2), "inout": str(attendance.status).zfill(2), }) print("Data kehadiran berhasil disimpan di", filename) if conn: conn.disconnect() def operasi(dipilih, conn, idmesin): if dipilih == "Input karyawan baru": input_karyawan(conn) elif dipilih == "Import data karyawan": import_data_karyawan(conn) elif dipilih == "Import data finger": import_data_finger(conn) elif dipilih == "Tampilkan data karyawan": tampilkan_data_karyawan() elif dipilih == "Ekspor data karyawan": ekspor_data_karyawan() elif dipilih == "Tampilkan data kehadiran": tampilkan_data_kehadiran() elif dipilih == "Ekspor data kehadiran": ekspor_data_kehadiran(conn, idmesin) elif dipilih == "Ekspor data kehadiran per tanggal": fromdate = input("Masukkan tanggal awal (dd-mm-yyyy): ") todate = input("Masukkan tanggal akhir (dd-mm-yyyy): ") ekspor_data_kehadiran_per_tanggal(conn, idmesin, fromdate, todate) elif dipilih == "Ekspor data finger": ekspor_data_finger(conn) elif dipilih == "Eksport data finger satuan": ekspor_data_finger_satuan(conn) elif dipilih == "Hapus data karyawan": delete_karyawan(conn) elif dipilih == "Hapus data finger": delete_finger(conn) elif dipilih == "Keluar": print("Keluar dari program") conn.disconnect() sys.exit() while True: ipaddress, idmesin = pilih_mesin() conn = koneksi_mesin(ipaddress) dipilih = menu() operasi(dipilih, conn, idmesin)