WebAGV - AGV 車隊即時監控看板

Vue 3 + Node.js + Socket.IO 打造的 AGV 資訊看板系統

WebAGV - AGV 車隊即時監控看板

專案簡介

WebAGV 是一套 AGV 車隊即時監控看板系統,由 WebAGVClient(前端)和 WebAGVServer(後端)組成。這個系統的目的是提供一個直觀的資訊看板,讓操作人員可以即時監控 AGV 在地圖上的位置、任務執行狀態、設備狀態等資訊。

與 RosAGV 的關係:

專案背景:


🎯 核心功能

1. 即時地圖監控

使用 Leaflet 地圖引擎顯示 AGV 位置:

地圖功能:


2. 即時通訊架構

多重通訊協定整合:

前端 (WebAGVClient)
    ↕️ Socket.IO (即時雙向通訊)
後端 (WebAGVServer)
    ├─ MQTT ← AGV 狀態資料
    ├─ ROS 2 (rclnodejs) ← ROS 2 節點通訊
    └─ PostgreSQL / MSSQL ← 資料庫存取

Socket.IO 命名空間:

MQTT 訂閱:


3. 資料視覺化

儀表板顯示:

資訊類型 顯示方式 更新頻率
AGV 位置 地圖 Marker 即時
電池電量 顏色編碼圖示 即時
任務狀態 文字標籤 即時
歷史軌跡 地圖路徑 按需載入
系統日誌 日誌檢視器 即時

電池電量顏色編碼:

