Initial commit

This commit is contained in:
2026-07-03 16:31:37 +07:00
commit 899c7c637d
1939 changed files with 641750 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
# Built-in APIs / API Tích hợp Sẵn
## 📋 Overview / Tổng quan
Các APIs có sẵn trong tất cả scripts mà không cần import hoặc khai báo.
## 📝 Logger API
```csharp
Logger.Info("Informational message");
Logger.Warning("Warning message");
Logger.Error("Error message");
```
## 🎯 Mission Management APIs
```csharp
// Create mission
Guid missionId = CreateMission("DeliverPackage",
fromLocation: "A1",
toLocation: "B2");
// Cancel mission
CancelMission(missionId);
```
## ⚙️ Task Control APIs
```csharp
EnableTask("MonitoringTask"); // Resume task - chuyển từ Paused → Running
DisableTask("MaintenanceTask"); // Pause task - chuyển từ Running → Paused
```
**Lưu ý**:
- `EnableTask/DisableTask` là API level (public interface cho scripts)
- Tương đương với `Pause/Resume` ở state machine level
- Xem chi tiết về Task state machine trong [StateMachine_Design.md](StateMachine_Design.md)
## 🔌 IO Connection APIs / API Kết nối IO
ScriptEngine hỗ trợ các giao tiếp công nghiệp phổ biến để tích hợp với thiết bị bên ngoài:
### HTTP Connection
```csharp
var httpConn = RobotNet.CreateHttpConnection("http://localhost:8080", timeoutSeconds: 30);
await httpConn.ConnectAsync();
var response = await httpConn.GetAsync("/api/data");
await httpConn.PostAsync("/api/update", jsonData, "application/json");
await httpConn.DisconnectAsync();
```
### ModbusTCP Connection
```csharp
var modbusConn = RobotNet.CreateModbusTcpConnection("192.168.1.100", port: 502, slaveId: 1);
await modbusConn.ConnectAsync();
var registers = await modbusConn.ReadHoldingRegistersAsync(0, 10);
await modbusConn.WriteSingleRegisterAsync(0, 100);
await modbusConn.DisconnectAsync();
```
### OPC UA Connection
```csharp
var opcConn = RobotNet.CreateOpcUaConnection("opc.tcp://localhost:4840");
await opcConn.ConnectAsync();
// Hoặc với authentication
await opcConn.ConnectAsync("username", "password");
var value = await opcConn.ReadNodeAsync("ns=2;s=MyVariable");
await opcConn.WriteNodeAsync("ns=2;s=MyVariable", 123);
var nodes = await opcConn.BrowseNodesAsync();
await opcConn.DisconnectAsync();
```
### ProfiNet Connection
```csharp
var profinetConn = RobotNet.CreateProfiNetConnection("192.168.1.100", slot: 1, subslot: 1);
await profinetConn.ConnectAsync();
var data = await profinetConn.ReadAsync(index: 0, length: 100);
await profinetConn.WriteAsync(index: 0, data: byteArray);
await profinetConn.DisconnectAsync();
```
**Lưu ý**: ProfiNet implementation hiện tại là skeleton, cần thêm thư viện hoặc implement protocol stack đầy đủ.
### CC-Link IE Connection
```csharp
var cclinkConn = RobotNet.CreateCcLinkIeConnection("192.168.1.100", stationNumber: 1);
await cclinkConn.ConnectAsync();
var data = await cclinkConn.ReadAsync(address: 0, length: 10);
await cclinkConn.WriteAsync(address: 0, data: ushortArray);
await cclinkConn.DisconnectAsync();
```
**Lưu ý**: CC-Link IE implementation hiện tại là skeleton, cần thêm thư viện hoặc implement protocol stack đầy đủ.
### Connection Lifecycle
Tất cả connections đều implement `IDisposable` và nên được dispose sau khi sử dụng:
```csharp
using var httpConn = RobotNet.CreateHttpConnection("http://localhost:8080");
await httpConn.ConnectAsync();
// ... use connection ...
// Automatically disposed when exiting using block
```
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [Tasks](Tasks.md) - Sử dụng Task control APIs
- [Missions](Missions.md) - Sử dụng Mission management APIs
- [Extension APIs](ExtensionAPIs.md) - App-specific APIs
---
**Last Updated**: 2025-11-13

View File

@@ -0,0 +1,49 @@
# Script Compilation Process / Quá trình Biên dịch
## 📋 Overview / Tổng quan
ScriptEngine compile C# scripts sử dụng Roslyn để extract metadata và generate executable runners.
## 🔄 Compilation Flow / Luồng Biên dịch
```mermaid
flowchart TD
Start([User clicks Build]) --> Collect[Step 1: Collect Files<br/>Load all .cs files]
Collect --> Merge[Step 2: Merge Code<br/>Combine into DummyClass]
Merge --> Compile[Step 3: Compile<br/>Roslyn CSharpCompilation]
Compile --> Analyze[Step 4: Analyze<br/>Extract Variables, Tasks, Missions]
Analyze --> Generate[Step 5: Generate Runners<br/>Create TaskRunner, MissionRunner]
Generate --> Ready[State: Ready<br/>Can start execution]
Compile -->|Errors| BuildError[State: BuildError<br/>Show diagnostics]
style Start fill:#e6ffe6
style Ready fill:#e6ffe6
style BuildError fill:#ffe6e6
```
## 📝 Chi tiết từng bước / Step Details
1. **Collect Files**: Load tất cả `.cs` files từ filesystem
2. **Merge Code**: Combine vào một `DummyClass` để phân tích
3. **Compile**: Sử dụng Roslyn để compile và lấy SemanticModel
4. **Analyze**: Extract metadata (variables với `[Variable]`, methods với `[Task]`/`[Mission]`)
5. **Generate Runners**: Tạo executable classes cho mỗi task/mission
## 🔍 IntelliSense Support / Hỗ trợ IntelliSense
- Sử dụng AdhocWorkspace trên WebAssembly
- IntelliSense, Hover information, Diagnostics
- Real-time code analysis
- No server round-trip for IntelliSense
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [State Machine Design](StateMachine_Design.md) - Kiến trúc State Machine chi tiết
- [Script Files](ScriptFiles.md) - Quản lý file script
---
**Last Updated**: 2025-11-13

View File

@@ -0,0 +1,74 @@
# Data Persistence / Lưu trữ Dữ liệu
## 📋 Overview / Tổng quan
ScriptEngine lưu trữ Mission instances và logs vào database để track execution history.
## 💾 Mission Instances
Missions được persist vào database:
```mermaid
erDiagram
MissionInstances {
Guid Id PK
string MissionName
string Parameters
int Status
int CurrentScore
int TotalScore
DateTime StartedAt
DateTime CompletedAt
string ErrorMessage
}
MissionInstances ||--o{ MissionLogs : has
MissionLogs {
Guid Id PK
Guid MissionInstanceId FK
DateTime Timestamp
int Score
string Message
}
```
## 📊 Status Enum
- `0`: Running
- `1`: Completed
- `2`: Cancelled
- `3`: Failed
## 💾 Backup & Restore / Sao lưu & Khôi phục
### Backup
**Format**: ZIP file chứa tất cả script files với folder structure
**Process**:
1. User clicks "Backup"
2. Server collect all files from script directory
3. Create ZIP with preserved structure
4. Store: `ScriptBackup_2025-11-13_143022.zip`
5. Optionally download to browser
### Restore
**Process**:
1. User select backup (from list or upload ZIP)
2. Engine transitions to Idle
3. Extract ZIP
4. Validate files
5. Replace current scripts if valid
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [Missions](Missions.md) - Mission execution và persistence
- [Script Files](ScriptFiles.md) - File system storage
---
**Last Updated**: 2025-11-13

View File

@@ -0,0 +1,117 @@
# Extension APIs / API Mở rộng
## 📋 Overview / Tổng quan
Apps implement `IScriptResource` interface để expose custom APIs cho scripts.
## 🔌 IScriptResource Interface
```mermaid
classDiagram
class IScriptResource {
<<interface>>
+Type AppGlobalType
+GetTaskGlobals() IDictionary
+GetMissionGlobals(id, ct) IDictionary
+UsingNamespaces ImmutableArray~string~
+Modules ImmutableArray~string~
}
class RobotScriptResource {
+AppGlobalType: typeof(RobotGlobals)
+GetTaskGlobals()
+GetMissionGlobals()
}
class FleetScriptResource {
+AppGlobalType: typeof(FleetGlobals)
+GetTaskGlobals()
+GetMissionGlobals()
}
class RobotGlobals {
+MoveTo(x, y) Task
+GetBatteryLevel() double
+IsMoving() bool
}
class FleetGlobals {
+GetAvailableRobots() List~Robot~
+SendOrder(serial, order) Task
+GetRobotState(serial) RobotState
}
IScriptResource <|-- RobotScriptResource
IScriptResource <|-- FleetScriptResource
RobotScriptResource ..> RobotGlobals: exposes
FleetScriptResource ..> FleetGlobals: exposes
```
## 🤖 RobotApp Example
**Define AppGlobalType**:
```csharp
public class RobotScriptGlobals
{
public Task MoveTo(double x, double y) { }
public double GetBatteryLevel() { }
public bool IsMoving() { }
}
```
**Use in Script**:
```csharp
[Task(Interval = 5000)]
public async Task CheckBattery()
{
var level = Robot.GetBatteryLevel();
Logger.Info($"Battery: {level}%");
if (level < 20.0)
{
await Robot.MoveTo(0, 0); // Home position
}
}
```
## 🏭 FleetManager Example
**Define AppGlobalType**:
```csharp
public class FleetScriptGlobals
{
public List<Robot> GetAvailableRobots() { }
public Task SendOrder(string robotSerial, Order order) { }
public RobotState GetRobotState(string robotSerial) { }
public Task MoveToNode(string robotSerial, string nodeId) { }
public Task MoveToStation(string robotSerial, string stationId) { }
}
```
**Use in Script**:
```csharp
[Task(Interval = 10000)]
public void MonitorFleet()
{
var robots = Fleet.GetAvailableRobots();
foreach (var robot in robots)
{
var state = Fleet.GetRobotState(robot.SerialNumber);
if (state?.BatteryCharge < 20.0)
{
Logger.Warning($"Robot {robot.SerialNumber} low battery");
}
}
}
```
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [FleetManager ScriptEngine Module](../fleetmanager/ScriptEngine.md) - FleetManager implementation
- [RobotApp Documentation](../robotapp/README.md) - RobotApp implementation
---
**Last Updated**: 2025-11-13

