EP09: Programming with Database

8: การเขียนโปรแกรมเชื่อมต่อฐานข้อมูล (Programming with Database)


ส่วนที่ 1: การบรรยาย

หัวข้อ: สถาปัตยกรรมระบบ IoT สำหรับ Smart Factory และบทนำสู่ Python

ภาพรวมสถาปัตยกรรม Smart Factory Data Pipeline

  1. ชั้นกายภาพ (Physical Layer): ESP32 + Sensor (เช่น เซ็นเซอร์อุณหภูมิ DHT22) ทำหน้าที่ “ตรวจจับ” ข้อมูลจากโลกจริง
  2. ชั้นสื่อสาร (Communication Layer): ข้อมูลถูกส่งผ่านเครือข่าย (เช่น Wi-Fi) โดยใช้โปรโตคอลสื่อสาร (เช่น HTTP, MQTT)
  3. ชั้นแอปพลิเคชัน (Application Layer): สคริปต์ Python ที่ทำงานบนคอมพิวเตอร์หรือเซิร์ฟเวอร์ ทำหน้าที่ “รับ” ข้อมูลจาก ESP32, “ประมวลผลเบื้องต้น”, และ “ส่งต่อ” ไปยังฐานข้อมูล
  4. ชั้นข้อมูล (Data Layer): ฐานข้อมูล (PostgreSQL/MySQL) ที่เราเรียนกันมา ทำหน้าที่ “จัดเก็บ” ข้อมูลอย่างมีโครงสร้าง

ทำไมต้องใช้ Python และ ESP32?

  • Python:
    • ภาษามนุษย์: ไวยากรณ์ (Syntax) อ่านง่าย เข้าใจง่าย เหมาะสำหรับผู้เริ่มต้น
    • กาวชั้นดี (Glue Language): มี “คลังเครื่องมือ” หรือไลบรารี (Library) ขนาดใหญ่ที่ใช้เชื่อมต่อกับเทคโนโลยีอื่นๆ ได้อย่างง่ายดาย
    • ไลบรารีสำคัญที่เราจะใช้:
      • psycopg2 (สำหรับ PostgreSQL) หรือ mysql-connector-python (สำหรับ MySQL) -> ตัวแปลภาษาระหว่าง Python กับ SQL
      • pandas -> สุดยอดเครื่องมือจัดการข้อมูล (จะใช้ในสัปดาห์ถัดๆ ไป)
  • ESP32:
    • คอมพิวเตอร์จิ๋วราคาถูก: เป็นไมโครคอนโทรลเลอร์ (Microcontroller) ที่มีประสิทธิภาพสูง
    • ความสามารถครบครัน: มี Wi-Fi และ Bluetooth ในตัว เหมาะสำหรับงาน IoT
    • บทบาทในโรงงาน: ใช้เป็นสมองกลของเซ็นเซอร์ต่างๆ เพื่ออ่านค่าและส่งข้อมูลเข้าระบบกลาง

หลักการทำงานของ Database Connector

  • เปรียบเทียบ: Database Connector ก็เหมือน “ล่าม” หรือ “ทูต”
    • โค้ด Python ของเราพูด “ภาษาไพธอน”
    • ฐานข้อมูลของเราพูด “ภาษา SQL”
    • psycopg2 หรือ mysql-connector ทำหน้าที่แปลคำสั่งจาก Python ให้เป็น SQL ที่ฐานข้อมูลเข้าใจ และแปลผลลัพธ์จาก SQL กลับมาเป็นข้อมูลที่ Python ใช้งานต่อได้
  • ภาพรวมขั้นตอนการทำงานในโค้ด Python (The 4 Steps):
    1. Connect: สร้างการเชื่อมต่อ (ต้องระบุ ที่อยู่, ชื่อฐานข้อมูล, ผู้ใช้, รหัสผ่าน)
    2. Cursor: สร้าง “ตัวชี้” หรือ “รีโมต” สำหรับส่งคำสั่ง
    3. Execute: สั่งให้รีโมต “ทำงาน” โดยส่งคำสั่ง SQL เข้าไป
    4. Close: “ตัดการเชื่อมต่อ” เมื่อทำงานเสร็จ (สำคัญมาก!)

ส่วนที่ 2: การฝึกปฏิบัติ

หัวข้อ: Workshop: เขียนสคริปต์ Python แรกเพื่อคุยกับฐานข้อมูล

เครื่องมือ: คอมพิวเตอร์ที่มี Python, VS Code (หรือ Text Editor อื่นๆ), และเชื่อมต่อเครือข่ายกับ Database Server ได้

ขั้นตอนที่ 1: การติดตั้งและเตรียมสภาพแวดล้อม (Environment Setup)

  1. ติดตั้ง Python: (หากยังไม่มีในเครื่อง)
  2. แนะนำ pip (Package Installer for Python):
    • เปิด Command Prompt หรือ Terminal
    • สอนคำสั่ง pip install <ชื่อไลบรารี>
  3. ติดตั้ง Database Connector:
    • สำหรับ PostgreSQL: pip install psycopg2-binary
    • สำหรับ MySQL: pip install mysql-connector-python
  4. แนะนำ VS Code: สอนการสร้างไฟล์ใหม่ (เช่น connect_db.py) และการเปิด Terminal ใน VS Code เพื่อรันสคริปต์

ขั้นตอนที่ 2: การเขียนสคริปต์เชื่อมต่อฐานข้อมูล (The Connection Script)

  • ภารกิจ: ให้นักศึกษาเขียนโค้ดตาม และแก้ไขส่วนของ conn_params ให้เป็นข้อมูลของตัวเอง
