# STK Agent RPC 通訊系統 — 完整規格書

> 版本: 1.0 | 日期: 2026-05-19

---

## 一、架構

```
┌─────────────────┐       UDP 廣播 (port 9527)      ┌──────────────────┐
│  stk_commander   │ ──────────────────────────────→ │   stk_agent      │
│  (SERVER 管理端) │       TCP 回報 (port 9528)      │   (CLIENT 常駐)  │
│  Harbour + GTWVT │ ←────────────────────────────── │   Harbour EXE    │
│  系統匣圖示      │                                  │   系統匣圖示     │
└─────────────────┘                                  └──────────────────┘
                                                      × N 台工作站
```

### 通訊方式
- **指令下發**: UDP 廣播 port 9527（一次發送全部收到）
- **結果回報**: TCP 連回 SERVER port 9528（確保送達）
- **檔案傳輸**: TCP port 9529（獨立 port，大檔傳輸）
- **心跳**: UDP port 9527（定期自動發送）

---

## 二、封包格式（JSON）

### 指令封包（SERVER → CLIENT，UDP 廣播）
```json
{
  "magic": "STKAGENT1",
  "cmd": "SHUTDOWN",
  "from": "S001",
  "target": "*",
  "time": "2026-05-19 15:30:00",
  "id": "uuid-xxxx",
  "token": "stk2026",
  "params": {}
}
```

| 欄位 | 說明 |
|------|------|
| magic | 固定標頭，防誤觸發 |
| cmd | 指令名稱 |
| from | 發送端站名 |
| target | 目標站（"*"=全部, "S002"=指定站, "S002,S003"=多站） |
| time | 發送時間 |
| id | 唯一識別碼（用於配對回報） |
| token | 驗證密鑰 |
| params | 指令參數（依指令不同） |

### 回報封包（CLIENT → SERVER，TCP）
```json
{
  "magic": "STKAGENT1",
  "cmd": "SHUTDOWN",
  "station": "S002",
  "status": "OK",
  "time": "2026-05-19 15:30:01",
  "id": "uuid-xxxx",
  "data": {}
}
```

| 欄位 | 說明 |
|------|------|
| status | "OK" / "FAIL" / "BUSY" |
| data | 回報資料（依指令不同） |

---

## 三、完整指令清單

### A. 基本控制

| # | 指令 | 說明 | params | 回報 data |
|---|------|------|--------|-----------|
| A1 | PING | 探測在線 | — | station, uptime, stk_running |
| A2 | SHUTDOWN | 通知 STK32 倒數退出 | timeout:60 | — |
| A3 | KILL_STK | 強制關閉 STK32.EXE | — | — |
| A4 | POWEROFF | 關機 | delay:30 | — |
| A5 | REBOOT | 重新開機 | delay:30 | — |
| A6 | LOCK_SCREEN | 鎖定螢幕 | — | — |
| A7 | WAKE_ON_LAN | 喚醒工作站（由 SERVER 發） | mac:"xx:xx:xx:xx:xx:xx" | — |

### B. 訊息通知

| # | 指令 | 說明 | params | 回報 data |
|---|------|------|--------|-----------|
| B1 | MESSAGE | 彈出訊息框 | text, title | user_clicked:"OK"/"Cancel" |
| B2 | NOTIFY | 系統匣氣球通知 | text, title, timeout:5 | — |

### C. 遠端監控

| # | 指令 | 說明 | params | 回報 data |
|---|------|------|--------|-----------|
| C1 | STATUS | 系統狀態 | — | cpu, mem_total, mem_free, disk_total, disk_free, stk_running, uptime, os_version |
| C2 | PROCLIST | 程序列表 | — | processes[{name, pid, mem}] |
| C3 | PRINTER_STATUS | 印表機狀態 | — | printers[{name, status, jobs}] |
| C4 | SCREENSHOT | 截取畫面 | — | (透過 FILE_PUSH 回傳圖檔) |

### D. 遠端執行

| # | 指令 | 說明 | params | 回報 data |
|---|------|------|--------|-----------|
| D1 | EXEC | 執行命令 | command, wait:true/false | exitcode, stdout, stderr |
| D2 | DEPLOY_ZIP | 解壓 ZIP 到指定路徑 | src:"W:\TOOLS\xxx.zip", dest:"C:\xxx" | — |
| D3 | DISK_CLEANUP | 清理暫存檔 | paths:["C:\TEMP","W:\S00X\TMP"] | freed_bytes |
| D4 | CONFIG_PUSH | 推送 INI 設定 | file:"System.ini", section:"UI", key:"ColorTheme", value:"2" | — |