View File

@@ -0,0 +1,659 @@
# InstanceMissionManager Test Cases
## Tổng quan
InstanceMissionManager là component để quản lý và hiển thị danh sách các instance missions (mission instances đã được tạo và chạy). Component sử dụng MudTable với server-side pagination và search.
Tài liệu này mô tả các test case cần thiết để đảm bảo component hoạt động đúng.
---
## 1. Test Cases - Khởi tạo và Loading
### TC-001: Hiển thị table khi khởi tạo
**Mô tả:** Kiểm tra table hiển thị đúng khi component được load.
**Các bước:**
1. Navigate đến InstanceMissionManager page
2. Quan sát UI
**Kết quả mong đợi:**
- MudTable hiển thị với các columns: Mission Name, State, Score, Created At, Stopped At, Actions
- Loading indicator hiển thị khi đang load data
- Table height được tính toán đúng dựa trên container height
- Toolbar với search box và refresh button hiển thị
---
### TC-002: Khởi tạo SignalR connection
**Mô tả:** Kiểm tra InstanceMissionHub connection được khởi tạo đúng.
**Các bước:**
1. Navigate đến InstanceMissionManager page
2. Mở browser DevTools > Network tab
3. Quan sát SignalR connections
**Kết quả mong đợi:**
- InstanceMissionHub connection được khởi tạo
- Connection thành công (status 101 Switching Protocols)
- Không có lỗi connection trong console
---
### TC-003: Tính toán table height động
**Mô tả:** Kiểm tra table height được tính toán đúng dựa trên container.
**Các bước:**
1. Navigate đến InstanceMissionManager page
2. Resize browser window
3. Quan sát table height
**Kết quả mong đợi:**
- Table height được tính toán dựa trên container height
- Table height = container height - toolbar height - padding
- Table height cập nhật khi resize window
- Table không bị overflow
---
### TC-004: Load data ban đầu
**Mô tả:** Kiểm tra data được load đúng khi component khởi tạo.
**Các bước:**
1. Navigate đến InstanceMissionManager page
2. Đợi data load
3. Quan sát table
**Kết quả mong đợi:**
- LoadData được gọi với page 1, page size mặc định
- Data được hiển thị trong table
- Total items được hiển thị đúng trong pagination
- Loading indicator biến mất sau khi load xong
---
## 2. Test Cases - Table Display
### TC-005: Hiển thị mission name
**Mô tả:** Kiểm tra mission name được hiển thị đúng.
**Các bước:**
1. Load table với data
2. Quan sát Mission Name column
**Kết quả mong đợi:**
- Mission name hiển thị đúng cho mỗi row
- Text không bị truncate không mong muốn
- Format đúng
---
### TC-006: Hiển thị state với color coding
**Mô tả:** Kiểm tra state được hiển thị với đúng màu sắc.
**Các bước:**
1. Load table với missions ở các states khác nhau
2. Quan sát State column
**Kết quả mong đợi:**
- Running: Color.Success (green)
- Paused: Color.Warning (yellow)
- Pausing: Color.Warning (yellow)
- Resuming: Color.Info (blue)
- Completed: Color.Success (green)
- Canceled: Color.Default (gray)
- Error: Color.Error (red)
- Idle: Color.Default (gray)
- MudChip hiển thị đúng state name và color
---
### TC-007: Hiển thị score percentage
**Mô tả:** Kiểm tra score được hiển thị dưới dạng percentage.
**Các bước:**
1. Load table với missions có score
2. Quan sát Score column
**Kết quả mong đợi:**
- Score hiển thị dưới dạng: `(score / totalScore) * 100` với 2 decimal places
- Format: "XX.XX%"
- Hiển thị "0.00%" nếu score = 0
- Hiển thị "100.00%" nếu score = totalScore
---
### TC-008: Hiển thị Created At
**Mô tả:** Kiểm tra Created At được hiển thị đúng format.
**Các bước:**
1. Load table với missions
2. Quan sát Created At column
**Kết quả mong đợi:**
- Created At hiển thị format: "yyyy-MM-dd HH:mm:ss"
- Timezone đúng (UTC hoặc local time)
- Hiển thị cho tất cả missions
---
### TC-009: Hiển thị Stopped At
**Mô tả:** Kiểm tra Stopped At chỉ hiển thị khi mission đã stopped.
**Các bước:**
1. Load table với missions ở các states khác nhau
2. Quan sát Stopped At column
**Kết quả mong đợi:**
- Stopped At hiển thị format: "yyyy-MM-dd HH:mm:ss" cho missions ở states: Canceled, Completed, Error
- Stopped At hiển thị "--" cho missions ở states khác (Running, Paused, etc.)
- Format đúng
---
### TC-010: Hiển thị actions buttons theo state
**Mô tả:** Kiểm tra action buttons hiển thị đúng theo mission state.
**Các bước:**
1. Load table với missions ở các states khác nhau
2. Quan sát Actions column
**Kết quả mong đợi:**
- View Log button: Hiển thị cho tất cả missions
- Cancel button: Chỉ hiển thị cho Running, Paused, Pausing states
- Pause button: Chỉ hiển thị cho Running state
- Resume button: Chỉ hiển thị cho Paused state
- Buttons không hiển thị khi không applicable
---
## 3. Test Cases - Pagination
### TC-011: Pagination hoạt động đúng
**Mô tả:** Kiểm tra pagination hoạt động đúng với server-side data.
**Các bước:**
1. Load table với nhiều missions (> page size)
2. Click vào page 2
3. Quan sát data
**Kết quả mong đợi:**
- LoadData được gọi với page number đúng (MudTable uses 0-based, API uses 1-based)
- Data được load đúng cho page được chọn
- Total items được hiển thị đúng trong pagination
- Page number được highlight đúng
---
### TC-012: Change page size
**Mô tả:** Kiểm tra thay đổi page size hoạt động đúng.
**Các bước:**
1. Load table
2. Thay đổi page size (10, 25, 50, 100)
3. Quan sát data
**Kết quả mong đợi:**
- LoadData được gọi với page size mới
- Data được load đúng số lượng items theo page size
- Pagination cập nhật đúng
- Table height vẫn đúng
---
### TC-013: Navigate giữa các pages
**Mô tả:** Kiểm tra navigate giữa các pages hoạt động đúng.
**Các bước:**
1. Load table với nhiều pages
2. Navigate: Page 1 → Page 2 → Page 3 → Page 1
3. Quan sát data
**Kết quả mong đợi:**
- Data được load đúng cho mỗi page
- Loading indicator hiển thị khi đang load
- Không có duplicate data
- Page number được highlight đúng
---
## 4. Test Cases - Search
### TC-014: Search bằng text input
**Mô tả:** Kiểm tra search hoạt động khi nhập text.
**Các bước:**
1. Load table
2. Nhập text vào search box
3. Đợi debounce (1 second)
4. Quan sát data
**Kết quả mong đợi:**
- Search được trigger sau 1 second debounce
- LoadData được gọi với TxtSearch parameter đúng
- Table reload với kết quả search
- Total items cập nhật theo kết quả search
---
### TC-015: Search bằng Enter key
**Mô tả:** Kiểm tra search hoạt động khi nhấn Enter.
**Các bước:**
1. Load table
2. Nhập text vào search box
3. Nhấn Enter
4. Quan sát data
**Kết quả mong đợi:**
- Search được trigger ngay lập tức (không đợi debounce)
- LoadData được gọi với TxtSearch parameter đúng
- Table reload với kết quả search
---
### TC-016: Search bằng search icon click
**Mô tả:** Kiểm tra search hoạt động khi click vào search icon.
**Các bước:**
1. Load table
2. Nhập text vào search box
3. Click vào search icon (adornment)
4. Quan sát data
**Kết quả mong đợi:**
- Search được trigger ngay lập tức
- LoadData được gọi với TxtSearch parameter đúng
- Table reload với kết quả search
---
### TC-017: Search với empty text
**Mô tả:** Kiểm tra search với empty text trả về tất cả records.
**Các bước:**
1. Search với một text
2. Clear search text (để trống)
3. Đợi debounce hoặc nhấn Enter
4. Quan sát data
**Kết quả mong đợi:**
- LoadData được gọi với TxtSearch = ""
- Table reload với tất cả records
- Total items trở về tổng số records
---
### TC-018: Search với special characters
**Mô tả:** Kiểm tra search hoạt động với special characters.
**Các bước:**
1. Search với text chứa special characters (%, _, @, etc.)
2. Quan sát data
**Kết quả mong đợi:**
- Search không crash
- Kết quả search đúng (hoặc empty nếu không match)
- Special characters được handle đúng
---
## 5. Test Cases - Actions
### TC-019: View Log action
**Mô tả:** Kiểm tra View Log action mở dialog với đúng log content.
**Các bước:**
1. Click vào View Log button của một mission
2. Quan sát dialog
**Kết quả mong đợi:**
- MissionLogDialog được mở
- Dialog title: "Mission Log: {missionName}"
- Dialog hiển thị đúng log content
- Dialog có thể đóng bằng Close button
- Dialog size: MaxWidth.Large, FullWidth = true
---
### TC-020: Cancel Mission action - Dialog
**Mô tả:** Kiểm tra Cancel Mission action mở dialog xác nhận.
**Các bước:**
1. Click vào Cancel button của một Running mission
2. Quan sát dialog
**Kết quả mong đợi:**
- CancelMissionDialog được mở
- Dialog title: "Cancel Mission"
- Dialog có input field để nhập reason
- Dialog có Cancel và Confirm buttons
- Dialog size: MaxWidth.Small, FullWidth = true
---
### TC-021: Cancel Mission action - Success
**Mô tả:** Kiểm tra Cancel Mission action thành công.
**Các bước:**
1. Click vào Cancel button của một Running mission
2. Nhập reason (hoặc để trống)
3. Click Confirm
4. Quan sát UI
**Kết quả mong đợi:**
- CancelMissionAsync được gọi với mission ID và reason
- Reason format: "Canceled by {userName}: {userReason}" hoặc "Canceled by {userName}" nếu reason trống
- Success snackbar hiển thị
- Table reload để cập nhật state
- Mission state chuyển sang Canceled
---
### TC-022: Cancel Mission action - Cancel dialog
**Mô tả:** Kiểm tra Cancel Mission action khi cancel dialog.
**Các bước:**
1. Click vào Cancel button của một Running mission
2. Click Cancel trong dialog
3. Quan sát UI
**Kết quả mong đợi:**
- Dialog đóng
- Mission không bị cancel
- Table không reload
- Không có snackbar
---
### TC-023: Cancel Mission action - Error handling
**Mô tả:** Kiểm tra error handling khi Cancel Mission fail.
**Các bước:**
1. Simulate error khi cancel mission (disconnect network hoặc server error)
2. Click Cancel button và confirm
3. Quan sát UI
**Kết quả mong đợi:**
- Error được catch
- Error snackbar hiển thị với message
- Table không reload
- Mission state không thay đổi
---
### TC-024: Pause Mission action
**Mô tả:** Kiểm tra Pause Mission action.
**Các bước:**
1. Click vào Pause button của một Running mission
2. Quan sát UI
**Kết quả mong đợi:**
- PauseMissionAsync được gọi với mission ID
- Success snackbar hiển thị nếu thành công
- Error snackbar hiển thị nếu thất bại
- Table có thể reload để cập nhật state (nếu có auto-refresh)
---
### TC-025: Resume Mission action
**Mô tả:** Kiểm tra Resume Mission action.
**Các bước:**
1. Click vào Resume button của một Paused mission
2. Quan sát UI
**Kết quả mong đợi:**
- ResumeMissionAsync được gọi với mission ID
- Success snackbar hiển thị nếu thành công
- Error snackbar hiển thị nếu thất bại
- Table có thể reload để cập nhật state (nếu có auto-refresh)
---
### TC-026: Refresh button
**Mô tả:** Kiểm tra Refresh button reload table data.
**Các bước:**
1. Load table
2. Thực hiện một action (cancel mission, etc.)
3. Click Refresh button
4. Quan sát data
**Kết quả mong đợi:**
- Table reload với data mới nhất
- Current page và search text được giữ nguyên
- Loading indicator hiển thị khi đang load
---
## 6. Test Cases - Error Handling
### TC-027: Error khi load data fail
**Mô tả:** Kiểm tra error handling khi load data thất bại.
**Các bước:**
1. Simulate error (disconnect network hoặc server error)
2. Navigate đến InstanceMissionManager page
3. Quan sát UI
**Kết quả mong đợi:**
- Exception được catch
- Error snackbar hiển thị: "Error loading missions: {errorMessage}"
- Table hiển thị empty state (No matching records found)
- Loading indicator biến mất
- Không crash ứng dụng
---
### TC-028: Error khi SignalR connection fail
**Mô tả:** Kiểm tra error handling khi SignalR connection thất bại.
**Các bước:**
1. Block SignalR port hoặc tắt server
2. Navigate đến InstanceMissionManager page
3. Quan sát UI
**Kết quả mong đợi:**
- Connection error được handle
- Table vẫn có thể load data (nếu server-side API vẫn hoạt động)
- Không crash ứng dụng
- Error message hiển thị nếu cần
---
## 7. Test Cases - Performance
### TC-029: Performance khi load nhiều records
**Mô tả:** Kiểm tra performance khi có nhiều missions.
**Các bước:**
1. Tạo 1000+ missions
2. Load table
3. Navigate giữa các pages
4. Quan sát performance
**Kết quả mong đợi:**
- Table load trong thời gian hợp lý (< 2 giây cho mỗi page)
- Pagination hoạt động mượt mà
- UI không bị freeze
- Memory usage hợp lý
---
### TC-030: Performance khi search
**Mô tả:** Kiểm tra performance khi search với nhiều records.
**Các bước:**
1. Load table với 1000+ missions
2. Search với text
3. Quan sát performance
**Kết quả mong đợi:**
- Search hoàn tất trong thời gian hợp lý (< 2 giây)
- Debounce hoạt động đúng (không search mỗi keystroke)
- UI responsive
- Không có lag
---
## 8. Test Cases - Edge Cases
### TC-031: Empty state - No missions
**Mô tả:** Kiểm tra hiển thị khi không có missions.
**Các bước:**
1. Load table khi không có missions
2. Quan sát UI
**Kết quả mong đợi:**
- Table hiển thị "No matching records found"
- Pagination hiển thị 0 items
- Search box vẫn hoạt động
- Refresh button vẫn hoạt động
---
### TC-032: Empty state - No search results
**Mô tả:** Kiểm tra hiển thị khi search không có kết quả.
**Các bước:**
1. Load table với missions
2. Search với text không match
3. Quan sát UI
**Kết quả mong đợi:**
- Table hiển thị "No matching records found"
- Pagination hiển thị 0 items
- Clear search trả về tất cả records
---
### TC-033: Table height với toolbar height khác nhau
**Mô tả:** Kiểm tra table height tính toán đúng với toolbar height khác nhau.
**Các bước:**
1. Resize browser window
2. Quan sát table height
3. Kiểm tra toolbar height
**Kết quả mong đợi:**
- Table height = container height - max(toolbar height, 64) - padding
- Table không bị overflow
- Table scroll hoạt động đúng
---
### TC-034: Dispose và cleanup
**Mô tả:** Kiểm tra cleanup đúng khi component dispose.
**Các bước:**
1. Navigate đến InstanceMissionManager page
2. Navigate away
3. Quan sát Network tab và console
**Kết quả mong đợi:**
- InstanceMissionHub connection được stop
- Không có memory leaks
- Không có lỗi trong console
---
## 9. Test Cases - Integration
### TC-035: Tích hợp với Authentication
**Mô tả:** Kiểm tra tích hợp với authentication để lấy user name.
**Các bước:**
1. Login với một user
2. Cancel một mission
3. Kiểm tra reason trong log
**Kết quả mong đợi:**
- User name được lấy từ AuthenticationStateProvider
- Reason format: "Canceled by {userName}: {reason}"
- User name đúng với user đã login
---
### TC-036: Tích hợp với Snackbar
**Mô tả:** Kiểm tra snackbar hiển thị đúng cho các actions.
**Các bước:**
1. Thực hiện các actions (cancel, pause, resume)
2. Quan sát snackbar
**Kết quả mong đợi:**
- Success snackbar hiển thị khi action thành công
- Error snackbar hiển thị khi action thất bại
- Message đúng và rõ ràng
- Snackbar tự động dismiss sau vài giây
---
## Checklist Test Execution
### Pre-conditions
- [ ] Ứng dụng đã được build thành công
- [ ] Server đang chạy
- [ ] Database có dữ liệu test (missions)
- [ ] Authentication đã được configure
### Test Environment
- [ ] Browser: Chrome/Firefox/Edge (latest version)
- [ ] Screen resolution: 1920x1080 hoặc tương đương
- [ ] Network: Stable connection
- [ ] User đã login
### Test Execution Notes
- Ghi chú các bug phát hiện trong quá trình test
- Ghi lại screenshots cho các test case failed
- Ghi lại performance metrics nếu có vấn đề
- Test với nhiều số lượng missions khác nhau
---
## Known Issues và Limitations
### Đã Fix
- ✅ Table height không được tính toán đúng khi toolbar height thay đổi
- ✅ Search không hoạt động với Enter key
- ✅ Cancel mission reason không include user name
### Cần theo dõi
- Performance khi có quá nhiều missions (>10000)
- Memory usage khi pagination với nhiều pages
- Auto-refresh khi mission state thay đổi (có thể cần thêm feature)
---
## Test Priority
### High Priority (P0)
- TC-001, TC-002, TC-004, TC-005, TC-006, TC-010, TC-011, TC-014, TC-019, TC-020, TC-021, TC-027
### Medium Priority (P1)
- TC-003, TC-007, TC-008, TC-009, TC-012, TC-013, TC-015, TC-016, TC-017, TC-022, TC-023, TC-024, TC-025, TC-026, TC-028
### Low Priority (P2)
- TC-018, TC-029, TC-030, TC-031, TC-032, TC-033, TC-034, TC-035, TC-036
---
## Test Results Template
```
Test Case ID: TC-XXX
Test Date: YYYY-MM-DD
Tester: [Name]
Status: Pass/Fail/Blocked
Notes: [Any additional notes]
Screenshots: [If applicable]
Browser: [Browser name and version]
Missions Count: [Number of missions in test data]
```
---
*Tài liệu này được tạo tự động và cần được cập nhật khi có thay đổi trong InstanceMissionManager component.*

