This commit is contained in:
Dwi Swandhana
2026-01-30 19:50:40 +07:00
parent 5865d44110
commit 41139d3df5
2 changed files with 97 additions and 35 deletions
+9 -4
View File
@@ -840,7 +840,7 @@ class AstmMessageService
try {
// Ambil pesan ASTM dari kolom 'message' atau yang relevan
$response = $data->rawdt;
if ($data->no_id != ''){
if ($data->alat == 'MGIT' OR $data->alat == 'COM5' OR $data->alat == 'BACTEC'){
$assembled = $this->reassembleAstmFrames($data->rawdt);
$messages = $this->splitBDAstmMessages($assembled);
foreach ($messages as $msg) {
@@ -864,9 +864,14 @@ class AstmMessageService
]
);
} else {
DB::table('lis_phoenix')->where('id', $data->id)->update([
'processed' => 9
]);
$result = $this->processAstmResponse($data->rawdt, $data->alat);
if ($result) {
DataListiner::where('urut', $data->urut)->update([
'processed' => 1
]);
} else {
Log::debug($result);
}
}
} catch (\Exception $e) {
Log::critical($e->getMessage());
+88 -31
View File
@@ -48,7 +48,9 @@ GENEXPERT_TEST_MAPPING = {
"HCV VL": "HCV", # Xpert HCV Viral Load Version 1
# Mapping untuk IP 10.10.120.74 (Khusus)
"HBV VL": "HBV", # Xpert HBV Viral Load Version 1
# Catatan: Di dokumen Anda tertulis Assay 'HBV' tapi kodenya 'HCV'.
# Pastikan ini benar, atau sesuaikan jika itu typo di dokumen.
"HBV VL": "HCV",
}
# Default code jika nama tes di database tidak dikenali
@@ -72,16 +74,16 @@ app = Flask(__name__)
active_genexpert_connections = {}
connection_lock = threading.Lock()
DEVICE_CONFIGS = [
#{
# 'port': 'COM6', 'baud_rate': 19200, 'device_type': 'vitek', 'alat_name': 'Vitek 1',
# 'protocol': 'serial', 'flag_column': 'flg_vitek1'
#},
{
'port': 'COM6', 'baud_rate': 19200, 'device_type': 'vitek', 'alat_name': 'Vitek 1',
'protocol': 'serial', 'flag_column': 'flg_vitek1'
},
{
'port': 'COM4', 'baud_rate': 9600, 'device_type': 'vitek', 'alat_name': 'Vitek 2',
'protocol': 'serial', 'flag_column': 'flg_vitek2'
},
{
'port': 'COM3', 'baud_rate': 19200, 'device_type': 'bd', 'alat_name': 'BACTEC',
'port': 'COM5', 'baud_rate': 19200, 'device_type': 'bd', 'alat_name': 'BACTEC',
'protocol': 'serial', 'flag_column': 'flg_bd1'
},
#BD_MGIT yang di dalam ruangan isolasi
@@ -292,11 +294,12 @@ def parse_hl7_result(hl7_message, device_name="GeneXpert"):
# 4. Validasi Data Penting
if not sample_id:
logging.warning("[HL7 Parser] Sample ID tidak ditemukan. Data tidak disimpan.")
print("[HL7 Parser] Sample ID tidak ditemukan. Data tidak disimpan.")
return
logging.info(f"[HL7 Parser] Menyimpan hasil untuk Sample: {sample_id} - {patient_name}")
print(f"[HL7 Parser] Menyimpan hasil untuk Sample: {sample_id} - {patient_name}")
# 5. Simpan ke Database (Tabel LisPhoenix)
new_data = LisPhoenix(
no_id=sample_id, # OBR-3
@@ -310,9 +313,11 @@ def parse_hl7_result(hl7_message, device_name="GeneXpert"):
session.add(new_data)
session.commit()
logging.info(f"[DB] Berhasil simpan ke LisPhoenix: {sample_id}")
print(f"[DB] Berhasil simpan ke LisPhoenix: {sample_id}")
except Exception as e:
logging.error(f"[HL7 Parser] Error menyimpan data: {e}")
print(f"[HL7 Parser] Error menyimpan data: {e}")
session.rollback()
finally:
@@ -329,6 +334,7 @@ def parse_hl7_result(hl7_message, device_name="GeneXpert"):
# ==========================================
def handle_tcp_client(client_socket, addr):
"""Menangani satu koneksi client GeneXpert"""
logging.info(f"[TCP] Koneksi diterima dari {addr}")
print(f"[TCP] Koneksi diterima dari {addr}")
try:
# Loop baca data dari client ini
@@ -341,19 +347,22 @@ def handle_tcp_client(client_socket, addr):
# decode, parsing ASTM, save to DB
try:
msg = data.decode('latin-1', errors='ignore')
print(f"[TCP] Data dari {addr}: {msg[:50]}...")
logging.info(f"[TCP] Data dari {addr}: {msg[:50]}...")
print(f"[TCP] Data dari {addr}: {msg[:50]}...")
# Panggil fungsi parser GeneXpert Anda disini
# parse_and_save_genexpert(msg)
parse_hl7_result(msg, device_name=addr[0] if addr else "Unknown")
# Kirim ACK ASTM jika perlu (\x06)
client_socket.send(b'\x06')
except Exception as e:
logging.error(f"[TCP] Error processing data: {e}")
print(f"[TCP] Error processing data: {e}")
except Exception as e:
logging.error(f"[TCP] Koneksi Error {addr}: {e}")
print(f"[TCP] Koneksi Error {addr}: {e}")
finally:
client_socket.close()
logging.info(f"[TCP] Koneksi ditutup {addr}")
print(f"[TCP] Koneksi ditutup {addr}")
def manage_tcp_server():
@@ -365,8 +374,8 @@ def manage_tcp_server():
try:
server.bind((SERVER_HOST, TCP_LISTENER_PORT))
server.listen(5) # Bisa antri 5 koneksi
logging.info(f"[TCP-SERVER] Listening GeneXpert di port {TCP_LISTENER_PORT}...")
print(f"[TCP-SERVER] Listening GeneXpert di port {TCP_LISTENER_PORT}...")
while True:
# Accept koneksi baru (Blocking, tapi aman karena di thread sendiri)
client_sock, addr = server.accept()
@@ -380,6 +389,7 @@ def manage_tcp_server():
client_thread.start()
except Exception as e:
logging.critical(f"[TCP-SERVER] Gagal Start: {e}")
print(f"[TCP-SERVER] Gagal Start: {e}")
def run_flask():
@@ -397,7 +407,7 @@ def send_mllp_message(sock, hl7_msg):
def handle_genexpert_client(conn, addr):
ip_sender = addr[0]
logging.info(f"[CONNECT] GeneXpert terkoneksi dari IP: {ip_sender}")
print(f"[CONNECT] GeneXpert terkoneksi dari IP: {ip_sender}")
with connection_lock:
active_genexpert_connections[ip_sender] = conn
@@ -422,12 +432,13 @@ def handle_genexpert_client(conn, addr):
hl7_str = raw_msg.decode('utf-8')
logging.info(f"[RECV] Dari {ip_sender}: {hl7_str[:50]}...") # Log 50 karakter awal
print(f"[RECV] Dari {ip_sender}: {hl7_str[:50]}...") # Print 50 karakter awal
# Cek Tipe Pesan (MSH field 9)
if "ORU^R01" in hl7_str:
# Ini adalah Hasil
hasil = parse_hl7_result(hl7_str)
hasil = parse_hl7_result(hl7_str, device_name=addr[0] if addr else "GeneXpert")
logging.info(f"[RESULT] {hasil}")
print(f"[RESULT] {hasil}")
# TODO: Simpan 'hasil' ke database berdasarkan Sample ID di HL7
# Kirim ACK (Terima Kasih) ke Alat
@@ -459,7 +470,7 @@ def run_tcp_server():
server.bind((SERVER_HOST, TCP_LISTENER_PORT))
server.listen(5) # Backlog 5 koneksi
logging.info(f"TCP Listener AKTIF di port {TCP_LISTENER_PORT}. Menunggu koneksi GeneXpert...")
print(f"TCP Listener AKTIF di port {TCP_LISTENER_PORT}. Menunggu koneksi GeneXpert...")
while True:
conn, addr = server.accept()
# Buat thread baru untuk setiap alat yg konek
@@ -468,6 +479,7 @@ def run_tcp_server():
except Exception as e:
logging.critical(f"Gagal menjalankan TCP Server: {e}")
print(f"Gagal menjalankan TCP Server: {e}")
def send_order_via_active_connection(target_ip, hl7_message):
conn = None
@@ -476,6 +488,7 @@ def send_order_via_active_connection(target_ip, hl7_message):
if not conn:
logging.warning(f"Gagal kirim Order: GeneXpert dengan IP {target_ip} BELUM TERKONEKSI ke Python.")
print(f"Gagal kirim Order: GeneXpert dengan IP {target_ip} BELUM TERKONEKSI ke Python.")
return False # Indikasi gagal
try:
@@ -494,6 +507,7 @@ def send_order_via_active_connection(target_ip, hl7_message):
return True
except Exception as e:
logging.error(f"Error mengirim ke {target_ip}: {e}")
print(f"Error mengirim ke {target_ip}: {e}")
# Jika error saat kirim, anggap koneksi rusak
with connection_lock:
if target_ip in active_genexpert_connections:
@@ -507,19 +521,22 @@ def broadcast_order_to_all_machines(hl7_message, order_id):
if not connected_ips:
logging.warning(f"Order {order_id} GAGAL dikirim: Tidak ada GeneXpert yang terkoneksi saat ini.")
print(f"Order {order_id} GAGAL dikirim: Tidak ada GeneXpert yang terkoneksi saat ini.")
return False
success_count = 0
logging.info(f"Memulai broadcast Order {order_id} ke {len(connected_ips)} alat...")
print(f"Memulai broadcast Order {order_id} ke {len(connected_ips)} alat...")
for target_ip in connected_ips:
# Panggil fungsi kirim tunggal yang sudah kita buat sebelumnya
# Note: Fungsi send_order_via_active_connection ada di kode sebelumnya
if send_order_via_active_connection(target_ip, hl7_message):
logging.info(f" -> Sukses kirim ke {target_ip}")
print(f" -> Sukses kirim ke {target_ip}")
success_count += 1
else:
logging.error(f" -> Gagal kirim ke {target_ip}")
print(f" -> Gagal kirim ke {target_ip}")
# Logika bisnis: Dianggap sukses jika minimal terkirim ke SATU alat
if success_count > 0:
@@ -626,7 +643,7 @@ def parse_and_save_vitek_result(raw_data, port_name="VITEK"):
final_res_string = "NEGATIVE / NO GROWTH"
logging.info(f"[{port_name}] Save DB -> ID: {sample_id}, Pasien: {patient_name}, Bakteri: {organism_name}")
print(f"[{port_name}] Save DB -> ID: {sample_id}, Pasien: {patient_name}, Bakteri: {organism_name}")
new_entry = LisPhoenix(
no_id=sample_id, # Menggunakan tag 'ci'
seq_no=patient_id, # Menggunakan tag 'pi'
@@ -641,11 +658,14 @@ def parse_and_save_vitek_result(raw_data, port_name="VITEK"):
else:
if msg_type != 'mtrsl':
logging.info(f"[{port_name}] Mengabaikan pesan tipe {msg_type}")
print(f"[{port_name}] Mengabaikan pesan tipe {msg_type}")
else:
logging.warning(f"[{port_name}] Data tidak lengkap (No Sample ID). Raw: {raw_data[:50]}...")
print(f"[{port_name}] Data tidak lengkap (No Sample ID). Raw: {raw_data[:50]}...")
except Exception as e:
logging.error(f"Error Parsing Vitek: {e}")
print(f"Error Parsing Vitek: {e}")
session.rollback()
finally:
session.close()
@@ -704,7 +724,7 @@ def manage_vitek_port(config):
flag_col = config.get('flag_column')
alat_name = config.get('alat_name', 'VITEK')
logging.info(f"[{port_name}] Membuka port untuk alat {alat_name}...")
print(f"[{port_name}] Membuka port untuk alat {alat_name}...")
# Buffer untuk menampung pecahan data
rx_buffer = b""
@@ -730,6 +750,7 @@ def manage_vitek_port(config):
# 1. Handle Handshake Awal (ENQ) - Alat minta izin kirim
if b'\x05' in data_chunk:
logging.info(f"[{port_name}] Terima ENQ. Kirim ACK.")
print(f"[{port_name}] Terima ENQ. Kirim ACK.")
ser.write(b'\x06') # ACK
rx_buffer = b"" # Reset buffer bytes
continue
@@ -754,12 +775,13 @@ def manage_vitek_port(config):
parse_and_save_vitek_result(full_str, alat_name)
except Exception as e:
logging.error(f"[{port_name}] Error Decoding/Parsing: {e}")
print(f"[{port_name}] Error Decoding/Parsing: {e}")
rx_buffer = b"" # Bersihkan buffer
continue
except Exception as e:
logging.error(f"[{port_name}] Error Reading: {e}")
print(f"[{port_name}] Error Reading: {e}")
rx_buffer = b"" # Reset jika error parah
@@ -778,7 +800,7 @@ def manage_vitek_port(config):
if pending_order:
has_activity = True # Jangan sleep lama-lama
logging.info(f"[{port_name}] Menemukan Order: {pending_order.rnoreg}. Memulai Handshake...")
print(f"[{port_name}] Menemukan Order: {pending_order.rnoreg}. Memulai Handshake...")
# --- STEP 1: HANDSHAKE (ENQ) ---
ser.reset_input_buffer()
ser.write(b'\x05')
@@ -789,6 +811,7 @@ def manage_vitek_port(config):
if ack_response == b'\x06':
logging.info(f"[{port_name}] Handshake dengan {alat_name}Sukses. Kirim Data...")
print(f"[{port_name}] Handshake dengan {alat_name} Sukses. Kirim Data...")
time.sleep(1.0) # Jeda aman
frames = create_vitek_order_message(pending_order)
@@ -799,7 +822,8 @@ def manage_vitek_port(config):
retry = 0
frame_sent = False
while retry < 3:
logging.info(f"[{port_name}] Kirim Frame (Try {retry+1}): {frame}") # Log apa yang dikirim
logging.info(f"[{port_name}] Kirim Frame (Try {retry+1}): {frame}")
print(f"[{port_name}] Kirim Frame (Try {retry+1}): {frame}")
ser.write(frame)
# Tunggu ACK
@@ -813,17 +837,21 @@ def manage_vitek_port(config):
if response == b'\x06': # ACK
logging.info(f"[{port_name}] Frame ACK (OK).")
print(f"[{port_name}] Frame ACK (OK).")
frame_sent = True
break
elif response == b'\x15': # NAK
logging.warning(f"[{port_name}] Dibalas NAK (Checksum/Format Salah).")
print(f"[{port_name}] Dibalas NAK (Checksum/Format Salah).")
time.sleep(1)
retry += 1
elif response is None: # TIMEOUT
logging.warning(f"[{port_name}] Timeout (Alat tidak membalas). Cek Framing/Kabel.")
print(f"[{port_name}] Timeout (Alat tidak membalas). Cek Framing/Kabel.")
retry += 1
else: # Respon Aneh
logging.warning(f"[{port_name}] Respon aneh: {response}")
print(f"[{port_name}] Respon aneh: {response}")
retry += 1
if not frame_sent:
@@ -835,20 +863,23 @@ def manage_vitek_port(config):
if all_success:
logging.info(f"[{port_name}] Order {pending_order.rnoreg} SELESAI.")
print(f"[{port_name}] Order {pending_order.rnoreg} SELESAI.")
setattr(pending_order, flag_col, True)
session.commit()
else:
logging.error(f"[{port_name}] Gagal kirim order {pending_order.rnoreg}.")
print(f"[{port_name}] Gagal kirim order {pending_order.rnoreg}.")
else:
# Handshake gagal (Alat sibuk/Mati)
# logging.debug(f"[{port_name}] Alat sibuk/tidak balas ENQ.")
print(f"[{port_name}] Alat sibuk/tidak balas ENQ.")
pass
session.close()
except Exception as e:
logging.error(f"[{port_name}] Error Sending Logic: {e}")
print(f"[{port_name}] Error Sending Logic: {e}")
if 'session' in locals(): session.close()
# ==========================================
@@ -861,6 +892,7 @@ def manage_vitek_port(config):
except Exception as e:
logging.critical(f"[{port_name}] Gagal connect Serial: {e}")
print(f"[{port_name}] Gagal connect Serial: {e}")
time.sleep(5)
# ==========================================
@@ -946,7 +978,7 @@ def parse_and_save_bd_result(raw_data, port_name="BD Bactec"):
final_res_string += f" ({specimen_type})"
logging.info(f"[{port_name}] Save DB -> ID: {sample_id}, Pasien: {patient_name}, Hasil: {final_res_string}")
print(f"[{port_name}] Save DB -> ID: {sample_id}, Pasien: {patient_name}, Hasil: {final_res_string}")
new_entry = LisPhoenix(
no_id=sample_id,
seq_no=patient_id,
@@ -960,9 +992,11 @@ def parse_and_save_bd_result(raw_data, port_name="BD Bactec"):
session.commit()
else:
logging.warning(f"[{port_name}] Data tidak lengkap. ID: {sample_id}, Res: {result_val}")
print(f"[{port_name}] Data tidak lengkap. ID: {sample_id}, Res: {result_val}")
except Exception as e:
logging.error(f"Error Parsing BD: {e}")
print(f"Error Parsing BD: {e}")
session.rollback()
finally:
session.close()
@@ -1092,6 +1126,7 @@ def manage_bd_port(config):
# 1. Handle Handshake Awal (ENQ)
if b'\x05' in data_chunk:
logging.info(f"[{port_name}] Terima ENQ (Alat mau kirim data). Kirim ACK.")
print(f"[{port_name}] Terima ENQ (Alat mau kirim data). Kirim ACK.")
ser.write(b'\x06') # ACK
rx_buffer = "" # Reset buffer untuk data baru
continue
@@ -1099,6 +1134,7 @@ def manage_bd_port(config):
# 2. Handle Akhir Transmisi (EOT)
if b'\x04' in data_chunk:
logging.info(f"[{port_name}] Terima EOT (Selesai). Memproses data...")
print(f"[{port_name}] Terima EOT (Selesai). Memproses data...")
# Proses semua data yang terkumpul di buffer
parse_and_save_bd_result(rx_buffer, alat_name)
rx_buffer = "" # Kosongkan buffer setelah save
@@ -1118,11 +1154,13 @@ def manage_bd_port(config):
# logging.debug(f"[{port_name}] Frame diterima, ACK dikirim.")
except Exception as e:
logging.error(f"Error decode frame: {e}")
print(f"Error decode frame: {e}")
continue # Loop lagi untuk ambil sisa data
except Exception as e:
logging.error(f"[{port_name}] Error Reading: {e}")
print(f"[{port_name}] Error Reading: {e}")
rx_buffer = b"" # Reset jika error parah
@@ -1141,7 +1179,7 @@ def manage_bd_port(config):
if pending_order:
has_activity = True # Jangan sleep lama-lama
logging.info(f"[{port_name}] Menemukan Order: {pending_order.rnoreg}. Memulai Handshake...")
print(f"[{port_name}] Menemukan Order: {pending_order.rnoreg}. Memulai Handshake...")
# --- STEP 1: HANDSHAKE (ENQ) ---
ser.reset_input_buffer()
ser.write(b'\x05')
@@ -1151,7 +1189,7 @@ def manage_bd_port(config):
if ack_response == b'\x06':
logging.info(f"[{port_name}] Handshake Sukses (Dapat ACK). Menunggu alat siap...")
print(f"[{port_name}] Handshake Sukses (Dapat ACK). Menunggu alat siap...")
# --- PERBAIKAN 1: BERI JEDA SETELAH HANDSHAKE ---
# Mesin butuh napas sebelum terima data panjang
time.sleep(1.5) # Jeda 1.5 detik
@@ -1171,6 +1209,7 @@ def manage_bd_port(config):
ser.reset_input_buffer()
logging.info(f"[{port_name}] Kirim Frame {i+1} (Percobaan {retry_count+1})...")
print(f"[{port_name}] Kirim Frame {i+1} (Percobaan {retry_count+1})...")
ser.write(frame)
# Tunggu ACK
@@ -1182,28 +1221,33 @@ def manage_bd_port(config):
if frame_ack == b'\x06': # ACK (Sukses)
frame_success = True
logging.info(f"[{port_name}] Frame {i+1} ACK diterima.")
print(f"[{port_name}] Frame {i+1} ACK diterima.")
# Beri jeda dikit sebelum kirim frame berikutnya
time.sleep(0.2)
break
elif frame_ack == b'\x15': # NAK (Ditolak - Checksum Salah)
logging.warning(f"[{port_name}] Frame ditolak (NAK). Checksum mungkin salah.")
print(f"[{port_name}] Frame ditolak (NAK). Checksum mungkin salah.")
time.sleep(2) # Tunggu 2 detik
retry_count += 1
elif not frame_ack: # Timeout (Sepi)
# --- PERBAIKAN 2: BERI JEDA SAAT TIMEOUT ---
logging.warning(f"[{port_name}] Timeout (Alat diam). Menunggu sebelum retry...")
print(f"[{port_name}] Timeout (Alat diam). Menunggu sebelum retry...")
time.sleep(2) # Tunggu 2 detik agar alat recover
retry_count += 1
else:
logging.warning(f"[{port_name}] Respon aneh: {frame_ack}")
print(f"[{port_name}] Respon aneh: {frame_ack}")
time.sleep(1)
retry_count += 1
if not frame_success:
logging.error(f"[{port_name}] Gagal kirim frame ke-{i+1}. Batal.")
print(f"[{port_name}] Gagal kirim frame ke-{i+1}. Batal.")
all_frames_sent = False
break
# ---------------------------------------------------
@@ -1212,17 +1256,18 @@ def manage_bd_port(config):
if all_frames_sent:
ser.write(b'\x04') # EOT (End of Transmission)
logging.info(f"[{port_name}] Order {pending_order.rnoreg} SUKSES Terkirim.")
print(f"[{port_name}] Order {pending_order.rnoreg} SUKSES Terkirim.")
# Update Database
setattr(pending_order, flag_col, True)
session.commit()
else:
ser.write(b'\x04') # EOT (Putus paksa karena error)
logging.error(f"[{port_name}] Pengiriman Order GAGAL.")
print(f"[{port_name}] Pengiriman Order GAGAL.")
else:
# Jika Handshake gagal (Dibalas NAK, atau Timeout)
logging.warning(f"[{port_name}] Handshake Gagal. Respon alat: {ack_response}")
print(f"[{port_name}] Handshake Gagal. Respon alat: {ack_response}")
# Jangan update flag DB, biarkan coba lagi nanti
@@ -1230,6 +1275,7 @@ def manage_bd_port(config):
except Exception as e:
logging.error(f"[{port_name}] Error Sending Logic: {e}")
print(f"[{port_name}] Error Sending Logic: {e}")
if 'session' in locals(): session.close()
# ==========================================
@@ -1242,6 +1288,7 @@ def manage_bd_port(config):
except Exception as e:
logging.critical(f"[{port_name}] Gagal connect Serial: {e}")
print(f"[{port_name}] Gagal connect Serial: {e}")
time.sleep(5)
# ==========================================
@@ -1251,7 +1298,7 @@ def manage_bd_port(config):
def order_poller(stop_event):
"""Looping cek DB dan kirim order ke SEMUA alat"""
logging.info("Order Poller Berjalan...")
print("Order Poller Berjalan...")
while not stop_event.is_set():
session = SessionLocal()
try:
@@ -1286,8 +1333,10 @@ def order_poller(stop_event):
send_mllp_message(conn, hl7_msg)
order.flg_gxp1 = True # Update Flag
logging.info(f"[SENT] Order {order.rnoreg} dikirim ke GXP-1 ({target_ip})")
print(f"[SENT] Order {order.rnoreg} dikirim ke GXP-1 ({target_ip})")
except Exception as e:
logging.error(f"[FAIL] Gagal kirim ke GXP-1: {e}")
print(f"[FAIL] Gagal kirim ke GXP-1: {e}")
else:
# Alat 1 belum connect, biarkan False (pending)
pass
@@ -1301,8 +1350,10 @@ def order_poller(stop_event):
send_mllp_message(conn, hl7_msg)
order.flg_gxp2 = True
logging.info(f"[SENT] Order {order.rnoreg} dikirim ke GXP-2 ({target_ip})")
print(f"[SENT] Order {order.rnoreg} dikirim ke GXP-2 ({target_ip})")
except Exception as e:
logging.error(f"[FAIL] Gagal kirim ke GXP-2: {e}")
print(f"[FAIL] Gagal kirim ke GXP-2: {e}")
# 3. Cek Target GXP 3
if order.flg_gxp3 == False:
@@ -1313,13 +1364,16 @@ def order_poller(stop_event):
send_mllp_message(conn, hl7_msg)
order.flg_gxp3 = True
logging.info(f"[SENT] Order {order.rnoreg} dikirim ke GXP-3 ({target_ip})")
print(f"[SENT] Order {order.rnoreg} dikirim ke GXP-3 ({target_ip})")
except Exception as e:
logging.error(f"[FAIL] Gagal kirim ke GXP-3: {e}")
print(f"[FAIL] Gagal kirim ke GXP-3: {e}")
# Commit perubahan flag ke database
session.commit()
except Exception as e:
logging.error(f"Error Poller: {e}")
print(f"Error Poller: {e}")
session.rollback()
finally:
session.close()
@@ -1335,7 +1389,7 @@ def manage_serial_port(config):
manage_bd_port(config)
else:
logging.error(f"Tipe alat tidak diketahui: '{device_type}' untuk port {config.get('port')}. Thread dihentikan.")
print(f"Tipe alat tidak diketahui: '{device_type}' untuk port {config.get('port')}. Thread dihentikan.")
# ==========================================
# 6. FLASK API (Opsional)
# ==========================================
@@ -1388,25 +1442,28 @@ if __name__ == "__main__":
# Ini sekarang bisa berjalan karena Flask sudah dipindah ke thread
try:
while True:
logging.debug(f"--- Monitoring {len(all_threads)} Threads ---")
print(f"--- Monitoring {len(all_threads)} Threads ---")
# Cek status setiap thread
alive_count = 0
for t in all_threads:
if t.is_alive():
alive_count += 1
else:
logging.warning(f"!!! THREAD MATI: {t.name} !!!")
print(f"!!! THREAD MATI: {t.name} !!!")
# Disini Anda bisa menambahkan logika restart thread jika mati
# Jika semua mati, exit (atau restart service)
if alive_count == 0:
logging.critical("Semua thread mati. System Shutdown.")
print("Semua thread mati. System Shutdown.")
break
time.sleep(10) # Cek setiap 10 detik (Hemat CPU)
except KeyboardInterrupt:
logging.info("Mematikan Service (Ctrl+C)...")
print("Mematikan Service (Ctrl+C)...")
stop_event.set()
# Thread daemon akan mati otomatis saat main exit
# Thread daemon akan mati otomatis saat main exit