Files
BQP/srcs/RobotNet10/FleetManager/README.md
2026-07-13 09:25:40 +07:00

416 lines
14 KiB
Markdown

# RobotNet10.FleetManager
Hệ thống quản lý và điều phối đội robot AMR (Autonomous Mobile Robot) theo chuẩn **VDA 5050**, xây dựng trên nền tảng **.NET 10 Blazor**.
---
## Mục lục
- [Tổng quan](#tổng-quan)
- [Yêu cầu hệ thống](#yêu-cầu-hệ-thống)
- [Cấu trúc project](#cấu-trúc-project)
- [Cấu hình](#cấu-hình)
- [Build & Chạy local](#build--chạy-local)
- [Docker](#docker)
- [Các services phụ thuộc](#các-services-phụ-thuộc)
- [Tài khoản mặc định](#tài-khoản-mặc-định)
---
## Tổng quan
FleetManager là ứng dụng **Blazor Web App** chạy trên server nhà máy, cung cấp:
| Tính năng | Mô tả |
|---|---|
| **Robot Management** | Quản lý kết nối và trạng thái nhiều robot qua MQTT/VDA 5050 |
| **Traffic Control** | Tự động tính route, phát hiện và giải quyết xung đột |
| **Map Editor** | Tạo và quản lý bản đồ nhà máy |
| **Script Engine** | Viết và chạy C# script để tự động hóa mission |
| **Real-time Monitor** | Theo dõi toàn đội robot qua SignalR |
| **Web UI** | Giao diện Blazor + MudBlazor (15 trang) |
**Tech stack:** .NET 10 · Blazor (Server + WASM) · SignalR · MQTT (MQTTnet 5) · EF Core · SQL Server · MinIO
---
## Yêu cầu hệ thống
### Để build
| Yêu cầu | Phiên bản |
|---|---|
| .NET SDK | **10.0** trở lên |
| Git | Bất kỳ |
### Để chạy (runtime dependencies)
| Service | Mô tả | Cổng mặc định |
|---|---|---|
| **SQL Server** | 3 database: App, Layout, Script | 1433 |
| **MinIO** | Object storage (ảnh robot model, layout, config) | 9000 |
| **MQTT Broker** | Eclipse Mosquitto hoặc tương đương | 1883 |
---
## Cấu trúc project
```
srcs/RobotNet10/
├── FleetManager/
│ ├── RobotNet10.FleetManager/ # Main web app (backend + Blazor Server)
│ │ ├── Components/ # Razor components & pages
│ │ ├── Controllers/ # REST API controllers
│ │ ├── Data/ # EF Core DbContext & Migrations
│ │ ├── Events/ # VDA 5050 event bus
│ │ ├── Hubs/ # SignalR hub
│ │ ├── Services/
│ │ │ ├── ConfigManager/ # MQTT/Traffic config
│ │ │ ├── OpenACS/ # ACS traffic integration
│ │ │ ├── RobotConnections/ # VDA 5050 MQTT connections
│ │ │ ├── RobotManager/ # VDA 5050 robot management
│ │ │ ├── Script/ # Script engine integration
│ │ │ └── TrafficControl/ # Route planning & conflict resolution
│ │ ├── appsettings.json
│ │ ├── nlog.config
│ │ └── Program.cs
│ │
│ ├── RobotNet10.FleetManager.Client/ # Blazor WASM (frontend UI)
│ │ ├── Pages/ # 15 trang UI
│ │ └── Services/ # API & SignalR client services
│ │
│ ├── RobotNet10.FleetManager.Shared/ # DTOs, Models, Enums dùng chung
│ ├── RobotNet10.FleetManager.Script/ # Script engine cho FleetManager
│ └── RobotNet10.FleetManager.Script.Shared/
├── Commons/ # Các thư viện dùng chung
│ ├── RobotNet10.MapManager/ # Quản lý bản đồ + EF migrations
│ ├── RobotNet10.ScriptEngine/ # Script engine core
│ ├── RobotNet10.MqttConnection/ # MQTT wrapper
│ └── ...
├── Shared/
│ └── RobotNet.VDA5050/ # VDA 5050 standard models
├── Dockerfile.FleetManager # Docker build file
└── .dockerignore
```
---
## Cấu hình
Tất cả cấu hình nằm trong `RobotNet10.FleetManager/appsettings.json`.
### Connection Strings (bắt buộc)
```json
{
"ConnectionStrings": {
"DefaultConnection": "Server=<SQL_HOST>;Database=RobotNet10.FleetManager;User Id=sa;Password=<PASSWORD>;TrustServerCertificate=True;MultipleActiveResultSets=true",
"MapEditorConnection": "Server=<SQL_HOST>;Database=RobotNet10.Layout;User Id=sa;Password=<PASSWORD>;TrustServerCertificate=True;MultipleActiveResultSets=true",
"ScriptEngineConnection":"Server=<SQL_HOST>;Database=RobotNet10.Script;User Id=sa;Password=<PASSWORD>;TrustServerCertificate=True;MultipleActiveResultSets=true"
}
}
```
> **Lưu ý:** EF Core sẽ tự tạo database và chạy migration khi khởi động lần đầu.
### MinIO (object storage)
```json
{
"StorageConfig": {
"UsingLocal": false,
"Bucket": "fleet-custom-configs",
"MinioConfig": {
"Endpoint": "<MINIO_HOST>:9000",
"User": "minio",
"Password": "<MINIO_PASSWORD>",
"EnableSSL": false
}
},
"LayoutImage": {
"UsingLocal": false,
"Bucket": "fleet-layout-images",
"MinioConfig": { "Endpoint": "<MINIO_HOST>:9000", "User": "minio", "Password": "<MINIO_PASSWORD>" }
},
"RobotModelImage": {
"UsingLocal": false,
"Bucket": "robotmodel-images",
"MinioConfig": { "Endpoint": "<MINIO_HOST>:9000", "User": "minio", "Password": "<MINIO_PASSWORD>" }
}
}
```
> Đặt `"UsingLocal": true` để dùng thư mục local thay vì MinIO (phù hợp môi trường dev).
### ScriptEngine DLL folder
```json
{
"ScriptEngine": {
"RuntimeDllFolder": "bin/dlls"
}
}
```
---
## Build & Chạy local
### 1. Clone và di chuyển vào thư mục solution
```bash
git clone <repo-url>
cd srcs/RobotNet10
```
### 2. Restore packages
```bash
dotnet restore FleetManager/RobotNet10.FleetManager/RobotNet10.FleetManager.csproj
```
### 3. Cấu hình connection strings
Sửa `FleetManager/RobotNet10.FleetManager/appsettings.json` hoặc dùng User Secrets:
```bash
cd FleetManager/RobotNet10.FleetManager
dotnet user-secrets set "ConnectionStrings:DefaultConnection" \
"Server=localhost;Database=RobotNet10.FleetManager;User Id=sa;Password=YourPassword;TrustServerCertificate=True"
dotnet user-secrets set "ConnectionStrings:MapEditorConnection" \
"Server=localhost;Database=RobotNet10.Layout;User Id=sa;Password=YourPassword;TrustServerCertificate=True"
dotnet user-secrets set "ConnectionStrings:ScriptEngineConnection" \
"Server=localhost;Database=RobotNet10.Script;User Id=sa;Password=YourPassword;TrustServerCertificate=True"
```
### 4. Chạy ứng dụng
```bash
# Từ thư mục srcs/RobotNet10/
dotnet run --project FleetManager/RobotNet10.FleetManager/RobotNet10.FleetManager.csproj
```
Ứng dụng sẽ tự động:
- Tạo database và chạy EF Core migrations
- Seed dữ liệu ban đầu (user admin mặc định)
- Khởi động web server tại `https://localhost:5001` / `http://localhost:5000`
### 5. Build Release
```bash
dotnet publish FleetManager/RobotNet10.FleetManager/RobotNet10.FleetManager.csproj \
-c Release \
-o ./publish
```
---
## Docker
### Yêu cầu
- Docker Desktop hoặc Docker Engine với Linux containers
- Build context phải là thư mục `srcs/RobotNet10/`
### Chuẩn bị certificate (HTTPS)
Đặt file certificate `.pfx` vào thư mục `certs/` trước khi chạy container:
```bash
# Tùy chọn 1 — dùng dotnet dev-certs (self-signed, phù hợp dev/test)
dotnet dev-certs https -ep certs/fleet-manager.pfx -p YourCertPassword
# Tùy chọn 2 — dùng openssl (tự ký)
openssl req -x509 -newkey rsa:4096 -keyout certs/key.pem -out certs/cert.pem -days 365 -nodes \
-subj "/CN=fleet-manager"
openssl pkcs12 -export -out certs/fleet-manager.pfx \
-inkey certs/key.pem -in certs/cert.pem -passout pass:YourCertPassword
# Tùy chọn 3 — dùng certificate thật từ CA (Let's Encrypt, v.v.)
# Chuyển đổi sang .pfx nếu đang ở dạng .pem:
openssl pkcs12 -export -out certs/fleet-manager.pfx \
-inkey certs/privkey.pem -in certs/fullchain.pem -passout pass:YourCertPassword
```
> `certs/*.pfx` đã được loại khỏi `.dockerignore` — certificate **không bao giờ** được copy vào image, chỉ được mount tại runtime.
### Build image
```bash
# Chạy từ srcs/RobotNet10/
docker build -f FleetManager/Dockerfile -t robotnet10-fleet-manager:latest .
```
Quá trình build gồm 2 stage:
1. **Build stage** (mcr.microsoft.com/dotnet/sdk:10.0): Restore + Publish Release
2. **Runtime stage** (mcr.microsoft.com/dotnet/aspnet:10.0): Chỉ chứa output đã publish
Kích thước image cuối: **~211 MB** (content size) — Ports: HTTP `8080`, HTTPS `8081`
### Chạy container
```bash
docker run -d \
-p 8080:8080 -p 8081:8081 \
-v ./certs:/app/certs:ro \
-e ASPNETCORE_Kestrel__Certificates__Default__Path=/app/certs/fleet-manager.pfx \
-e ASPNETCORE_Kestrel__Certificates__Default__Password="YourCertPassword" \
-e ConnectionStrings__DefaultConnection="Server=<SQL_HOST>;Database=RobotNet10.FleetManager;User Id=sa;Password=<PASSWORD>;TrustServerCertificate=True;MultipleActiveResultSets=true" \
-e ConnectionStrings__MapEditorConnection="Server=<SQL_HOST>;Database=RobotNet10.Layout;User Id=sa;Password=<PASSWORD>;TrustServerCertificate=True;MultipleActiveResultSets=true" \
-e ConnectionStrings__ScriptEngineConnection="Server=<SQL_HOST>;Database=RobotNet10.Script;User Id=sa;Password=<PASSWORD>;TrustServerCertificate=True;MultipleActiveResultSets=true" \
--name fleet-manager \
robotnet10-fleet-manager:latest
```
> **Chú ý:** Dùng `__` (hai dấu gạch dưới) thay cho `:` khi truyền environment variable trong Docker.
### Gắn volume cho logs
```bash
docker run -d \
-p 8080:8080 \
-v /host/path/logs:/app/logs \
-e ConnectionStrings__DefaultConnection="..." \
--name fleet-manager \
robotnet10-fleet-manager:latest
```
### Docker Compose (khuyến nghị)
File [docker-compose.yml](docker-compose.yml) quản lý **fleet-manager** và kết nối đến SQL Server, MinIO, MQTT Broker đã có sẵn bên ngoài.
```bash
# 1. Tạo file .env từ template (từ thư mục FleetManager/)
cp .env.example .env
# Điền SQL Server host, MinIO host và các thông tin kết nối vào .env
# 2. Chạy container
docker compose up -d
# 3. Xem trạng thái
docker compose ps
# 4. Xem log
docker compose logs -f fleet-manager
```
**Các biến cần thiết trong `.env`:**
| Biến | Mô tả |
|---|---|
| `DB_DEFAULT_CONNECTION` | Connection string SQL Server (App DB) |
| `DB_MAP_CONNECTION` | Connection string SQL Server (Layout DB) |
| `DB_SCRIPT_CONNECTION` | Connection string SQL Server (Script DB) |
| `MINIO_ENDPOINT` | Địa chỉ MinIO, ví dụ `192.168.1.100:9000` |
| `MINIO_PASSWORD` | Mật khẩu MinIO |
| `FLEET_PORT` | Port expose web app (mặc định `8080`) |
---
## Các services phụ thuộc
### SQL Server
Ứng dụng cần **3 database** riêng biệt (tự tạo khi khởi động):
| Database | Connection String key | Mục đích |
|---|---|---|
| `RobotNet10.FleetManager` | `DefaultConnection` | User identity, Robot, RobotModel |
| `RobotNet10.Layout` | `MapEditorConnection` | Bản đồ nhà máy (nodes, edges, stations) |
| `RobotNet10.Script` | `ScriptEngineConnection` | Script engine data |
### MinIO
Tạo 3 bucket sau trong MinIO console (`http://<host>:9001`) trước khi chạy ứng dụng:
| Bucket | Config key | Mục đích |
|---|---|---|
| `fleet-custom-configs` | `StorageConfig.Bucket` | Custom configuration files |
| `fleet-layout-images` | `LayoutImage.Bucket` | Ảnh nền bản đồ |
| `robotmodel-images` | `RobotModelImage.Bucket` | Ảnh robot model |
> **Dev mode:** Đặt `"UsingLocal": true` để bỏ qua MinIO, dùng thư mục local.
### MQTT Broker
FleetManager kết nối đến MQTT Broker theo cấu hình trong **UI** (trang Config Manager), không cần cấu hình trong `appsettings.json`. Broker phổ biến:
```bash
# Eclipse Mosquitto (Docker)
docker run -d -p 1883:1883 -p 9883:9883 eclipse-mosquitto
```
---
## Tài khoản mặc định
Khi ứng dụng khởi động lần đầu, seed data sẽ tạo tài khoản admin:
| Trường | Giá trị |
|---|---|
| **Username/Email** | `admin@robotnet.local` |
| **Password** | `Admin@123` |
| **Role** | Administrator |
> **Quan trọng:** Đổi mật khẩu ngay sau lần đăng nhập đầu tiên trong môi trường production.
---
## Logs
Log được ghi vào thư mục `logs/` theo cấu hình NLog (`nlog.config`):
- Format: JSON, mỗi ngày một file (`YYYY-MM-DD.log`)
- Giữ tối đa 90 ngày
- Đường dẫn: `<app_dir>/logs/`
```bash
# Xem log trong container
docker logs fleet-manager
docker exec fleet-manager tail -f /app/logs/$(date +%Y-%m-%d).log
```
---
## Các lệnh Docker hữu ích
```bash
# Xem danh sách images
docker images robotnet10-fleet-manager
# Xem logs container
docker logs -f fleet-manager
# Vào shell container
docker exec -it fleet-manager bash
# Dừng và xóa container
docker stop fleet-manager && docker rm fleet-manager
# Rebuild image (sau khi cập nhật code)
docker build -f FleetManager/Dockerfile -t robotnet10-fleet-manager:latest . --no-cache
# Export image để chuyển sang máy khác
docker save robotnet10-fleet-manager:latest | gzip > fleet-manager.tar.gz
# Load image từ file
docker load < fleet-manager.tar.gz
```
---
## Tài liệu chi tiết
- [Architecture Overview](../../../docs/fleetmanager/README.md)
- [Traffic Control](../../../docs/fleetmanager/TrafficControl.md)
- [Robot Connections](../../../docs/fleetmanager/RobotConnections.md)
- [Script Engine](../../../docs/fleetmanager/ScriptEngine.md)
- [Map Editor](../../../docs/fleetmanager/MapEditor.md)
- [Configuration](../../../docs/fleetmanager/FleetManagerConfig.md)