---
name: scada-web-hmi
description: "ออกแบบและพัฒนาระบบ Web-based SCADA / HMI ด้วย HTML5 แบบครบวงจร ตั้งแต่สถาปัตยกรรมระบบ, การเชื่อมต่อ PLC/อุปกรณ์ผ่าน Modbus TCP-RTU / OPC UA / MQTT Sparkplug B, backend real-time (WebSocket + tag cache), หน้าจอ mimic diagram ตามมาตรฐาน ISA-101, ระบบ alarm ตาม ISA-18.2, historian/trend chart และ security ตาม IEC 62443. Use this skill when the user mentions \"SCADA\", \"Web SCADA\", \"HMI\", \"หน้าจอควบคุม\", \"mimic diagram\", \"Modbus\", \"OPC UA\", \"Sparkplug\", \"PLC\", \"RTU\", \"tag\", \"historian\", \"ระบบมอนิเตอร์โรงงาน\", \"industrial dashboard\" หรือเมื่อผู้ใช้ขอสร้างหน้าเว็บที่แสดงค่าจากเซนเซอร์/อุปกรณ์อุตสาหกรรมแบบ real-time หรือสั่งงานอุปกรณ์ผ่านเว็บ แม้จะไม่ได้พูดคำว่า SCADA ตรงๆ ก็ให้ใช้ skill นี้"
---

# 🏭 Web-based SCADA / HMI (HTML5)

## 📋 คำอธิบาย
ออกแบบและสร้างระบบ SCADA ที่ทำงานบนเว็บด้วย HTML5 ครบทุกชั้น ตั้งแต่การดึงค่าจาก
PLC/RTU/sensor → tag cache → real-time push → หน้าจอ HMI → alarm/trend → การสั่งงานกลับ
พร้อม security ที่จำเป็นสำหรับระบบควบคุมอุตสาหกรรม (ICS/OT)

## 🎯 เหมาะสำหรับ
Automation Engineer, SCADA Engineer, Full-stack Developer ที่ต้องทำงานกับระบบ OT,
System Integrator, ทีมที่กำลังย้ายจาก HMI แบบ desktop (WinCC / Ignition Vision / Wonderware)
มาเป็น web-based

## ⚡ วิธีเรียกใช้งาน
พิมพ์คำสั่งเหล่านี้เพื่อเปิดใช้งาน:
- ออกแบบระบบ Web SCADA สำหรับ [โรงงาน/กระบวนการ]
- ทำหน้าจอ HMI บนเว็บ / mimic diagram
- ต่อ Modbus / OPC UA / MQTT Sparkplug B เข้าเว็บ
- ทำระบบ alarm / trend / historian
- ตรวจ security ของระบบ SCADA บนเว็บ

---

## ⚠️ หลักคิดที่สำคัญที่สุด: SCADA HMI ไม่ใช่ Dashboard

นี่คือจุดที่พลาดกันมากที่สุด และเป็นเหตุผลที่ต้องมี skill นี้ Dashboard ทั่วไปทำเพื่อ "ดูสวยและเข้าใจง่าย"
แต่ HMI คือ **พื้นผิวควบคุม** ที่ operator ใช้ตัดสินใจสั่งงานเครื่องจักรจริง ข้อจำกัดจึงกลับด้านกันเกือบทั้งหมด:

| ประเด็น | Dashboard ทั่วไป | SCADA HMI |
|---|---|---|
| ข้อมูลเก่า/ขาดการเชื่อมต่อ | แสดงค่าล่าสุดต่อไปได้ | **ต้องแสดงชัดว่าไม่น่าเชื่อถือ** — ค่าเก่าที่ดูปกติอันตรายกว่าไม่มีค่าเลย |
| สี | ใช้ตกแต่งให้น่าสนใจ | เป็น **สัญญาณความปลอดภัย** — สีจัดสงวนไว้ให้ภาวะผิดปกติเท่านั้น |
| หน้าจอตอนทุกอย่างปกติ | สีสันสวยงาม | **เกือบเป็นสีเทาทั้งจอ** (ISA-101) |
| การเขียนค่า | POST แล้วจบ | ต้องมี interlock, ยืนยัน, อ่านกลับ, audit |
| ความหน่วง | ไม่ค่อยสำคัญ | มี budget ชัดเจนและต้องวัดได้ |