### E. 檔案傳輸

| # | 指令 | 說明 | params | 回報 data |
|---|------|------|--------|-----------|
| E1 | FILE_PUSH | SERVER 推送檔案到 CLIENT | filename, dest_path, size | — |
| E2 | FILE_PULL | 從 CLIENT 拉取檔案 | src_path | filename, size |
| E3 | LOG_COLLECT | 收集 CLIENT 的 LOG 檔案 | files:["Error.TXT","stk_agent.log"] | (透過 FILE_PULL 回傳) |

### F. 系統管理

| # | 指令 | 說明 | params | 回報 data |
|---|------|------|--------|-----------|
| F1 | HEARTBEAT | 心跳（CLIENT 定期自動發送） | — | station, stk_running, cpu, mem_free |
| F2 | UPDATE_AGENT | Agent 自我更新 | version, url | — |
| F3 | BATCH_CMD | 批次指令（SERVER 端對多站） | targets:["S002","S003"], cmd:"SHUTDOWN" | — |
| F4 | GET_CONFIG | 讀取 CLIENT 的 INI 設定 | file, section, key | value |

---

## 四、stk_agent.exe（CLIENT 端）

### 技術
- Harbour + 內建 hb_socket*() API
- 系統匣圖示（WinAPI Shell_NotifyIcon）
- 多執行緒：hb_threadStart（UDP 監聽 + 主迴圈分離）
- JSON：hb_jsonDecode / hb_jsonEncode（Harbour 內建）

### 程式架構
```
Main()
  ├── LoadConfig("stk_agent.ini")
  ├── InitTrayIcon()
  ├── InitLog()
  ├── hb_threadStart(@UDPListenerThread())   ← 背景 UDP 監聽
  ├── hb_threadStart(@HeartbeatThread())     ← 背景心跳發送
  └── MessageLoop()                          ← 主迴圈（系統匣事件）
       ├── OnTrayClick()    → 顯示狀態/選單
       ├── OnTrayMenu()     → 手動操作
       └── OnQuit()         → 退出
```

### UDP 監聽執行緒
```
UDPListenerThread():
  socket := hb_socketOpen(HB_SOCKET_AF_INET, HB_SOCKET_PT_DGRAM)
  hb_socketBind(socket, {HB_SOCKET_AF_INET, "0.0.0.0", 9527})
  LOOP:
    cData := hb_socketRecv(socket, ...)
    hCmd := hb_jsonDecode(cData)
    IF ValidateMagicToken(hCmd)
      IF MatchTarget(hCmd["target"], cMyStation)
        ExecuteCommand(hCmd)
      ENDIF
    ENDIF
```

### 指令處理
```
ExecuteCommand(hCmd):
  SWITCH hCmd["cmd"]:
    CASE "PING"         → CollectStatus() → TCPReport()
    CASE "SHUTDOWN"     → taskkill STK32 或建 FLG → TCPReport()
    CASE "KILL_STK"     → taskkill /F /IM STK32.EXE → TCPReport()
    CASE "POWEROFF"     → shutdown /s /t N → TCPReport()
    CASE "REBOOT"       → shutdown /r /t N → TCPReport()
    CASE "LOCK_SCREEN"  → LockWorkStation() → TCPReport()
    CASE "MESSAGE"      → MessageBox(text) → TCPReport(user_response)
    CASE "NOTIFY"       → BalloonTip(text, title) → TCPReport()
    CASE "STATUS"       → CollectFullStatus() → TCPReport()
    CASE "PROCLIST"     → EnumProcesses() → TCPReport()
    CASE "PRINTER_STATUS" → EnumPrinters() → TCPReport()
    CASE "SCREENSHOT"   → CaptureScreen() → FILE_PUSH to SERVER
    CASE "EXEC"         → ShellExecute(cmd) → TCPReport(output)
    CASE "DEPLOY_ZIP"   → UnzipFile(src,dest) → TCPReport()
    CASE "DISK_CLEANUP" → DeleteTempFiles(paths) → TCPReport(freed)
    CASE "CONFIG_PUSH"  → WriteINI(file,section,key,value) → TCPReport()
    CASE "GET_CONFIG"   → ReadINI(file,section,key) → TCPReport(value)
    CASE "FILE_PUSH"    → StartTCPFileReceive() → TCPReport()
    CASE "FILE_PULL"    → StartTCPFileSend() → TCPReport()
    CASE "LOG_COLLECT"  → FILE_PULL multiple files
    CASE "UPDATE_AGENT" → DownloadNewVersion() → RestartSelf()
```