View File

@@ -0,0 +1,97 @@
# Missions / Nhiệm vụ Dài hạn
## 📋 Overview / Tổng quan
Missions là long-running workflows với progress tracking, phù hợp cho các nhiệm vụ phức tạp có thể cancel và track progress.
**Lưu ý quan trọng**:
- `Mission` = method trong script với `[Mission]` attribute (không có state machine)
- `MissionInstance` = instance được tạo từ Mission method khi gọi `CreateMission()` (có state machine)
- Xem chi tiết về state machine trong [StateMachine_Design.md](StateMachine_Design.md)
## 🔧 Cách sử dụng / Usage
```csharp
[Mission(TotalScore = 10)]
public async IAsyncEnumerable<MissionStatus> PickAndPlace(
string pickLocation,
string placeLocation,
[EnumeratorCancellation] CancellationToken ct)
{
yield return new MissionStatus { Score = 1, Message = "Moving to pick" };
await MoveTo(pickLocation);
yield return new MissionStatus { Score = 3, Message = "Picking item" };
await PerformPick();
yield return new MissionStatus { Score = 5, Message = "Moving to place" };
await MoveTo(placeLocation);
yield return new MissionStatus { Score = 8, Message = "Placing item" };
await PerformPlace();
yield return new MissionStatus { Score = 10, Message = "Completed" };
}
```
## ⚙️ Đặc điểm / Features
- **IAsyncEnumerable<MissionStatus>**: Return type để track progress
- **CancellationToken support**: Có thể cancel mission
- **Progress tracking**: Score/TotalScore để track tiến độ
- **Per-instance MissionGlobals**: Isolated execution cho mỗi mission instance
- **Persist to database**: Mission history được lưu vào database
## 🎛️ Mission Attributes / Thuộc tính Mission
- `[Mission(TotalScore = number)]`: Định nghĩa total score cho progress tracking
## 📊 Mission Status / Trạng thái Mission
**ScriptMissionState Enum** (tương ứng với state machine trong [StateMachine_Design.md](StateMachine_Design.md)):
- `Idle` (0) - MissionInstance chưa được start
- `Running` (1) - MissionInstance đang thực thi
- `Canceling` (2) - MissionInstance đang được cancel
- `Pausing` (3) - MissionInstance đang được pause
- `Paused` (4) - MissionInstance đã bị pause
- `Resuming` (5) - MissionInstance đang được resume
- `Canceled` (6) - MissionInstance đã bị cancel
- `Completed` (7) - MissionInstance đã hoàn thành thành công
- `Error` (8) - MissionInstance gặp lỗi
**Lưu ý**:
- `Mission` là method trong script với `[Mission]` attribute (không có state machine)
- `MissionInstance` là instance được tạo từ Mission method khi gọi `CreateMission()` (có state machine)
- State machine quản lý state của **MissionInstance**, không phải Mission
- Terminal states (`Completed`, `Canceled`, `Error`) là final states - khi về các state này, MissionInstance sẽ:
1. Lưu trạng thái, log và score vào database
2. Dispose MissionInstance
## 🔄 Mission Management APIs / API Quản lý Mission
```csharp
// Create mission
Guid missionId = CreateMission("DeliverPackage",
fromLocation: "A1",
toLocation: "B2");
// Cancel mission
CancelMission(missionId);
```
## 💾 Data Persistence / Lưu trữ Dữ liệu
Missions được persist vào database với MissionInstances và MissionLogs tables.
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [Variables](Variables.md) - Missions có thể đọc/ghi variables
- [Tasks](Tasks.md) - Tasks có thể tạo/cancel missions
- [Data Persistence](DataPersistence.md) - Chi tiết về database storage
- [Built-in APIs](BuiltInAPIs.md) - Mission management APIs
---
**Last Updated**: 2025-11-13