**สรุปสั้นที่สุด:** ถ้าออกแบบ SCADA HMI แล้วผลลัพธ์ออกมาหน้าตาเหมือน dashboard สวยๆ ที่มี gradient
สีนีออน แปลว่าออกแบบผิด อ่าน `references/hmi-design.md` ก่อนเขียน UI ทุกครั้ง

---

## 🏗️ สถาปัตยกรรมอ้างอิง

```
   L0/L1 (Field)          L2/L3 (Control/Site)        L3.5 (DMZ)         L4 (Enterprise)
┌──────────────────┐   ┌────────────────────────┐  ┌───────────────┐  ┌────────────────┐
│ Sensor / Actuator│   │  Protocol Gateway      │  │  Web / API    │  │  Browser       │
│ PLC / RTU / VFD  │◄─►│  + Tag Cache (in-mem)  │─►│  WebSocket hub│─►│  HTML5 HMI     │
│ Flow / Temp / Lvl│   │  + Alarm Engine        │  │  AuthN/AuthZ  │  │  SVG mimic     │
│                  │   │  + Historian writer    │  │  Audit log    │  │  Trend / Alarm │
└──────────────────┘   └────────────────────────┘  └───────────────┘  └────────────────┘
   Modbus TCP/RTU        มี process เดียวที่เป็น        ไม่ต่อ PLC โดยตรง     ไม่ poll PLC โดยตรง
   OPC UA                เจ้าของ connection             ไม่เก็บ credential    รับ push อย่างเดียว
   MQTT Sparkplug B      ของอุปกรณ์                    ของอุปกรณ์
```

**เหตุผลที่ต้องมี Gateway แยกจาก Web server:**
PLC ส่วนใหญ่รับ TCP connection พร้อมกันได้แค่ 2–8 socket และ PLC รุ่นเก่าอาจค้างได้ถ้าถูก poll หนักเกินไป
ถ้าปล่อยให้ web server หรือ browser ต่อ PLC ตรง ทุกครั้งที่มีคนเปิดหน้าจอเพิ่มคือ connection ใหม่
พอถึง 10 คนพร้อมกันระบบจะล่ม — ต้องมี process เดียวเป็นเจ้าของ connection แล้ว fan-out ให้ client หลายตัว

---

## 🚦 กฎที่ห้ามละเมิด (Non-negotiables)

ห้าข้อนี้คือสิ่งที่แยกระบบที่ใช้งานจริงได้ออกจากระบบที่ดูเหมือนใช้ได้ อธิบายเหตุผลไว้ด้วยเพื่อให้ปรับใช้กับบริบทอื่นได้

**1. ทุกค่าต้องมี 3 ส่วนเสมอ: value + timestamp + quality**
อย่าออกแบบ API ที่ตอบ `{"tank_level": 42}` เด็ดขาด ต้องเป็น
`{"v": 42.1, "t": 1755499200123, "q": "good"}` โดย `q` ∈ `good | bad | uncertain | stale`
เพราะเมื่อสายหลุด ค่า `42` จะยังคงแสดงบนจอต่อไปและ operator จะเชื่อว่าถังมีของอยู่จริง —
นี่คือสาเหตุอุบัติเหตุที่พบบ่อยที่สุดในระบบ SCADA ที่ทำโดยทีมเว็บ
และ **UI ต้องเรนเดอร์ค่า bad/stale ให้ต่างจากปกติอย่างชัดเจน** (เทาลง ขีดทับ ใส่ hatch pattern)
ไม่ใช่แค่เก็บ flag ไว้เฉยๆ