### TCP 回報
```
TCPReport(hCmd, cStatus, hData):
  socket := hb_socketOpen(HB_SOCKET_AF_INET, HB_SOCKET_PT_STREAM)
  hb_socketConnect(socket, {HB_SOCKET_AF_INET, cServerIP, 9528})
  cJSON := hb_jsonEncode({
    "magic": "STKAGENT1",
    "cmd": hCmd["cmd"],
    "station": cMyStation,
    "status": cStatus,
    "id": hCmd["id"],
    "data": hData
  })
  hb_socketSend(socket, cJSON)
  hb_socketClose(socket)
```

### stk_agent.ini
```ini
[Agent]
STATION_NAME=S002
UDP_PORT=9527
TCP_REPORT_PORT=9528
TCP_FILE_PORT=9529
SERVER_IP=192.168.1.1
TOKEN=stk2026

[Heartbeat]
ENABLED=true
INTERVAL=60

[Log]
LOG_FILE=stk_agent.log
LOG_LEVEL=1
MAX_SIZE=10MB

[Paths]
STK_EXE=W:\S002\STK32.EXE
TEMP_DIR=C:\TEMP
```

---

## 五、stk_commander.exe（SERVER 端）

### 程式架構
```
Main()
  ├── LoadConfig("stk_commander.ini")
  ├── InitTrayIcon()
  ├── hb_threadStart(@TCPListenerThread())   ← 背景接收回報
  ├── hb_threadStart(@HeartbeatMonitor())    ← 監控心跳
  └── MainUI()                               ← 操作介面
       ├── Dashboard()      → 工作站總覽
       ├── SendCommand()    → 發送指令
       ├── FileManager()    → 檔案傳輸
       └── LogViewer()      → 查看日誌
```

### Dashboard 顯示
```
┌─ STK Commander ──────────────────────────────────────────┐
│ #   Station  Status   STK32  CPU  MEM    Disk   LastSeen │
│ 1   S001     Online   Run    12%  4.2G   120G   15:30:01 │
│ 2   S002     Online   Run     8%  3.1G    80G   15:30:02 │
│ 3   S003     Offline  —       —    —       —    14:20:33 │
│ 4   S004     Online   Idle    3%  2.8G    60G   15:30:01 │
├──────────────────────────────────────────────────────────┤
│ [F1]Ping All [F2]Shutdown [F3]Kill [F4]Message [F5]Status│
│ [F6]Exec [F7]File [F8]Deploy [F9]Cleanup [F10]Power      │
└──────────────────────────────────────────────────────────┘
```

### stk_commander.ini
```ini
[Commander]
UDP_PORT=9527
TCP_REPORT_PORT=9528
TCP_FILE_PORT=9529
TOKEN=stk2026
BROADCAST_ADDR=192.168.1.255

[Stations]
PREFIX=S
FROM=1
TO=20

[Log]
LOG_FILE=stk_commander.log
LOG_LEVEL=1

[UI]
REFRESH_INTERVAL=5
```

---

## 六、檔案傳輸協議（TCP port 9529）

### FILE_PUSH（SERVER → CLIENT）
```
1. SERVER 發 UDP 指令: FILE_PUSH {filename, dest_path, size}
2. CLIENT 收到 → 開 TCP 9529 監聽
3. SERVER TCP 連線 → 發送檔案內容（分塊 64KB）
4. CLIENT 接收完成 → 寫入 dest_path → TCP 回報 OK
```

### FILE_PULL（CLIENT → SERVER）
```
1. SERVER 發 UDP 指令: FILE_PULL {src_path}
2. CLIENT 收到 → TCP 連回 SERVER 9529 → 發送檔案內容
3. SERVER 接收完成 → 寫入本地 → 顯示完成
```

---

## 七、安全性

| 項目 | 方案 |
|------|------|
| 身份驗證 | JSON 封包含 token（共享密鑰，ini 設定） |
| 防偽造 | magic header "STKAGENT1" |
| 指令來源 | 只接受 SERVER_IP 發來的封包 |
| 危險指令 | POWEROFF/REBOOT/EXEC/KILL_STK 需二次確認（commander 端） |
| 加密 | Phase 4 可加 AES 加密封包內容 |