Python
# สำหรับ PostgreSQL
import psycopg2

# สำหรับ MySQL
# import mysql.connector

# 1. กำหนดข้อมูลสำหรับการเชื่อมต่อ
conn_params = {
    "host": "127.0.0.1",  # หรือ IP Address ของ Server
    "database": "smart_factory_week4",
    "user": "your_username",
    "password": "your_password"
}

# 2. สร้างตัวแปรสำหรับเก็บการเชื่อมต่อ
conn = None

try:
    # 3. พยายามเชื่อมต่อฐานข้อมูล
    print("กำลังพยายามเชื่อมต่อฐานข้อมูล...")
    # conn = psycopg2.connect(**conn_params) # สำหรับ PostgreSQL
    # conn = mysql.connector.connect(**conn_params) # สำหรับ MySQL

    print("เชื่อมต่อฐานข้อมูลสำเร็จ!")

except Exception as error:
    # 4. หากเกิดข้อผิดพลาดในการเชื่อมต่อ
    print(f"เกิดข้อผิดพลาดในการเชื่อมต่อ: {error}")

finally:
    # 5. ตรวจสอบและปิดการเชื่อมต่อเสมอ ไม่ว่าจะสำเร็จหรือล้มเหลว
    if conn is not None:
        conn.close()
        print("ตัดการเชื่อมต่อฐานข้อมูลแล้ว")
  • ช่วงแก้ปัญหา (Troubleshooting): ปัญหา เช่น รหัสผ่านผิด, ติด Firewall, ชื่อฐานข้อมูลผิด, ลืมเปิด service ฐานข้อมูล

ขั้นตอนที่ 3: การดึงข้อมูลมาแสดงผล (Fetch & Display Data)

  • ภารกิจ: ต่อยอดจากสคริปต์ที่เชื่อมต่อสำเร็จแล้ว ให้เพิ่มโค้ดส่วนของการดึงข้อมูลเข้ามา
Python
# ... (โค้ดส่วนเชื่อมต่อเหมือนเดิม) ...

try:
    print("กำลังพยายามเชื่อมต่อฐานข้อมูล...")
    conn = psycopg2.connect(**conn_params)
    print("เชื่อมต่อฐานข้อมูลสำเร็จ!")

    # สร้าง Cursor object
    cur = conn.cursor()

    # ส่งคำสั่ง SQL เพื่อดึงข้อมูล
    print("\n--- รายชื่อเครื่องจักรทั้งหมด ---")
    cur.execute("SELECT machine_id, machine_name, location FROM machines;")

    # ดึงผลลัพธ์ทั้งหมดมาเก็บไว้
    all_machines = cur.fetchall()

    # วนลูปเพื่อแสดงผลทีละแถว
    for machine in all_machines:
        print(f"ID: {machine[0]}, Name: {machine[1]}, Location: {machine[2]}")

    # ปิด Cursor
    cur.close()

except Exception as error:
    print(f"เกิดข้อผิดพลาด: {error}")

finally:
    if conn is not None:
        conn.close()
        print("\nตัดการเชื่อมต่อฐานข้อมูลแล้ว")
  • มอบหมายงานย่อย: “ให้นักศึกษาแก้ไขโค้ดเพื่อดึงข้อมูลจากตาราง employees มาแสดงผลแทน”

เพิ่มตารางใหม่สำหรับ “Data Logs”

เพิ่มตารางใหม่ ขึ้นมาโดยเฉพาะเพื่อทำหน้าที่เป็น “สมุดบันทึกข้อมูลจากเซ็นเซอร์” (Sensor Data Logs) โดยตารางนี้จะเชื่อมโยงกลับไปยังตาราง machines เดิม

การออกแบบตารางใหม่ชื่อว่า sensor_logs ดังนี้ครับ

ตาราง: sensor_logs

ชื่อคอลัมน์ (Column Name)ชนิดข้อมูล (Data Type)คำอธิบาย (Description)
log_idBIGSERIAL (PostgreSQL) / BIGINT AUTO_INCREMENT (MySQL)Primary Key รหัสของ Log แต่ละรายการ (ใช้ตัวเลขขนาดใหญ่เพราะข้อมูลจะเยอะมาก)
timestamp_evtTIMESTAMP WITH TIME ZONETimestamp สำคัญที่สุด! บอกว่าข้อมูลนี้เกิดขึ้นเมื่อไหร่ (เก็บ Timezone ด้วยเป็น Best Practice)
machine_id_fkINTForeign Key ชี้กลับไปยัง machine_id ในตาราง machines เพื่อให้รู้ว่าเป็นข้อมูลของเครื่องจักรใด
metric_typeVARCHAR(50)ชนิดของค่าที่วัดได้ เช่น ‘temperature’, ‘humidity’, ‘vibration’, ‘pressure’
metric_valueDECIMAL(10, 2)ค่าที่วัดได้จากเซ็นเซอร์ (ใช้ DECIMAL เพื่อความแม่นยำ)

ความสัมพันธ์ใหม่:

  • machines 1 เครื่อง จะมีความสัมพันธ์แบบ One-to-Many ไปยัง sensor_logs
  • (เครื่องจักร 1 เครื่อง สามารถมี log data ได้เป็นล้านๆ records)

คำสั่ง SQL สำหรับสร้างตารางใหม่

SQL
CREATE TABLE sensor_logs (
    log_id BIGINT AUTO_INCREMENT PRIMARY KEY,
    timestamp_evt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    machine_id_fk INT,
    metric_type VARCHAR(50) NOT NULL,
    metric_value DECIMAL(10, 2) NOT NULL,
    FOREIGN KEY (machine_id_fk) REFERENCES machines(machine_id)
);