0% - 19%:  紅色 (#F45)
20% - 39%: 橘色 (#FC5)
40% - 49%: 黃色 (#FE5)
50% - 100%: 綠色 (#8F5)

🏗️ 系統架構

WebAGVClient(前端)

技術棧:

專案結構:

src/
├── views/              # 頁面元件
│   ├── Home.vue       # 地圖監控主頁
│   ├── Task.vue       # 任務管理
│   ├── Signal.vue     # 訊號監控
│   ├── Log.vue        # 日誌檢視
│   ├── Login.vue      # 登入頁面
│   └── Dev.vue        # 開發工具
├── components/         # 可重用元件
│   ├── Sidebar.vue    # 側邊欄
│   ├── MapLegend.vue  # 地圖圖例
│   └── CopyRight.vue  # 版權資訊
├── services/           # API 服務
├── router/             # 路由配置
├── layouts/            # 佈局元件
└── store.js            # Pinia 狀態管理

WebAGVServer(後端)

技術棧:

專案結構:

src/
├── server.js           # 主伺服器入口
├── app.js              # Express 應用配置
├── api/                # RESTful API 路由
│   ├── apiRouter.js   # API 路由器
│   └── routes/        # 各功能路由
│       ├── logRoutes.js
│       ├── mapRoutes.js
│       ├── missionRoute.js
│       ├── taskRoutes.js
│       ├── signalRoutes.js
│       └── userRoutes.js
├── socket/             # Socket.IO 配置
│   ├── socketio.js    # Socket.IO 初始化
│   └── socketRouter.js # Socket 命名空間路由
├── mqtt/               # MQTT 配置
│   ├── mqtt.js        # MQTT 客戶端初始化
│   └── mqttRouter.js  # MQTT 主題訂閱
├── ros/                # ROS 2 整合
│   └── rosCore.js     # ROS 2 節點
├── db/                 # 資料庫
│   ├── database.js    # 資料庫連接
│   └── models/        # Sequelize 模型
├── services/           # 業務邏輯服務
│   └── dataPollingService.js # 資料輪詢
├── config/             # 配置檔案
└── utils/              # 工具函式

💻 核心技術實現

1. Leaflet 地圖整合

自定義 Marker 系統:

// AGV Marker 配置(每個 Marker 內含 3 個 Marker)
const agvMarkers = {
  mainMarker: L.marker(),     // 主要 AGV 圖示
  batteryMarker: L.divIcon(), // 電池圖示
  taskMarker: L.divIcon()     // 任務資訊
};

// 設備 Marker 配置(每個 Marker 內含 2 個 Marker)
const eqpMarkers = {
  mainMarker: L.marker(),     // 設備圖示
  nameMarker: L.divIcon()     // 設備名稱
};

Marker 旋轉(顯示 AGV 航向):

地圖座標系統:


2. Socket.IO 即時通訊

前端連接:

import { io } from "socket.io-client";

const socket = io("http://localhost:3000", {
  cors: {
    origin: "*"
  }
});

// 監聽 AGV 位置更新
socket.on("agv-update", (data) => {
  updateAGVPosition(data);
});

後端事件分發:

io.on("connection", (socket) => {
  console.log(`Client connected: ${socket.id}`);

  socket.on("disconnect", () => {
    console.log(`Client disconnected: ${socket.id}`);
  });
});

// 命名空間路由
socketRouter(io);

3. MQTT 整合

訂閱 AGV 狀態更新:

export function initMQTT() {
  const mqttClient = mqtt.connect(process.env.MQTT_BROKER_URL);

  mqttClient.on("connect", () => {
    console.log("Connected to MQTT broker");
    mqttRouter(mqttClient);
  });
}

MQTT 主題訂閱:


4. ROS 2 整合

使用 rclnodejs 橋接 ROS 2:

import rclnodejs from 'rclnodejs';

export async function startRosCore() {
  await rclnodejs.init();
  const node = new rclnodejs.Node('webagv_bridge');

  // 訂閱 ROS 2 主題
  const subscription = node.createSubscription(
    'std_msgs/msg/String',
    'agv_status',
    (msg) => {
      // 處理 ROS 2 訊息
      console.log('Received:', msg.data);
    }
  );

  rclnodejs.spin(node);
}

整合目的:


5. 資料輪詢服務

定期從資料庫更新資料:

export function dataPolling() {
  setInterval(async () => {
    // 從資料庫載入最新資料
    const agvData = await db.getAGVData();
    const eqpData = await db.getEquipmentData();

    // 透過 Socket.IO 廣播給所有客戶端
    io.emit("data-update", { agvData, eqpData });
  }, 1000); // 每秒更新
}

🎨 使用者介面

1. 地圖監控主頁(Home.vue)

功能:

互動功能:


2. 任務管理(Task.vue)

功能:


3. 訊號監控(Signal.vue)

功能:


4. 日誌檢視(Log.vue)

功能:


🔧 開發與部署

開發環境

前端開發:

cd WebAGVClient
npm install
npm run dev  # http://localhost:5173

後端開發:

cd WebAGVServer
npm install
npm start    # http://localhost:3000

生產部署

建置前端:

npm run build
# 產生 dist/ 目錄

部署流程:

npm run deploy
# 1. 建置前端(npm run build)
# 2. 複製 dist/* 到後端 public/ 目錄(npm run publish)

啟動後端伺服器:

npm start
# 同時提供 API 服務和靜態網頁

訪問網址:


🎯 技術亮點

1. 多重通訊協定整合

同時支援三種通訊方式:

為什麼需要三種?


2. 地圖視覺化技術

Leaflet 的優勢:

自定義功能:


3. Vue 3 Composition API

使用最新 Vue 3 語法:

<script setup>
import { ref, computed, onMounted, watch } from "vue";
import { useMainStore } from "../store";

const store = useMainStore();
const agvData = computed(() => store.agvData);

onMounted(() => {
  initializeMap();
});
</script>

優勢:


4. Pinia 狀態管理

集中管理應用狀態:

import { defineStore } from 'pinia';

export const useMainStore = defineStore('main', {
  state: () => ({
    agvData: [],
    eqpData: [],
    mapConfig: {}
  }),
  actions: {
    updateAGVData(data) {
      this.agvData = data;
    }
  }
});

5. 資料庫抽象層

支援多種資料庫:

使用 Sequelize ORM:


💡 開發體會

這個專案讓我學到:

多重通訊協定的整合挑戰:

地圖視覺化的複雜性:

即時性 vs 效能的平衡:

前後端分離的好處:


🚀 未來優化

目前系統運作良好,未來可優化的方向:


專案資訊


Happy Coding! 📊