**2. Browser ห้าม poll อุปกรณ์ และ Gateway ต้อง poll แบบมีวินัย**
Browser subscribe จาก tag cache เท่านั้น ส่วน gateway อ่านจากอุปกรณ์ด้วย
report-by-exception + deadband + จำกัด max update rate ดูรายละเอียดใน `references/realtime-backend.md`

**3. ค่าเริ่มต้นของระบบเว็บคือ READ-ONLY**
การเขียนค่า/สั่งงานเป็นความสามารถที่ต้องเปิดใช้แยก ยืนยันตัวตนแยก และผ่าน whitelist ของคำสั่งที่กำหนดไว้
ห้ามมี endpoint แบบ "เขียน tag อะไรก็ได้" อ่าน `references/security-and-writes.md` ก่อนทำ write path ทุกครั้ง

**4. หน้าจอปกติต้องเป็นสีเทา — สีจัดสงวนไว้ให้ alarm**
ตามมาตรฐาน ISA-101 (High Performance HMI) ถ้าหน้าจอมีสีเยอะ เมื่อเกิดเหตุจริงจะไม่มีอะไรโดดออกมาให้เห็น
นี่คือกฎที่ขัดกับสัญชาตญาณการออกแบบเว็บทั่วไปที่สุด รายละเอียดใน `references/hmi-design.md`

**5. Timestamp มาจากต้นทาง ไม่ใช่จากเบราว์เซอร์**
ประทับเวลาที่ PLC หรืออย่างช้าที่สุดคือที่ gateway ส่งเป็น epoch milliseconds UTC
แล้วค่อยแปลงเป็น timezone ของโรงงานตอนแสดงผล ถ้าประทับเวลาตอนข้อมูลถึง browser
ค่าที่ค้างในคิว 5 วินาทีจะถูกบันทึกว่าเพิ่งเกิด ทำให้สืบสวนเหตุการณ์ย้อนหลังไม่ได้

---

## 🔄 กระบวนการทำงาน

### ขั้นตอนที่ 1: เก็บ requirement เชิง process ก่อนเชิงเทคนิค
ถามให้ได้ก่อนเริ่มออกแบบ เพราะคำตอบเปลี่ยนสถาปัตยกรรมทั้งหมด:
- กระบวนการอะไร มีอุปกรณ์กี่ตัว ประมาณกี่ tag (100 / 5,000 / 100,000 ต่างกันคนละระบบ)
- **ต้องสั่งงานกลับไหม หรือดูอย่างเดียว** — ถ้าดูอย่างเดียว ตัดงานความปลอดภัยออกได้ครึ่งหนึ่ง
- ความหน่วงที่ยอมรับได้เท่าไหร่ (1 วินาที กับ 100 มิลลิวินาที ออกแบบคนละแบบ)
- ต้องเก็บย้อนหลังนานแค่ไหน ความละเอียดเท่าไหร่ (มีผลกับการเลือก historian)
- operator กี่คนพร้อมกัน ใช้อุปกรณ์อะไร (จอควบคุมในห้อง control room หรือ tablet เดินตรวจ)
- อยู่ในเครือข่ายไหน ต้องเข้าจากภายนอกไหม (มีผลกับ security ทั้งหมด)

### ขั้นตอนที่ 2: ทำ Tag Dictionary
เอกสารกลางที่ทุกชั้นอ้างอิงร่วมกัน ทำก่อนเขียนโค้ดบรรทัดแรก:

| tagName | address | dataType | scale/offset | eng.unit | range | deadband | alarm limits | writable |
|---|---|---|---|---|---|---|---|---|
| `T101.Level` | `HR40001` | int16 | ×0.1 | % | 0–100 | 0.5 | HH 95, H 90, L 10 | no |
| `P201.Run` | `Coil 17` | bool | — | — | — | — | — | yes |