208
docs/ScriptEngine/README.md Normal file
View File

@@ -0,0 +1,208 @@
# ScriptEngine Documentation / Tài liệu ScriptEngine
## 📋 Overview / Tổng quan
**ScriptEngine** là shared library cho phép viết và thực thi C# scripts trực tiếp trên web mà không cần rebuild ứng dụng. Module này được dùng bởi **RobotApp****FleetManager** để mở rộng chức năng linh hoạt.
### 🎯 Vấn đề Cần Giải quyết
**Thách thức**: Trong môi trường sản xuất thực tế:
- Mỗi robot có hành vi riêng (custom actions, sensor processing)
- Mỗi nhà máy có quy trình khác nhau (business logic)
- Cần tích hợp với thiết bị bên thứ 3 (conveyors, elevators, stations)
- Không thể rebuild/redeploy app mỗi lần thay đổi logic
**Giải pháp ScriptEngine**:
- ✅ Viết C# code trực tiếp trên web browser
- ✅ IntelliSense, diagnostics, refactoring (Monaco Editor + Roslyn)
- ✅ Multi-file support (organize code như C# project)
- ✅ Variables, Tasks (periodic), Missions (workflows)
- ✅ Extension APIs (mỗi app expose custom functions)
- ✅ Real-time updates qua SignalR
### 🎪 Use Cases / Trường hợp Sử dụng
**RobotApp**:
- Custom VDA 5050 actions (pick, drop, scan, charge)
- Robot-specific behaviors (sensor calibration, custom navigation)
- Hardware integration (custom actuators, sensors)
**FleetManager**:
- Mission planning algorithms (optimize routes, load balancing)
- External system integration (HTTP APIs, MQTT, OPC UA)
- Business logic (station management, elevator control, conveyor sync)
- Custom analytics and reporting
## 🏗️ Architecture / Kiến trúc
### System Overview
```mermaid
graph TB
subgraph Browser["🌐 Browser - Blazor WASM"]
Editor[Monaco Editor<br/>C# Code Editing<br/>Multi-file workspace]
Roslyn[Roslyn Analysis<br/>IntelliSense<br/>Diagnostics<br/>Hover info]
UI[UI Components<br/>Hierarchy Tree<br/>Tasks/Missions/Variables]
end
subgraph Server["🖥️ Server - .NET Runtime"]
Compiler[Script Compiler<br/>Merge files<br/>Analyze code<br/>Extract metadata]
SM[State Machine<br/>Idle → Building<br/>→ Ready → Running]
TaskMgr[Task Manager<br/>Timer-based execution<br/>1 TaskRunner per task]
MissionMgr[Mission Manager<br/>Workflow execution<br/>CancellationToken support<br/>Progress tracking]
VarMgr[Variable Manager<br/>ConcurrentDictionary<br/>Shared state]
ExtAPI[Extension APIs<br/>App-specific functions<br/>IScriptResource]
end
Editor -->|SignalR<br/>Save, Build| Compiler
Roslyn -.->|Analysis results| Editor
Compiler -->|Build trigger| SM
SM -->|Ready state| TaskMgr
SM -->|Ready state| MissionMgr
TaskMgr <-->|Read/Write| VarMgr
MissionMgr <-->|Read/Write| VarMgr
TaskMgr --> ExtAPI
MissionMgr --> ExtAPI
TaskMgr -.->|Status updates| UI
MissionMgr -.->|Progress updates| UI
VarMgr -.->|Value changes| UI
style Browser fill:#e6f3ff
style Server fill:#fff0e6
```
### State Machine / Máy Trạng thái
ScriptEngine sử dụng state machine để quản lý lifecycle của Engine, Tasks và MissionInstances.
📖 **[Xem chi tiết về State Machine Architecture →](StateMachine_Design.md)**
**Tóm tắt**:
- **Engine State Machine**: Quản lý trạng thái của ScriptEngine (Initializing → Idle → Building → Ready → Starting → Running → Stopping)
- **Task State Machine**: Quản lý trạng thái của mỗi Task (Idle → Running → Pausing → Paused → Resuming → Stopping → Stopped → Error)
- **MissionInstance State Machine**: Quản lý trạng thái của mỗi MissionInstance (Idle → Running → Pausing → Paused → Resuming → Canceling → Completed/Canceled/Error)
## 📚 Cấu trúc Tài liệu / Documentation Structure
Tài liệu ScriptEngine được tổ chức thành các module riêng biệt để dễ dàng tra cứu và bảo trì:
```
docs/ScriptEngine/
├── README.md # File này - Tổng quan ScriptEngine
├── StateMachine_Design.md # Kiến trúc State Machine (Task, Mission, Engine)
├── ScriptFiles.md # Quản lý File Script
├── Variables.md # Biến Toàn cục
├── Tasks.md # Nhiệm vụ Định kỳ
├── Missions.md # Nhiệm vụ Dài hạn
├── Compilation.md # Quá trình Biên dịch
├── ExtensionAPIs.md # API Mở rộng
├── BuiltInAPIs.md # API Tích hợp Sẵn
├── DataPersistence.md # Lưu trữ Dữ liệu & Backup/Restore
└── Security.md # Bảo mật & Giới hạn
```
## 📝 Core Concepts / Khái niệm Cốt lõi
### 1. [Script Files](ScriptFiles.md) - File Script
Scripts được tổ chức như C# project với multi-file support, file locking, và backup/restore.
📖 **[Xem chi tiết →](ScriptFiles.md)**
### 2. [Variables](Variables.md) - Biến Toàn cục
Shared state được chia sẻ giữa tất cả scripts với thread-safe storage.
📖 **[Xem chi tiết →](Variables.md)**
### 3. [Tasks](Tasks.md) - Nhiệm vụ Định kỳ
Periodic execution với timer, phù hợp cho monitoring và automation đơn giản.
📖 **[Xem chi tiết →](Tasks.md)**
### 4. [Missions](Missions.md) - Nhiệm vụ Dài hạn
Long-running workflows với progress tracking, cancellable, và persist to database.
📖 **[Xem chi tiết →](Missions.md)**
## 🔄 [Script Compilation Process](Compilation.md) - Quá trình Biên dịch
ScriptEngine compile C# scripts sử dụng Roslyn để extract metadata và generate executable runners.
📖 **[Xem chi tiết →](Compilation.md)**
## 🔌 [Extension APIs](ExtensionAPIs.md) - API Mở rộng
Apps implement `IScriptResource` interface để expose custom APIs cho scripts (RobotApp và FleetManager).
📖 **[Xem chi tiết →](ExtensionAPIs.md)**
## 📚 [Built-in APIs](BuiltInAPIs.md) - API Tích hợp Sẵn
Các APIs có sẵn trong tất cả scripts: Logger, Mission Management, Task Control.
📖 **[Xem chi tiết →](BuiltInAPIs.md)**
## 💾 [Data Persistence](DataPersistence.md) - Lưu trữ Dữ liệu
Mission instances và logs được lưu vào database. Backup và restore scripts với ZIP format.
📖 **[Xem chi tiết →](DataPersistence.md)**
## ⚠️ [Security & Limitations](Security.md) - Bảo mật & Giới hạn
MetadataReference restrictions và thread safety considerations.
📖 **[Xem chi tiết →](Security.md)**
## 🎯 Design Rationale / Lý do Thiết kế
### Tại sao C# Scripting?
| Lý do | Giải thích |
|-------|------------|
| **Familiar syntax** | Developers đã biết C# |
| **Type safety** | Strong typing giảm runtime errors |
| **IntelliSense** | Code completion, diagnostics |
| **Roslyn power** | Full language analysis |
| **Async/await** | Natural asynchronous programming |
### Tại sao Monaco Editor + Roslyn trên WASM?
| Lý do | Giải thích |
|-------|------------|
| **Client-side analysis** | No server round-trip for IntelliSense |
| **Fast feedback** | Instant diagnostics while typing |
| **VS Code experience** | Professional IDE in browser |
| **Offline capable** | Can work without constant server connection |
### Tại sao Tasks & Missions?
| Concept | Use Case |
|---------|----------|
| **Tasks** | Periodic monitoring, simple automation |
| **Missions** | Complex workflows, progress tracking, cancellable |
## 📖 Related Documents / Tài liệu Liên quan
- [Architecture Overview](../architecture/README.md) - System architecture
- [RobotApp Documentation](../robotapp/README.md) - RobotApp usage
- [FleetManager Documentation](../fleetmanager/README.md) - FleetManager usage
- [AI Collaboration Guide](../ai-guide/README.md) - For developers
---
**Status**: Design Document
**Last Updated**: 2025-11-13
**Version**: 1.1 (Modular documentation structure)

View File

@@ -0,0 +1,581 @@
# ScriptEditor Test Cases
## Tổng quan
ScriptEditor là component chính của Script Engine Editor, bao gồm:
- **Sidebar**: FileExplorer, VariableManager, TaskManager, MissionManager (có thể resize ngang)
- **Editor Area**: Monaco Editor để chỉnh sửa script files (có thể resize dọc)
- **Console Panel**: Hiển thị logs từ ScriptEngine (có thể resize dọc)
Tài liệu này mô tả các test case cần thiết để đảm bảo component hoạt động đúng.
---
## 1. Test Cases - Khởi tạo và Loading
### TC-001: Hiển thị loading overlay khi khởi tạo
**Mô tả:** Kiểm tra loading overlay hiển thị khi Workspace chưa được khởi tạo.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Quan sát UI trong quá trình loading
**Kết quả mong đợi:**
- Loading overlay (MudOverlay với MudProgressCircular) hiển thị ngay lập tức
- Overlay có dark background và modal
- Overlay không tự động đóng (AutoClose="false")
- Overlay biến mất khi Workspace.IsInitialized = true
---
### TC-002: Khởi tạo SignalR connections
**Mô tả:** Kiểm tra các SignalR connections được khởi tạo đúng.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Mở browser DevTools > Network tab
3. Quan sát SignalR connections
**Kết quả mong đợi:**
- FileManagerHub connection được khởi tạo
- ScriptManagerHub connection được khởi tạo
- Connections thành công (status 101 Switching Protocols)
- Không có lỗi connection trong console
---
### TC-003: Request edit permission khi khởi tạo
**Mô tả:** Kiểm tra edit permission được request tự động khi khởi tạo.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Quan sát Network tab hoặc server logs
**Kết quả mong đợi:**
- RequestEditPermission được gọi tự động
- Permission được grant nếu ScriptEngine state là Idle
- Permission bị từ chối nếu ScriptEngine state không phải Idle
- Workspace.IsReadOnly được set đúng dựa trên permission
---
### TC-004: Khởi tạo Workspace với metadata references
**Mô tả:** Kiểm tra Workspace được khởi tạo với đúng metadata references.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Đợi loading hoàn tất
3. Mở một file trong editor
**Kết quả mong đợi:**
- Workspace.Initialize được gọi với đúng parameters:
- Metadata references từ ScriptResource
- Using namespaces
- AppGlobalType
- Root folder structure
- Editor có IntelliSense hoạt động đúng
- Không có lỗi trong console
---
### TC-005: Khởi tạo JavaScript resize handlers
**Mô tả:** Kiểm tra JavaScript module cho resize handlers được load đúng.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Đợi loading hoàn tất
3. Thử resize sidebar hoặc console
**Kết quả mong đợi:**
- scriptEditorResize.js được load thành công
- initializeLayout được gọi
- Sidebar có thể resize ngang
- Console có thể resize dọc
- Editor area điều chỉnh kích thước đúng
---
## 2. Test Cases - Layout và Resize
### TC-006: Resize sidebar ngang
**Mô tả:** Kiểm tra sidebar có thể resize ngang.
**Các bước:**
1. Hover vào border bên phải của sidebar
2. Drag để resize
3. Quan sát UI
**Kết quả mong đợi:**
- Cursor đổi thành col-resize khi hover
- Border highlight khi hover
- Sidebar width thay đổi khi drag
- Editor area điều chỉnh width tự động
- Min width: 200px, Max width: 600px
- Width được giữ lại sau khi refresh (nếu có persistence)
---
### TC-007: Resize console panel dọc
**Mô tả:** Kiểm tra console panel có thể resize dọc.
**Các bước:**
1. Hover vào resizer giữa Editor và Console
2. Drag để resize
3. Quan sát UI
**Kết quả mong đợi:**
- Cursor đổi thành row-resize khi hover
- Resizer highlight khi hover
- Console height thay đổi khi drag
- Editor area điều chỉnh height tự động
- Min height cho editor: 200px
- Height được giữ lại sau khi refresh (nếu có persistence)
---
### TC-008: Layout responsive khi resize window
**Mô tả:** Kiểm tra layout điều chỉnh đúng khi resize browser window.
**Các bước:**
1. Resize browser window
2. Quan sát layout
**Kết quả mong đợi:**
- Sidebar, Editor, Console điều chỉnh kích thước đúng
- Không có overflow hoặc scroll không mong muốn
- Layout vẫn hoạt động tốt ở các kích thước khác nhau
---
## 3. Test Cases - Edit Permission
### TC-009: Edit permission được grant khi state là Idle
**Mô tả:** Kiểm tra edit permission được grant khi ScriptEngine state là Idle.
**Các bước:**
1. Đảm bảo ScriptEngine state là Idle
2. Navigate đến ScriptEditor page
3. Thử edit một file
**Kết quả mong đợi:**
- RequestEditPermission thành công
- HasEditPermission trả về true
- Workspace.IsReadOnly = false
- Editor cho phép edit (không readonly)
- FileExplorer cho phép tạo/xóa/rename
---
### TC-010: Edit permission bị từ chối khi state không phải Idle
**Mô tả:** Kiểm tra edit permission bị từ chối khi ScriptEngine state không phải Idle.
**Các bước:**
1. Đảm bảo ScriptEngine state là Ready hoặc Running
2. Navigate đến ScriptEditor page
3. Thử edit một file
**Kết quả mong đợi:**
- RequestEditPermission vẫn được gọi (luôn thành công)
- HasEditPermission trả về false (vì state không phải Idle)
- Workspace.IsReadOnly = true
- Editor readonly (không cho phép edit)
- FileExplorer không cho phép tạo/xóa/rename
---
### TC-011: Edit permission bị revoke từ client khác
**Mô tả:** Kiểm tra edit permission bị revoke khi client khác request permission.
**Các bước:**
1. Mở ScriptEditor trên 2 clients (Client A và Client B)
2. Client A có edit permission
3. Client B request edit permission
4. Quan sát Client A
**Kết quả mong đợi:**
- Client A nhận EditPermissionRevoked event
- PermissionRevokedDialog hiển thị trên Client A
- Workspace.IsReadOnly = true trên Client A
- Editor trở thành readonly trên Client A
- Dialog chỉ có thể đóng bằng nút Reload (không thể click outside hoặc Escape)
---
### TC-012: Revoke edit permission khi dispose
**Mô tả:** Kiểm tra edit permission được revoke khi component dispose.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Có edit permission
3. Navigate away hoặc close tab
4. Quan sát server logs
**Kết quả mong đợi:**
- RevokeEditPermission được gọi trước khi disconnect
- Permission được clear trên server
- Không có lỗi trong console
---
## 4. Test Cases - Component Integration
### TC-013: FileExplorer tích hợp với Editor
**Mô tả:** Kiểm tra FileExplorer tích hợp đúng với Editor.
**Các bước:**
1. Click vào một file trong FileExplorer
2. Quan sát Editor
**Kết quả mong đợi:**
- File được mở trong Editor
- Editor hiển thị đúng nội dung file
- Workspace.CurrentFile được set đúng
- Editor header hiển thị tên file
---
### TC-014: Editor tích hợp với Console
**Mô tả:** Kiểm tra Editor tích hợp đúng với Console.
**Các bước:**
1. Build scripts từ Editor
2. Quan sát Console
**Kết quả mong đợi:**
- Build messages hiển thị trong Console
- Error messages hiển thị trong Console
- Warning messages hiển thị trong Console
- Info messages hiển thị trong Console
---
### TC-015: VariableManager tích hợp với ScriptEngine
**Mô tả:** Kiểm tra VariableManager hiển thị đúng variables từ ScriptEngine.
**Các bước:**
1. Build scripts thành công
2. Quan sát VariableManager trong sidebar
**Kết quả mong đợi:**
- Variables được load và hiển thị
- Chỉ hiển thị variables có PublicRead = true
- Values được hiển thị đúng
- Có thể edit variables có PublicWrite = true
---
### TC-016: TaskManager tích hợp với ScriptEngine
**Mô tả:** Kiểm tra TaskManager hiển thị đúng tasks từ ScriptEngine.
**Các bước:**
1. Build scripts thành công
2. Start ScriptEngine
3. Quan sát TaskManager trong sidebar
**Kết quả mong đợi:**
- Tasks được load và hiển thị khi state là Ready hoặc Running
- Task states được hiển thị đúng
- Có thể enable/disable tasks
- Tasks với AutoStart = true tự động start
---
### TC-017: MissionManager tích hợp với ScriptEngine
**Mô tả:** Kiểm tra MissionManager hiển thị đúng missions từ ScriptEngine.
**Các bước:**
1. Build scripts thành công
2. Start ScriptEngine
3. Quan sát MissionManager trong sidebar
**Kết quả mong đợi:**
- Missions được load và hiển thị khi state là Ready hoặc Running
- Mission parameters được hiển thị đúng
- Có thể instantiate missions
- Missions với AutoStart = true tự động start
---
## 5. Test Cases - State Management
### TC-018: UI cập nhật khi ScriptEngine state thay đổi
**Mô tả:** Kiểm tra UI cập nhật đúng khi ScriptEngine state thay đổi.
**Các bước:**
1. Build scripts
2. Quan sát Editor header buttons
3. Start ScriptEngine
4. Quan sát Editor header buttons
**Kết quả mong đợi:**
- Build button enabled khi state là Idle hoặc BuildError
- Start button enabled khi state là Ready
- Stop button enabled khi state là Running
- Reset button enabled khi state là Idle, Ready, BuildError, Running, hoặc Fault
- Buttons disabled đúng theo state
---
### TC-019: Editor readonly state theo ScriptEngine state
**Mô tả:** Kiểm tra Editor readonly state thay đổi theo ScriptEngine state.
**Các bước:**
1. Đảm bảo ScriptEngine state là Idle
2. Mở một file trong Editor
3. Thử edit
4. Build scripts (chuyển sang Ready state)
5. Thử edit
**Kết quả mong đợi:**
- Editor cho phép edit khi state là Idle
- Editor trở thành readonly khi state không phải Idle
- Editor trở lại cho phép edit khi state quay về Idle
---
### TC-020: Workspace state đồng bộ với ScriptEngine
**Mô tả:** Kiểm tra Workspace state đồng bộ đúng với ScriptEngine state.
**Các bước:**
1. Thực hiện các thao tác (build, start, stop, reset)
2. Kiểm tra Workspace state
**Kết quả mong đợi:**
- Workspace.IsReadOnly đồng bộ với ScriptEngine state
- Workspace.CurrentFile được cập nhật đúng
- Workspace.Folders và Workspace.Files được cập nhật đúng
---
## 6. Test Cases - Error Handling
### TC-021: Xử lý lỗi khi SignalR connection fail
**Mô tả:** Kiểm tra xử lý lỗi khi SignalR connection không thể kết nối.
**Các bước:**
1. Tắt server hoặc block SignalR port
2. Navigate đến ScriptEditor page
3. Quan sát UI
**Kết quả mong đợi:**
- Loading overlay vẫn hiển thị
- Error message hiển thị (nếu có)
- Không crash ứng dụng
- Có thể retry connection
---
### TC-022: Xử lý lỗi khi JavaScript module không load
**Mô tả:** Kiểm tra xử lý lỗi khi scriptEditorResize.js không load được.
**Các bước:**
1. Block scriptEditorResize.js trong browser DevTools
2. Navigate đến ScriptEditor page
3. Quan sát UI
**Kết quả mong đợi:**
- JSException được catch
- Ứng dụng vẫn hoạt động (không crash)
- Resize có thể không hoạt động nhưng không ảnh hưởng chức năng khác
---
### TC-023: Xử lý lỗi khi Workspace initialization fail
**Mô tả:** Kiểm tra xử lý lỗi khi Workspace initialization thất bại.
**Các bước:**
1. Simulate lỗi trong ResourceResolver hoặc FileManagerClient
2. Navigate đến ScriptEditor page
3. Quan sát UI
**Kết quả mong đợi:**
- Exception được catch
- Loading overlay có thể không biến mất hoặc hiển thị error
- Không crash ứng dụng
- Error message hiển thị cho user
---
## 7. Test Cases - Cleanup và Dispose
### TC-024: Cleanup khi component dispose
**Mô tả:** Kiểm tra cleanup đúng khi component dispose.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Navigate away
3. Quan sát Network tab và console
**Kết quả mong đợi:**
- EditPermissionRevoked event được unsubscribe
- JavaScript module cleanup được gọi
- Edit permission được revoke
- SignalR connections được stop
- Không có memory leaks
- Không có lỗi trong console
---
### TC-025: Xử lý JSDisconnectedException khi dispose
**Mô tả:** Kiểm tra xử lý JSDisconnectedException khi JS context đã disconnect.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Close tab đột ngột
3. Quan sát server logs
**Kết quả mong đợi:**
- JSDisconnectedException được catch
- Không có lỗi trong server logs
- Cleanup vẫn được thực hiện đúng
---
## 8. Test Cases - Performance
### TC-026: Performance khi khởi tạo với nhiều files
**Mô tả:** Kiểm tra performance khi workspace có nhiều files.
**Các bước:**
1. Tạo workspace với 100+ files
2. Navigate đến ScriptEditor page
3. Đo thời gian loading
**Kết quả mong đợi:**
- Loading time < 5 giây cho 100 files
- UI không bị freeze
- Workspace initialization hoàn tất trong thời gian hợp lý
---
### TC-027: Performance khi resize layout
**Mô tả:** Kiểm tra performance khi resize sidebar và console.
**Các bước:**
1. Resize sidebar liên tục
2. Resize console liên tục
3. Quan sát performance
**Kết quả mong đợi:**
- Resize mượt mà, không lag
- UI responsive
- Không có jank hoặc stutter
---
## 9. Test Cases - Edge Cases
### TC-028: Multiple clients cùng lúc
**Mô tả:** Kiểm tra behavior khi có nhiều clients mở cùng lúc.
**Các bước:**
1. Mở ScriptEditor trên 3+ clients
2. Thực hiện các thao tác trên các clients khác nhau
3. Quan sát behavior
**Kết quả mong đợi:**
- Chỉ 1 client có edit permission tại một thời điểm
- Clients khác được notify khi permission bị revoke
- File changes được sync qua SignalR events
- Không có conflict hoặc race conditions
---
### TC-029: Reconnect sau khi disconnect
**Mô tả:** Kiểm tra behavior khi SignalR reconnect.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Disconnect network tạm thời
3. Reconnect network
4. Quan sát behavior
**Kết quả mong đợi:**
- SignalR tự động reconnect
- State được reload sau khi reconnect
- Edit permission được request lại
- UI cập nhật đúng
---
### TC-030: Navigate away và quay lại
**Mô tả:** Kiểm tra behavior khi navigate away và quay lại.
**Các bước:**
1. Navigate đến ScriptEditor page
2. Navigate đến page khác
3. Navigate quay lại ScriptEditor
4. Quan sát behavior
**Kết quả mong đợi:**
- Component được dispose đúng khi navigate away
- Component được khởi tạo lại khi quay lại
- State được reload
- Không có memory leaks
---
## Checklist Test Execution
### Pre-conditions
- [ ] Ứng dụng đã được build thành công
- [ ] Server đang chạy
- [ ] Database có dữ liệu test
- [ ] ScriptEngine đã được configure đúng
### Test Environment
- [ ] Browser: Chrome/Firefox/Edge (latest version)
- [ ] Screen resolution: 1920x1080 hoặc tương đương
- [ ] Network: Stable connection
- [ ] JavaScript enabled
### Test Execution Notes
- Ghi chú các bug phát hiện trong quá trình test
- Ghi lại screenshots cho các test case failed
- Ghi lại performance metrics nếu có vấn đề
- Test với nhiều browsers khác nhau
---
## Known Issues và Limitations
### Đã Fix
- ✅ Edit permission không được request tự động khi khởi tạo
- ✅ Workspace không được khởi tạo đúng khi SignalR chưa connect
- ✅ Loading overlay không hiển thị đúng
### Cần theo dõi
- Performance khi có quá nhiều files (>1000 items)
- Memory leak khi navigate nhiều lần
- SignalR reconnection behavior trong môi trường network không ổn định
---
## Test Priority
### High Priority (P0)
- TC-001, TC-002, TC-003, TC-004, TC-009, TC-010, TC-011, TC-013, TC-018, TC-019, TC-024
### Medium Priority (P1)
- TC-005, TC-006, TC-007, TC-008, TC-012, TC-014, TC-015, TC-016, TC-017, TC-020, TC-021, TC-022, TC-023
### Low Priority (P2)
- TC-025, TC-026, TC-027, TC-028, TC-029, TC-030
---
## Test Results Template
```
Test Case ID: TC-XXX
Test Date: YYYY-MM-DD
Tester: [Name]
Status: Pass/Fail/Blocked
Notes: [Any additional notes]
Screenshots: [If applicable]
Browser: [Browser name and version]
```
---
*Tài liệu này được tạo tự động và cần được cập nhật khi có thay đổi trong ScriptEditor component.*

View File

@@ -0,0 +1,48 @@
# Script Files / File Script
## 📋 Overview / Tổng quan
ScriptEngine hỗ trợ multi-file C# scripts, cho phép tổ chức code như một C# project thực sự.
## 📁 File Organization / Tổ chức File
Scripts được tổ chức như C# project:
```
Scripts/
├── Common/
│ ├── Helpers.cs # Shared helper methods
│ └── Constants.cs # Global constants
├── Tasks/
│ ├── MonitorTask.cs # Periodic monitoring
│ └── MaintenanceTask.cs # Periodic maintenance
└── Missions/
├── DeliverMission.cs # Delivery workflow
└── ChargeMission.cs # Charging workflow
```
## ✨ Đặc điểm / Features
- **Multi-file support**: Files share variables & methods
- **Top-level statements**: Allowed trong C# scripts
- **Class definitions**: Can define classes, structs, enums
- **Using directives**: Supported for namespaces
- **File system storage**: Scripts lưu trong file system
- **Backup & Restore**: ZIP format với preserved structure
## 🔒 File Locking / Khóa File
- SignalR-based file locking
- Khi user đang edit, các session khác không được sửa file
- ScriptEngine quản lý trạng thái cho phép chỉnh sửa hay không
- Không có realtime update file content, chỉ khi user gọi action Save mới gửi lên server
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [Backup & Restore](DataPersistence.md#backup--restore) - Sao lưu và khôi phục scripts
---
**Last Updated**: 2025-11-13

View File

@@ -0,0 +1,42 @@
# Security & Limitations / Bảo mật & Giới hạn
## 📋 Overview / Tổng quan
ScriptEngine có các giới hạn về security và metadata references để đảm bảo an toàn.
## 🔒 MetadataReference Restrictions
### Allowed / Được phép
- `System.Runtime`
- `System.Collections`
- `System.Private.CoreLib`
- `RobotNet.Script` (ScriptEngine APIs)
- App-specific DLL
### Forbidden / Không được phép
**Not included** (for security):
- `System.IO` (file system access)
- `System.Net` (network - trừ khi app explicitly add)
- `System.Reflection.Emit`
- `System.Diagnostics.Process`
## 🔐 Thread Safety / An toàn Luồng
**Current Design**:
- Variables stored in `ConcurrentDictionary` (thread-safe dictionary ops)
- BUT: Complex operations (read-modify-write) NOT atomic
**Recommendation**: User adds manual locking if needed
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [Variables](Variables.md) - Thread-safe variable storage
- [Design Rationale](README.md#design-rationale--lý-do-thiết-kế) - Lý do thiết kế security
---
**Last Updated**: 2025-11-13

View File

@@ -0,0 +1,452 @@
# ScriptEngine State Machine Architecture / Kiến trúc State Machine cho ScriptEngine
## 📋 Overview / Tổng quan
Tài liệu này mô tả kiến trúc state machine cho module ScriptEngine sử dụng **Appccelerate.StateMachine**. Module ScriptEngine có 3 state machine chính:
1. **TaskStateMachine** - Quản lý state của Task (periodic execution)
2. **MissionStateMachine** - Quản lý state của Mission (long-running workflow)
3. **EngineManagerStateMachine** - Quản lý state của ScriptEngine Manager
---
## 🎯 State Machine Definitions / Định nghĩa State Machine
### 1. Task State Machine
#### States / Trạng thái
```csharp
public enum ScriptTaskState
{
Idle = 0,
Running,
Pausing,
Paused,
Resuming,
Stopping,
Stopped,
Error,
}
```
#### Triggers / Sự kiện
**Public Triggers** (có thể gọi từ bên ngoài):
- `Start` - Bắt đầu task
- `Pause` - Tạm dừng task (timer tiếp tục chạy, chỉ skip execution)
- `Resume` - Tiếp tục task (timer đã chạy, chỉ enable execution lại)
- `Stop` - Dừng task (dừng timer và cleanup)
**Internal Triggers** (tự động fire khi operation hoàn thành):
- `PausingCompleted` - Hoàn thành quá trình pausing
- `ResumingCompleted` - Hoàn thành quá trình resuming
- `StoppingCompleted` - Hoàn thành quá trình stopping
- `ErrorOccurred` - Xảy ra lỗi
#### State Transition Diagram / Sơ đồ Chuyển đổi Trạng thái
```mermaid
stateDiagram-v2
[*] --> Idle
Idle --> Running: Start
Running --> Pausing: Pause
Running --> Stopping: Stop
Running --> Error: ErrorOccurred
Pausing --> Paused: PausingCompleted
Pausing --> Error: ErrorOccurred
Paused --> Resuming: Resume
Paused --> Stopping: Stop
Resuming --> Running: ResumingCompleted
Resuming --> Error: ErrorOccurred
Stopping --> Stopped: StoppingCompleted
Stopping --> Error: ErrorOccurred
Stopped --> Running: Start
Error --> Running: Start
note right of Running
Task đang chạy định kỳ
theo interval
Timer/Realtime loop đang chạy
end note
note right of Paused
Task đã tạm dừng
Timer/Realtime loop vẫn chạy
Chỉ skip execution
Có thể resume hoặc stop
end note
note right of Stopped
Task đã dừng
Timer/Realtime loop đã dừng
Có thể start lại
end note
note right of Error
Task gặp lỗi
Có thể start lại
end note
```
---
**Lưu ý về Task State Machine**:
- Task bắt đầu ở state `Idle`
- Khi ở `Running`, task chạy định kỳ theo interval
- **Pause/Resume Behavior**:
- Khi `Pause`: Timer/Realtime loop **vẫn tiếp tục chạy**, chỉ skip execution khi timer expire
- Khi `Resume`: Timer/Realtime loop **đã chạy**, chỉ enable execution lại
- Điều này đảm bảo timer không bị gián đoạn và có thể resume ngay lập tức
- Các intermediate states (`Pausing`, `Resuming`, `Stopping`) được sử dụng khi có async operations
- Từ `Stopped` hoặc `Error`, có thể `Start` lại để về `Running` (không cần về `Idle`)
- Task có thể được pause/resume nhiều lần
- Task có thuộc tính `AutoStart` (mặc định `true`) - khi `AutoStart = true`, task sẽ tự động start khi Engine chuyển sang `Running`
- Khi Engine chuyển sang `Stopping`, tất cả Tasks phải stop và về `Stopped`
- **Enable/Disable là API level, Pause/Resume là state machine level**:
- `Enable()` = `Resume()` - chuyển từ `Paused``Resuming``Running`
- `Disable()` = `Pause()` - chuyển từ `Running``Pausing``Paused`
- `Stopped` chỉ xảy ra khi Engine stop, không phải khi Disable
- **Dispose**: `Dispose()` method được gọi trực tiếp, không qua state machine trigger. Dispose có thể được gọi từ bất kỳ state nào và sẽ tự động stop task nếu đang running trước khi cleanup
---
### 2. Mission State Machine
#### States / Trạng thái
```csharp
public enum ScriptMissionState
{
Idle = 0,
Running,
Canceling,
Pausing,
Paused,
Resuming,
Canceled,
Completed,
Error,
}
```
#### Triggers / Sự kiện
**Public Triggers**:
- `Start` - Bắt đầu mission
- `Cancel` - Hủy mission
- `Pause` - Tạm dừng mission
- `Resume` - Tiếp tục mission
**Internal Triggers**:
- `CompleteCanceling` - Hoàn thành quá trình canceling
- `CompletePausing` - Hoàn thành quá trình pausing
- `CompleteResuming` - Hoàn thành quá trình resuming
- `CompleteRunning` - Hoàn thành mission (success)
- `ErrorOccurred` - Xảy ra lỗi
#### State Transition Diagram / Sơ đồ Chuyển đổi Trạng thái
```mermaid
stateDiagram-v2
[*] --> Idle
Idle --> Running: Start
Running --> Canceling: Cancel
Running --> Pausing: Pause
Running --> Completed: CompleteRunning
Running --> Error: ErrorOccurred
Canceling --> Canceled: CompleteCanceling
Canceling --> Error: ErrorOccurred
Pausing --> Paused: CompletePausing
Pausing --> Error: ErrorOccurred
Paused --> Resuming: Resume
Paused --> Canceling: Cancel
Resuming --> Running: CompleteResuming
Resuming --> Error: ErrorOccurred
Canceled --> [*]
Completed --> [*]
Error --> [*]
note right of Running
Mission đang thực thi
IAsyncEnumerable execution
end note
note right of Paused
Mission đã tạm dừng
Có thể resume hoặc cancel
end note
```
---
**Lưu ý về Mission State Machine**:
- **Mission vs MissionInstance**:
- `Mission` là method được khai báo trong script với `[Mission]` attribute (không có state machine)
- `MissionInstance` là instance được tạo từ Mission method khi gọi `CreateMission()` (có state machine)
- State machine này quản lý state của **MissionInstance**, không phải Mission class
- MissionInstance bắt đầu ở state `Idle`
- Khi ở `Running`, MissionInstance thực thi IAsyncEnumerable workflow
- Có thể pause/resume MissionInstance trong quá trình execution thông qua cơ chế `MoveNext()` của IAsyncEnumerable
- Terminal states (`Completed`, `Canceled`, `Error`) là final states - không thể transition từ đây
- Mỗi MissionInstance chỉ chạy một lần, sau khi complete/cancel/error thì không thể reuse
- Để chạy lại mission, phải tạo MissionInstance mới
- Khi Engine chuyển sang `Stopping`, các MissionInstance đang `Running` sẽ bị cancel và chờ về `Canceled`
- **MissionInstance Lifecycle**: Khi MissionInstance về terminal states (`Completed`, `Canceled`, `Error`):
1. Lưu trạng thái, log và score vào database
2. Dispose MissionInstance
---
### 3. Engine Manager State Machine
#### States / Trạng thái
```csharp
public enum ScriptEngineState
{
Initializing = 0,
Resetting,
Idle,
Building,
Ready,
Starting,
Running,
Stopping,
BuildError,
Fault,
}
```
#### Triggers / Sự kiện
**Public Triggers**:
- `Reset` - Reset engine về Idle
- `Build` - Build scripts
- `Start` - Start engine (enable tasks/missions)
- `Stop` - Stop engine
**Internal Triggers**:
- `InitializationCompleted` - Hoàn thành initialization (tự động chuyển từ Initializing → Idle)
- `ResettingCompleted` - Hoàn thành reset
- `BuildingCompleted` - Hoàn thành build
- `StartingCompleted` - Hoàn thành starting
- `StoppingCompleted` - Hoàn thành stopping
- `BuildErrorOccurred` - Lỗi khi build
- `FaultOccurred` - Lỗi hệ thống
#### State Transition Diagram / Sơ đồ Chuyển đổi Trạng thái
```mermaid
stateDiagram-v2
[*] --> Initializing
Initializing --> Resetting: Reset
Initializing --> Idle: InitializationCompleted
Resetting --> Idle: ResettingCompleted
Resetting --> Fault: FaultOccurred
Idle --> Building: Build
Idle --> Resetting: Reset
Building --> Ready: BuildingCompleted
Building --> BuildError: BuildErrorOccurred
Building --> Fault: FaultOccurred
BuildError --> Idle: Reset
BuildError --> Building: Build
Ready --> Starting: Start
Ready --> Idle: Reset
Ready --> Building: Build
Starting --> Running: StartingCompleted
Starting --> Fault: FaultOccurred
Running --> Stopping: Stop
Running --> Resetting: Reset
Running --> Fault: FaultOccurred
Stopping --> Ready: StoppingCompleted<br/>(All Tasks Stopped<br/>AND All Missions not Running)
Stopping --> Fault: FaultOccurred
Fault --> Resetting: Reset
note right of Idle
Scripts có thể được edit
và save
end note
note right of Building
Compile scripts
Extract metadata
end note
note right of Running
Tasks execute periodically
MissionInstances can be created
Tasks with AutoStart=true auto-start
end note
note right of Stopping
Wait for all Tasks to Stopped
Wait for all MissionInstances
not Running
end note
```
---
**Lưu ý về Engine Manager State Machine**:
- Engine bắt đầu ở state `Initializing` khi khởi động
- Engine tự động chuyển từ `Initializing` sang `Idle` khi initialization hoàn thành
- `Idle`: Scripts có thể được edit và save
- `Building`: Compile scripts và extract metadata (Tasks, Missions, Variables). Khi build thành công, sẽ tạo lại Task và Mission từ compiled scripts
- `Ready`: Scripts đã compiled thành công, sẵn sàng để start. **Không thể edit scripts khi ở Ready**, phải gọi `Reset` để về `Idle` mới edit được
- `Starting`: Khi Engine vào `Starting`, các Task có `AutoStart = true` sẽ bắt đầu start
- `Running`: Tasks và MissionInstances có thể execute. MissionInstance có thể được tạo khi Engine ở `Running`
- `Stopping`: Engine chỉ chuyển sang `Ready` khi **TẤT CẢ** Tasks đã về `Stopped` **VÀ** **TẤT CẢ** MissionInstances không còn ở state `Running`
- `BuildError`: Lỗi khi compile, có thể reset về Idle hoặc build lại
- `Fault`: Lỗi hệ thống nghiêm trọng, cần reset để recovery
- Engine chỉ có thể `Build` từ `Idle` hoặc `BuildError`. Khi `Running`, chỉ có thể gọi `Stop`
- Khi Engine `Reset`, TaskManager và MissionManager sẽ giải phóng (dispose) tất cả Tasks và MissionInstances
---
## 🔗 Relationships Between State Machines / Mối quan hệ giữa các State Machine
### Hierarchical Relationship / Quan hệ Phân cấp
```mermaid
graph TB
Engine[EngineManagerStateMachine<br/>Running/Ready]
subgraph "When Engine is Running"
TaskMgr[TaskManager<br/>Collections of Tasks<br/>with StateMachines]
MissionMgr[MissionManager<br/>Collections of MissionInstances<br/>with StateMachines]
end
Engine -->|Controls| TaskMgr
Engine -->|Controls| MissionMgr
TaskMgr --> Task1[Task1: Running<br/>AutoStart=true]
TaskMgr --> Task2[Task2: Stopped<br/>AutoStart=false]
TaskMgr --> TaskN[TaskN: Running<br/>AutoStart=true]
MissionMgr --> MissionInst1[MissionInstance1: Running]
MissionMgr --> MissionInst2[MissionInstance2: Completed]
MissionMgr --> MissionInstN[MissionInstanceN: Idle]
style Engine fill:#e6ffe6
style TaskMgr fill:#e6f3ff
style MissionMgr fill:#fff0e6
```
### State Dependencies / Phụ thuộc Trạng thái
1. **EngineManager → TaskManager**:
- Tasks chỉ có thể chạy khi Engine ở state `Running`
- Khi Engine chuyển sang `Stopping`, tất cả Tasks phải stop và về `Stopped`
- Khi Engine ở `Starting`, các Task có `AutoStart = true` sẽ tự động start
- Task có thể được Enable/Disable khi Engine ở `Running` (tương đương pause/resume)
- Khi Engine `Reset`, tất cả Tasks sẽ bị dispose
2. **EngineManager → MissionManager**:
- MissionInstance chỉ có thể start khi Engine ở state `Running`
- MissionInstance có thể được tạo khi Engine ở `Running`
- Khi Engine chuyển sang `Stopping`, các MissionInstance đang `Running` sẽ bị cancel và chờ về `Canceled`
- Engine chỉ chuyển từ `Stopping` sang `Ready` khi **TẤT CẢ** MissionInstances không còn ở state `Running`
- Khi Engine `Reset`, tất cả MissionInstances sẽ bị dispose
3. **Task và MissionInstance độc lập**:
- Tasks và MissionInstances không phụ thuộc trực tiếp vào nhau
- Chúng có thể tương tác qua Variables và APIs
- Có thể chạy song song nhiều MissionInstances cùng lúc
4. **Engine Lifecycle**:
- `Building → Ready`: Tạo lại Task và Mission từ compiled scripts
- `Starting`: Các Task có `AutoStart = true` bắt đầu start
- `Stopping → Ready`: Chờ tất cả Tasks về `Stopped` và tất cả MissionInstances không còn `Running`
- `Reset`: Dispose tất cả Tasks và MissionInstances
---
## 📝 Important Clarifications / Làm rõ Quan trọng
### 1. Task Enable/Disable vs Pause/Resume
**Đã làm rõ**:
- `Enable/Disable`**API level** (public interface cho scripts/users)
- `Pause/Resume`**state machine level** (internal state transitions)
- `Enable()` = `Resume()` - chuyển từ `Paused``Resuming``Running`
- `Disable()` = `Pause()` - chuyển từ `Running``Pausing``Paused`
- Khi Task đang `Running` và bị `Disable()`, sẽ chuyển sang `Pausing` rồi mới về `Paused`
- Khi Task bị `Disable`, state machine sẽ về `Paused` (không phải `Stopped`)
- `Stopped` chỉ xảy ra khi Engine stop, không phải khi Disable
### 2. Mission vs MissionInstance
**Đã làm rõ**:
- `Mission` = method trong script với `[Mission]` attribute (không có state machine)
- `MissionInstance` = instance được tạo từ Mission (có state machine)
- State machine quản lý state của **MissionInstance**, không phải Mission
### 3. Engine Stopping → Ready Transition
**Đã làm rõ**:
- Engine chỉ chuyển từ `Stopping` sang `Ready` khi:
- **TẤT CẢ** Tasks đã về `Stopped`
- **VÀ** **TẤT CẢ** MissionInstances không còn ở state `Running`
- Cần implement logic kiểm tra điều kiện này trước khi fire `StoppingCompleted` trigger
### 4. Task AutoStart Behavior
**Đã làm rõ**:
- Task có thuộc tính `AutoStart` (mặc định `true`)
- Khi Engine chuyển sang `Starting`, các Task có `AutoStart = true` sẽ tự động start
- Task có `AutoStart = false` phải manually start
### 5. Engine Building → Ready
**Đã làm rõ**:
- Khi Engine chuyển từ `Building` sang `Ready`, sẽ tạo lại Task và Mission từ compiled scripts
- Các Task và MissionInstance cũ sẽ bị dispose trước đó (khi Engine Reset hoặc khi bắt đầu Building)
- Flow: `Reset` → dispose Tasks/MissionInstances → `Building` → compile scripts → `Ready` → tạo lại Tasks/Missions từ compiled scripts
### 6. Engine Reset Behavior
**Đã làm rõ**:
- Khi Engine `Reset`, TaskManager và MissionManager sẽ dispose tất cả Tasks và MissionInstances
- Engine về `Idle`, scripts có thể được edit
---
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [Tasks](Tasks.md) - Chi tiết về Tasks
- [Missions](Missions.md) - Chi tiết về Missions
- [Compilation](Compilation.md) - Quá trình build scripts
---
**Last Updated**: 2025-01-XX
**Status**: Design Document
**Library**: Appccelerate.StateMachine

View File

@@ -0,0 +1,75 @@
# Tasks / Nhiệm vụ Định kỳ
## 📋 Overview / Tổng quan
Tasks là methods chạy lặp lại theo interval định kỳ, phù hợp cho monitoring và automation đơn giản.
## 🔧 Cách sử dụng / Usage
```csharp
[Task(Interval = 1000, AutoStart = true)]
public void MonitorBattery()
{
var level = GetBatteryLevel();
if (level < batteryThreshold)
{
Logger.Warning($"Battery low: {level}%");
}
}
// Async task support
[Task(Interval = 5000, AutoStart = false)]
public async Task CheckConnection()
{
await PingServerAsync();
Logger.Info("Connection OK");
}
```
## ⚙️ Đặc điểm / Features
- **Timer-based execution**:
- Standard: Sử dụng `System.Threading.Timer`
- Realtime (Linux): Sử dụng `RealtimeTimer` với dedicated thread và highest priority
- **AutoStart option**: Task có `AutoStart = true` sẽ tự động start khi Engine chuyển sang `Starting` state (xem [StateMachine_Design.md](StateMachine_Design.md))
- **Warning**: Nếu execution time > interval
- **ScriptGlobals**: Reused cho tất cả executions (performance)
- **Thread-safe**: Variables được chia sẻ thread-safe
- **State Machine**: Task có state machine quản lý lifecycle (Idle, Running, Pausing, Paused, Resuming, Stopping, Stopped, Error)
- **Pause/Resume**: Timer/Realtime loop tiếp tục chạy khi paused, chỉ skip execution. Resume ngay lập tức không cần restart timer
## 🎛️ Task Attributes / Thuộc tính Task
- `[Task(Interval = milliseconds)]`: Định nghĩa interval giữa các lần chạy
- `[Task(Interval = milliseconds, AutoStart = true/false)]`: Tự động start khi engine ready
## 🔄 Task Control APIs / API Điều khiển Task
```csharp
EnableTask("MonitoringTask"); // Tương đương task.Resume() - chuyển từ Paused → Running
DisableTask("MaintenanceTask"); // Tương đương task.Pause() - chuyển từ Running → Paused
```
**Lưu ý**:
- `EnableTask/DisableTask` là API level (public interface cho scripts)
- `Pause/Resume` là state machine level (internal state transitions)
- `EnableTask()` = `Resume()` - chuyển từ `Paused``Resuming``Running`
- `DisableTask()` = `Pause()` - chuyển từ `Running``Pausing``Paused`
- **Pause/Resume Behavior**:
- Khi `Pause`: Timer/Realtime loop **vẫn tiếp tục chạy**, chỉ skip execution khi timer expire
- Khi `Resume`: Timer/Realtime loop **đã chạy**, chỉ enable execution lại
- Điều này đảm bảo timer không bị gián đoạn và có thể resume ngay lập tức
- Xem chi tiết về Task state machine trong [StateMachine_Design.md](StateMachine_Design.md)
- Xem tích hợp realtime trong [Realtime Integration Guide](../development/RealtimeIntegration.md)
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [Variables](Variables.md) - Tasks có thể đọc/ghi variables
- [Missions](Missions.md) - Tasks có thể tạo/cancel missions
- [Built-in APIs](BuiltInAPIs.md) - Task control APIs
---
**Last Updated**: 2025-11-13

View File

@@ -0,0 +1,45 @@
# Variables / Biến Toàn cục
## 📋 Overview / Tổng quan
Variables là shared state được chia sẻ giữa tất cả scripts trong ScriptEngine.
## 🔧 Cách sử dụng / Usage
```csharp
// Simple variable (không hiện UI)
int counter = 0;
string robotName = "ROBOT001";
// Variable visible trong UI (read-only)
[Variable]
double batteryThreshold = 20.0;
// Variable có thể edit từ UI
[Variable(Writeable = true)]
int maxSpeed = 100;
```
## ⚙️ Cách hoạt động / How It Works
- Stored in `ConcurrentDictionary<string, object?>`
- Thread-safe dictionary operations
- Runtime-only (không persist to database)
- Property wrappers tự động generate
## 📊 Variable Attributes / Thuộc tính Variable
- `[Variable]`: Variable hiển thị trong UI, read-only
- `[Variable(Writeable = true)]`: Variable có thể edit từ UI
- Không có attribute: Variable không hiển thị trong UI
## 🔗 Related Documents / Tài liệu Liên quan
- [ScriptEngine Overview](README.md) - Tổng quan ScriptEngine
- [Tasks](Tasks.md) - Tasks có thể đọc/ghi variables
- [Missions](Missions.md) - Missions có thể đọc/ghi variables
---
**Last Updated**: 2025-11-13