---

## 八、實作分期

### Phase 1：基礎通訊（最小可用）
- UDP 監聽/廣播
- TCP 回報
- PING / SHUTDOWN / KILL_STK
- 系統匣圖示（基本）
- stk_agent.ini / stk_commander.ini

### Phase 2：遠端管理
- STATUS / PROCLIST
- MESSAGE / NOTIFY
- EXEC
- POWEROFF / REBOOT / LOCK_SCREEN
- HEARTBEAT + 掉線偵測
- Commander Dashboard UI

### Phase 3：檔案傳輸 + 部署
- FILE_PUSH / FILE_PULL
- DEPLOY_ZIP
- LOG_COLLECT
- CONFIG_PUSH / GET_CONFIG
- UPDATE_AGENT

### Phase 4：進階功能
- SCREENSHOT
- PRINTER_STATUS
- DISK_CLEANUP
- WAKE_ON_LAN
- BATCH_CMD（指定站群）
- 加密通訊
- 歷史記錄 / 報表

---

## 九、檔案結構

```
E:\ConvertFW\SOCKET\
├── StkAgent\
│   ├── source\
│   │   ├── stk_agent.prg       ← 主程式 + 系統匣
│   │   ├── udp_listener.prg    ← UDP 監聽執行緒
│   │   ├── tcp_report.prg      ← TCP 回報模組
│   │   ├── tcp_file.prg        ← TCP 檔案傳輸
│   │   ├── cmd_handler.prg     ← 指令處理分發
│   │   ├── cmd_control.prg     ← 基本控制指令（A1~A7）
│   │   ├── cmd_monitor.prg     ← 監控指令（C1~C4）
│   │   ├── cmd_execute.prg     ← 執行指令（D1~D4）
│   │   ├── cmd_file.prg        ← 檔案指令（E1~E3）
│   │   ├── cmd_system.prg      ← 系統管理（F1~F4）
│   │   ├── sys_info.prg        ← 系統資訊收集（CPU/MEM/DISK）
│   │   ├── tray_icon.prg       ← 系統匣圖示
│   │   └── heartbeat.prg       ← 心跳執行緒
│   ├── c_code\
│   │   ├── trayicon_c.c        ← Shell_NotifyIcon 封裝
│   │   ├── sysinfo_c.c         ← GetSystemInfo/GlobalMemoryStatus
│   │   └── lockscreen_c.c      ← LockWorkStation 封裝
│   ├── include\
│   │   └── stk_agent.ch        ← 常數定義
│   └── build\
│       ├── stk_agent.hbp
│       └── stk_agent.ini
│
├── StkCommander\
│   ├── source\
│   │   ├── stk_commander.prg   ← 主程式 + UI
│   │   ├── udp_sender.prg      ← UDP 廣播
│   │   ├── tcp_listener.prg    ← TCP 接收回報
│   │   ├── tcp_file.prg        ← TCP 檔案傳輸
│   │   ├── dashboard.prg       ← 工作站總覽 UI
│   │   ├── station_mgr.prg     ← 工作站狀態管理
│   │   ├── heartbeat_mon.prg   ← 心跳監控
│   │   └── wake_on_lan.prg     ← WOL 喚醒
│   ├── include\
│   │   └── stk_commander.ch
│   └── build\
│       ├── stk_commander.hbp
│       └── stk_commander.ini
│
├── shared\
│   ├── protocol.ch             ← 共用常數（指令碼、port、magic）
│   ├── json_helper.prg         ← JSON 封包建構/解析
│   └── socket_helper.prg       ← Socket 共用函式
│
└── doc\
    ├── STK_Agent_RPC_spec.md   ← 本文件
    └── STK_Agent_RPC_spec.pdf
```

---

## 十、技術要點

| 項目 | 方案 |
|------|------|
| Socket | Harbour 內建 hb_socket*()，不需額外 lib |
| JSON | Harbour 內建 hb_jsonDecode/hb_jsonEncode |
| 多執行緒 | hb_threadStart()（Harbour 內建） |
| 系統匣 | C code Shell_NotifyIcon（小函式，BCC 不會 ICE） |
| 系統資訊 | C code GetSystemInfo/GlobalMemoryStatus |
| 螢幕截圖 | C code BitBlt + 存 BMP（Phase 4） |
| WOL | UDP 廣播 magic packet（純 Harbour） |
| 印表機 | C code EnumPrinters（Phase 4） |