ชื่อ tag ควรสื่อลำดับชั้นอุปกรณ์ (`Area.Equipment.Signal`) เพราะจะกลายเป็นทั้งชื่อ element ใน SVG,
key ใน cache, ชื่อคอลัมน์ใน historian และข้อความใน alarm — ตั้งผิดตอนแรกแก้ทีหลังแพงมาก

### ขั้นตอนที่ 3: เลือกโปรโตคอลและเขียน Gateway
อ่าน `references/protocols.md` แล้วเลือกตามสถานการณ์:

| สถานการณ์ | เลือก |
|---|---|
| PLC เก่า / อุปกรณ์ราคาประหยัด / ต้องการง่ายที่สุด | **Modbus TCP** |
| PLC สมัยใหม่ ต้องการ security + subscription ในตัว + metadata | **OPC UA** |
| หลายไซต์ / ผ่าน cellular หรือ internet / edge-to-cloud | **MQTT Sparkplug B** |
| มี SCADA/historian อยู่แล้ว (Ignition, WinCC, PI) | เรียก REST API ของระบบเดิม อย่าไปแย่ง poll PLC |

### ขั้นตอนที่ 4: สร้าง Tag Cache + Real-time transport
อ่าน `references/realtime-backend.md` — ครอบคลุมโครงสร้าง cache, envelope ของ WebSocket,
deadband, การ resync ตอน reconnect และ backpressure

### ขั้นตอนที่ 5: ออกแบบหน้าจอ HMI
อ่าน `references/hmi-design.md` — ISA-101, การทำ mimic diagram ด้วย SVG,
การผูก tag เข้ากับ element, การเลือกใช้ SVG vs Canvas, trend chart, faceplate

### ขั้นตอนที่ 6: ระบบ Alarm
อ่าน `references/alarms.md` — state machine ตาม ISA-18.2, การกัน alarm flood, shelving,
และการ resync alarm list ตอน reconnect

### ขั้นตอนที่ 7: Security และ Write path
อ่าน `references/security-and-writes.md` — IEC 62443, การแบ่ง network zone,
command whitelist, read-back verification, audit trail

### ขั้นตอนที่ 8: ทดสอบด้วย Simulator ไม่ใช่ของจริง
ห้ามชี้ dev build ไปที่ PLC ที่กำลังคุมกระบวนการจริงเด็ดขาด ใช้:
```bash
python scripts/tag_simulator.py --port 8765
```
Simulator นี้ส่ง envelope รูปแบบเดียวกับ production พร้อมจำลองสายหลุด ค่า stale
และ alarm ตามรอบ เพื่อให้ทดสอบได้ว่า UI แสดงสถานะผิดปกติถูกต้องจริง —
ซึ่งเป็นส่วนที่เทสต์ยากที่สุดถ้าไม่มีตัวจำลอง

---

## 📚 เอกสารอ้างอิงเชิงลึก

อ่านเฉพาะไฟล์ที่เกี่ยวกับงานตรงหน้า ไม่ต้องอ่านทั้งหมด:

| ไฟล์ | อ่านเมื่อ |
|---|---|
| `references/protocols.md` | ต่ออุปกรณ์ — Modbus TCP/RTU, OPC UA, MQTT Sparkplug B พร้อมกับดักที่พบบ่อย |
| `references/realtime-backend.md` | ทำ tag cache, WebSocket/SSE, deadband, reconnect, scaling |
| `references/hmi-design.md` | ออกแบบหรือเขียนหน้าจอ — ISA-101, SVG mimic, trend, faceplate |
| `references/alarms.md` | ทำระบบ alarm — state machine, priority, flood suppression, shelving |
| `references/security-and-writes.md` | ทำ write path หรือประเมินความปลอดภัย — IEC 62443, audit |
| `scripts/tag_simulator.py` | ต้องการข้อมูลจำลองสำหรับพัฒนา/ทดสอบ |

---

## 📤 รูปแบบผลลัพธ์

