Files
MesinAbsen/attendanceManager.py
Aries Wibowo 484ba05a65 Initial test
2026-04-22 09:19:12 +07:00

503 lines
19 KiB
Python

# -*- 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)