update
This commit is contained in:
+151
-24
@@ -184,6 +184,91 @@ Base.metadata.create_all(bind=engine)
|
|||||||
# ==========================================
|
# ==========================================
|
||||||
# 3. HL7 HELPER FUNCTIONS
|
# 3. HL7 HELPER FUNCTIONS
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
def get_flag_by_device(ip_addr):
|
||||||
|
for flag, ip in TARGET_MAPPING.items():
|
||||||
|
if ip == ip_addr:
|
||||||
|
return flag
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_pending_orders(ip_addr):
|
||||||
|
flag = get_flag_by_device(ip_addr)
|
||||||
|
if not flag:
|
||||||
|
return []
|
||||||
|
|
||||||
|
session = SessionLocal()
|
||||||
|
try:
|
||||||
|
q = session.query(PaslabOrder).filter(getattr(PaslabOrder, flag) == False)
|
||||||
|
return q.all()
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def build_rsp_for_order(order, msg_id):
|
||||||
|
ts = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
||||||
|
|
||||||
|
return (
|
||||||
|
f"MSH|^~\\&|LIS|LAB|GeneXpert|Cepheid|{ts}||RSP^Z03|{msg_id}|P|2.5\r"
|
||||||
|
f"MSA|AA|{msg_id}\r"
|
||||||
|
f"QAK|OK|{msg_id}\r"
|
||||||
|
f"QPD|Z01^REQUEST TEST ORDERS|{order.rnoreg}|ALL\r"
|
||||||
|
f"ORC|NW|{order.urut}\r"
|
||||||
|
f"OBR|1|{order.urut}|{order.rnoreg}|^{order.kd_spesimen}^{order.nm_spesimen}\r"
|
||||||
|
)
|
||||||
|
|
||||||
|
def send_all_orders(conn, ip_addr, hl7_msg, msg_id):
|
||||||
|
orders = get_pending_orders(ip_addr)
|
||||||
|
session = SessionLocal()
|
||||||
|
|
||||||
|
if not orders:
|
||||||
|
print(f"[GENEXPERT] Tidak ada order pending untuk {ip_addr}")
|
||||||
|
rsp = (
|
||||||
|
f"MSH|^~\\&|LIS|LAB|GeneXpert|Cepheid|{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}||RSP^Z03|{msg_id}|P|2.5\r"
|
||||||
|
f"MSA|AA|{msg_id}\r"
|
||||||
|
f"QAK|NF|{msg_id}\r"
|
||||||
|
)
|
||||||
|
conn.sendall(f"\x0b{rsp}\x1c\r".encode('utf-8'))
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"[GENEXPERT] Mengirim {len(orders)} order ke {ip_addr}")
|
||||||
|
|
||||||
|
for order in orders:
|
||||||
|
rsp = build_rsp_for_order(order, msg_id)
|
||||||
|
mllp = f"\x0b{rsp}\x1c\r"
|
||||||
|
conn.sendall(mllp.encode('utf-8'))
|
||||||
|
flag = get_flag_by_device(ip_addr)
|
||||||
|
setattr(order, flag, True)
|
||||||
|
session.add(order)
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def extract_msg_control_id(hl7_message):
|
||||||
|
try:
|
||||||
|
segments = hl7_message.split('\r')
|
||||||
|
msh = segments[0].split('|')
|
||||||
|
if len(msh) > 9:
|
||||||
|
return msh[9].strip()
|
||||||
|
return None
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def extract_requested_sample_id(hl7_message):
|
||||||
|
try:
|
||||||
|
for seg in hl7_message.split('\r'):
|
||||||
|
if seg.startswith('QPD|'):
|
||||||
|
fields = seg.split('|')
|
||||||
|
if len(fields) > 2:
|
||||||
|
return fields[2].strip()
|
||||||
|
return None
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_order_from_db(sample_id):
|
||||||
|
session = SessionLocal()
|
||||||
|
try:
|
||||||
|
order = session.query(PaslabOrder).filter(PaslabOrder.rnoreg == sample_id).first()
|
||||||
|
return order
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
def create_hl7_orm_message(order):
|
def create_hl7_orm_message(order):
|
||||||
timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
||||||
@@ -222,8 +307,9 @@ def create_hl7_orm_message(order):
|
|||||||
|
|
||||||
return f"{msh}\r{pid}\r{orc}\r{obr}\r"
|
return f"{msh}\r{pid}\r{orc}\r{obr}\r"
|
||||||
|
|
||||||
def parse_hl7_result(hl7_message, device_name="GeneXpert"):
|
def parse_hl7_result(conn, msg_id, hl7_message, device_name="GeneXpert"):
|
||||||
session = SessionLocal()
|
session = SessionLocal()
|
||||||
|
clean_hl7 = hl7_message
|
||||||
try:
|
try:
|
||||||
# 1. Bersihkan dan Split Pesan
|
# 1. Bersihkan dan Split Pesan
|
||||||
# HL7 dipisahkan oleh \r (Carriage Return)
|
# HL7 dipisahkan oleh \r (Carriage Return)
|
||||||
@@ -303,13 +389,9 @@ def parse_hl7_result(hl7_message, device_name="GeneXpert"):
|
|||||||
|
|
||||||
# 4. Validasi Data Penting (DIMODIFIKASI)
|
# 4. Validasi Data Penting (DIMODIFIKASI)
|
||||||
if not sample_id:
|
if not sample_id:
|
||||||
# JANGAN RETURN, tapi buat ID palsu agar tetap bisa masuk database
|
send_all_orders(conn, device_name, clean_hl7, msg_id)
|
||||||
timestamp_err = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
print("[HL7 Parser] Meminta order")
|
||||||
sample_id = f"ERR_{timestamp_err}"
|
return
|
||||||
logging.warning(f"[HL7 Parser] Sample ID kosong. Disimpan sebagai {sample_id} untuk audit.")
|
|
||||||
print(f"[HL7 Parser] Sample ID kosong. Disimpan sebagai {sample_id} untuk audit.")
|
|
||||||
# Tambahkan penanda di hasil agar Anda tahu ini error
|
|
||||||
final_result = f"[PARSE FAIL] {final_result}"
|
|
||||||
|
|
||||||
logging.info(f"[HL7 Parser] Menyimpan hasil untuk Sample: {sample_id}")
|
logging.info(f"[HL7 Parser] Menyimpan hasil untuk Sample: {sample_id}")
|
||||||
print(f"[HL7 Parser] Menyimpan hasil untuk Sample: {sample_id}")
|
print(f"[HL7 Parser] Menyimpan hasil untuk Sample: {sample_id}")
|
||||||
@@ -337,6 +419,46 @@ def parse_hl7_result(hl7_message, device_name="GeneXpert"):
|
|||||||
finally:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
|
def send_order_response(conn, hl7_msg, msg_id=None):
|
||||||
|
if not msg_id:
|
||||||
|
msg_id = extract_msg_control_id(hl7_msg)
|
||||||
|
|
||||||
|
# ambil sample_id yang diminta GeneXpert
|
||||||
|
sample_id = extract_requested_sample_id(hl7_msg)
|
||||||
|
|
||||||
|
print(f"[GENEXPERT] Request ORDER untuk sample_id: {sample_id}")
|
||||||
|
|
||||||
|
# cari order di database
|
||||||
|
order = find_order_from_db(sample_id)
|
||||||
|
|
||||||
|
if not order:
|
||||||
|
print(f"[GENEXPERT] Tidak ditemukan ORDER untuk {sample_id}. Balas NOT FOUND.")
|
||||||
|
rsp = (
|
||||||
|
f"MSH|^~\\&|LIS|LAB|GeneXpert|Cepheid|{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}||RSP^Z03|{msg_id}|P|2.5\r"
|
||||||
|
f"MSA|AE|{msg_id}\r"
|
||||||
|
f"QAK|NF|{msg_id}\r"
|
||||||
|
f"QPD|Z01^REQUEST TEST ORDERS|{msg_id}|ALL\r"
|
||||||
|
)
|
||||||
|
mllp = f"\x0b{rsp}\x1c\r"
|
||||||
|
conn.sendall(mllp.encode('utf-8'))
|
||||||
|
return
|
||||||
|
|
||||||
|
response_time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
||||||
|
|
||||||
|
rsp = (
|
||||||
|
f"MSH|^~\\&|LIS|LAB|GeneXpert|Cepheid|{response_time}||RSP^Z03|{msg_id}|P|2.5\r"
|
||||||
|
f"MSA|AA|{msg_id}\r"
|
||||||
|
f"QAK|OK|{msg_id}\r"
|
||||||
|
f"QPD|Z01^REQUEST TEST ORDERS|{sample_id}|ALL\r"
|
||||||
|
f"ORC|NW|{order.urut}\r"
|
||||||
|
f"OBR|1|{order.urut}|{order.rnoreg}|^{order.kd_spesimen}^{order.nm_spesimen}\r"
|
||||||
|
)
|
||||||
|
|
||||||
|
mllp = f"\x0b{rsp}\x1c\r"
|
||||||
|
conn.sendall(mllp.encode('utf-8'))
|
||||||
|
print(f"[GENEXPERT] >> RSP^Z03 terkirim untuk ORDER {order.urut}")
|
||||||
|
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# 4. NETWORK & COMMUNICATION LOGIC
|
# 4. NETWORK & COMMUNICATION LOGIC
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -361,23 +483,23 @@ def handle_tcp_client(client_socket, addr):
|
|||||||
# decode, parsing ASTM, save to DB
|
# decode, parsing ASTM, save to DB
|
||||||
try:
|
try:
|
||||||
msg = data.decode('latin-1', errors='ignore')
|
msg = data.decode('latin-1', errors='ignore')
|
||||||
logging.info(f"[TCP] Data dari {addr}: {msg[:50]}...")
|
logging.info(f"[TCP_HANDLING] Data dari {addr}: {msg[:50]}...")
|
||||||
print(f"[TCP] Data dari {addr}: {msg[:50]}...")
|
print(f"[TCP_HANDLING] Data dari {addr}: {msg[:50]}...")
|
||||||
# Panggil fungsi parser GeneXpert Anda disini
|
msg_id = extract_msg_control_id(msg)
|
||||||
parse_hl7_result(msg, device_name=addr[0] if addr else "Unknown")
|
parse_hl7_result(client_socket, msg_id, msg, device_name=addr[0] if addr else "Unknown")
|
||||||
|
|
||||||
# Kirim ACK ASTM jika perlu (\x06)
|
# Kirim ACK ASTM jika perlu (\x06)
|
||||||
client_socket.send(b'\x06')
|
client_socket.send(b'\x06')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"[TCP] Error processing data: {e}")
|
logging.error(f"[TCP_HANDLING] Error processing data: {e}")
|
||||||
print(f"[TCP] Error processing data: {e}")
|
print(f"[TCP_HANDLING] Error processing data: {e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"[TCP] Koneksi Error {addr}: {e}")
|
logging.error(f"[TCP_HANDLING] Koneksi Error {addr}: {e}")
|
||||||
print(f"[TCP] Koneksi Error {addr}: {e}")
|
print(f"[TCP_HANDLING] Koneksi Error {addr}: {e}")
|
||||||
finally:
|
finally:
|
||||||
client_socket.close()
|
client_socket.close()
|
||||||
logging.info(f"[TCP] Koneksi ditutup {addr}")
|
logging.info(f"[TCP_HANDLING] Koneksi ditutup {addr}")
|
||||||
print(f"[TCP] Koneksi ditutup {addr}")
|
print(f"[TCP_HANDLING] Koneksi ditutup {addr}")
|
||||||
|
|
||||||
def manage_tcp_server():
|
def manage_tcp_server():
|
||||||
"""Thread Server Utama untuk GeneXpert"""
|
"""Thread Server Utama untuk GeneXpert"""
|
||||||
@@ -419,7 +541,7 @@ def send_mllp_message(sock, hl7_msg):
|
|||||||
sock.sendall(mllp_msg)
|
sock.sendall(mllp_msg)
|
||||||
|
|
||||||
def handle_genexpert_client(conn, addr):
|
def handle_genexpert_client(conn, addr):
|
||||||
print(f"[TCP] Koneksi baru dari {addr}")
|
print(f"[GenExpert_TCP] Koneksi baru dari {addr}")
|
||||||
buffer = b""
|
buffer = b""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -484,12 +606,17 @@ def handle_genexpert_client(conn, addr):
|
|||||||
if "MSH|" in temp_str:
|
if "MSH|" in temp_str:
|
||||||
msh_index = temp_str.find("MSH|")
|
msh_index = temp_str.find("MSH|")
|
||||||
clean_hl7 = temp_str[msh_index:]
|
clean_hl7 = temp_str[msh_index:]
|
||||||
|
if "QBP^Z03" in clean_hl7:
|
||||||
|
print("[GENEXPERT] Alat meminta ORDER")
|
||||||
|
msg_id = extract_msg_control_id(clean_hl7)
|
||||||
|
send_all_orders(conn, addr[0], clean_hl7, msg_id)
|
||||||
|
continue
|
||||||
|
|
||||||
# Logging sample data (50 karakter)
|
# Logging sample data (50 karakter)
|
||||||
print(f"[TCP] Pesan Lengkap Diterima: {clean_hl7[:50]}...")
|
print(f"[GenExpert_TCP] Pesan Lengkap Diterima: {clean_hl7[:50]}...")
|
||||||
|
|
||||||
# Panggil Parser
|
# Panggil Parser
|
||||||
parse_hl7_result(clean_hl7, device_name=f"GeneXpert-{addr[0]}")
|
parse_hl7_result(conn, msg_id, clean_hl7, device_name=f"GeneXpert-{addr[0]}, ")
|
||||||
|
|
||||||
# --- KIRIM ACK ---
|
# --- KIRIM ACK ---
|
||||||
try:
|
try:
|
||||||
@@ -516,10 +643,10 @@ def handle_genexpert_client(conn, addr):
|
|||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"[TCP Error] Koneksi {addr} terputus: {e}")
|
logging.error(f"[GenExpert_TCP Error] Koneksi {addr} terputus: {e}")
|
||||||
finally:
|
finally:
|
||||||
conn.close()
|
conn.close()
|
||||||
logging.info(f"[TCP] Koneksi {addr} ditutup.")
|
logging.info(f"[GenExpert_TCP] Koneksi {addr} ditutup.")
|
||||||
|
|
||||||
def run_tcp_server():
|
def run_tcp_server():
|
||||||
"""Loop utama TCP Server"""
|
"""Loop utama TCP Server"""
|
||||||
|
|||||||
Reference in New Issue
Block a user