เมื่อผู้ใช้ขอ "ออกแบบระบบ" ให้ส่งเอกสารตามโครงนี้ (ปรับความยาวตามขนาดงาน):

```
# ระบบ Web SCADA: [ชื่อกระบวนการ]

## 1. ขอบเขตและ requirement
- กระบวนการ / จำนวน tag / จำนวน operator
- Read-only หรือ read-write
- Latency budget: [X ms จากอุปกรณ์ถึงหน้าจอ]
- Data retention: [ความละเอียด / ระยะเวลา]

## 2. สถาปัตยกรรม
[แผนภาพชั้น field → gateway → web → browser พร้อมโปรโตคอลบนแต่ละเส้น]

## 3. Tag Dictionary
[ตาราง tagName / address / type / scale / unit / range / deadband / alarm / writable]

## 4. Protocol & Gateway
- โปรโตคอลที่เลือกและเหตุผล
- รอบ poll หรือ subscription parameter
- พฤติกรรมเมื่อการเชื่อมต่อล้มเหลว (ค่าเปลี่ยนเป็น quality อะไร ภายในกี่วินาที)

## 5. Real-time transport
- Envelope format
- Deadband / max update rate
- กลไก reconnect และ resync

## 6. หน้าจอ HMI
- ผังลำดับหน้าจอ (Level 1 overview → Level 2 unit → Level 3 detail)
- Mimic diagram แต่ละหน้า
- Color palette เชิงความหมาย

## 7. Alarm
- ตาราง alarm: tag / condition / limit / priority / delay / ข้อความถึง operator

## 8. Historian
- เทคโนโลยีที่เลือก / อัตราการเขียน / นโยบาย retention และ downsampling

## 9. Security
- แผนผัง network zone
- ผู้ใช้และสิทธิ์
- Write path และ audit
- ประเด็นความเสี่ยงที่เหลืออยู่

## 10. แผนการพัฒนา
[ลำดับงานเป็นเฟส พร้อมสิ่งที่ต้องตรวจสอบก่อนขึ้น production]
```

---

## 💡 เคล็ดลับ

- **ถามเรื่อง "สั่งงานได้ไหม" ให้ชัดตั้งแต่ประโยคแรก** — ระบบ read-only กับ read-write
  ต่างกันด้านความปลอดภัยและปริมาณงานหลายเท่าตัว ผู้ใช้หลายคนพูดว่า "มอนิเตอร์" แต่หมายถึงสั่งงานด้วย
- **ถ้าโรงงานมี SCADA อยู่แล้ว ให้ต่อผ่าน API ของระบบเดิม** อย่าไปเพิ่ม connection ที่ PLC แข่งกับระบบเดิม
  เพราะนอกจากเสี่ยงทำ PLC ค้าง ยังทำให้ค่าที่เห็นสองระบบไม่ตรงกันจนหา root cause ไม่ได้
- **หน้าจอ Level 1 ควรอ่านออกจากระยะ 3 เมตร** เพราะ operator ต้องเหลือบมองจากอีกฝั่งห้อง
  ตัวเลขค่ากระบวนการจึงต้องใหญ่กว่าที่คิดมาก
- **ทดสอบด้วยการดึงสาย** — ปิด gateway กลางคัน แล้วดูว่าหน้าจอเปลี่ยนเป็นสถานะ stale ภายในกี่วินาที
  ถ้าตัวเลขยังนิ่งอยู่เฉยๆ เหมือนเดิม แปลว่าระบบยังไม่พร้อมใช้งานจริง นี่คือเทสต์ที่สำคัญที่สุด
  และเป็นเทสต์ที่มักถูกลืม
- **อย่าใช้ 3D ถ้าไม่จำเป็นจริง** — โมเดล 3D สวยตอน demo แต่ทำให้ operator หาข้อมูลช้าลง
  และโหลดนานขึ้น ใช้เมื่อความสัมพันธ์เชิงพื้นที่สำคัญต่อการตัดสินใจเท่านั้น
