Files
Denso/srcs/RobotNet10/Commons/RobotNet10.CustomConfiguration/README.md
2026-07-03 16:31:37 +07:00

786 lines
18 KiB
Markdown

# RobotNet10.CustomConfiguration
Thư viện quản lý cấu hình động cho ứng dụng RobotNet10, cho phép import/export, chỉnh sửa và quản lý các file cấu hình dạng JSON với hỗ trợ nhiều kiểu dữ liệu.
## 📋 Mục lục
- [Tính năng](#tính-năng)
- [Cấu trúc Project](#cấu-trúc-project)
- [Cài đặt và Cấu hình](#cài-đặt-và-cấu-hình)
- [Hướng dẫn sử dụng Backend](#hướng-dẫn-sử-dụng-backend)
- [Hướng dẫn sử dụng Frontend](#hướng-dẫn-sử-dụng-frontend)
- [Format JSON Config](#format-json-config)
- [API Endpoints](#api-endpoints)
- [Ví dụ sử dụng](#ví-dụ-sử-dụng)
- [Troubleshooting](#troubleshooting)
## ✨ Tính năng
-**Import/Export Config**: Import và export các file cấu hình dạng JSON
-**Quản lý Config Files**: Tạo, đọc, cập nhật, xóa các file cấu hình
-**Quản lý Variables**: Thêm, sửa, xóa các biến trong config
-**Hỗ trợ nhiều kiểu dữ liệu**: String, Int, Double, Bool, Object, Array, Enum
-**Validation**: Kiểm tra tính hợp lệ của dữ liệu theo type và constraints
-**Tìm kiếm**: Tìm kiếm config theo tên, loại
-**UI Component**: Component Blazor sẵn có để quản lý config qua giao diện
-**Storage Manager**: Tích hợp với RobotNet10.StorageManager (Local hoặc MinIO)
## 📁 Cấu trúc Project
```
RobotNet10.CustomConfiguration/
├── Controllers/
│ └── ConfigController.cs # REST API Controller
├── DTOs/
│ ├── ConfigFileDto.cs
│ ├── ConfigFileMetadataDto.cs
│ ├── ConfigVariableDto.cs
│ └── Requests/
│ ├── CreateConfigRequest.cs
│ ├── UpdateConfigRequest.cs
│ └── UpdateVariableRequest.cs
├── Extensions/
│ └── ServiceCollectionExtensions.cs # DI Extension methods
├── Helpers/
│ ├── JsonConfigParser.cs # Parse/Serialize JSON
│ └── VariableTypeConverter.cs # Convert variable types
├── Models/
│ ├── ConfigFile.cs
│ ├── ConfigFileMetadata.cs
│ ├── ConfigVariable.cs
│ └── ConfigVariableType.cs
├── Services/
│ ├── IConfigService.cs
│ ├── ConfigService.cs
│ ├── ConfigService.Implementation.cs
│ └── ConfigService.Metadata.cs
└── Validators/
└── ConfigValidator.cs # Validation logic
```
## 🚀 Cài đặt và Cấu hình
### 1. Thêm Project Reference
Thêm reference vào project của bạn:
```xml
<ItemGroup>
<ProjectReference Include="..\Commons\RobotNet10.CustomConfiguration\RobotNet10.CustomConfiguration.csproj" />
</ItemGroup>
```
### 2. Cấu hình Backend (ASP.NET Core)
#### Bước 1: Thêm using trong `Program.cs`
```csharp
using RobotNet10.CustomConfiguration.Extensions;
using RobotNet10.StorageManager;
```
#### Bước 2: Đăng ký Services
**Cách 1: Từ appsettings.json (Khuyến nghị)**
```csharp
// Trong Program.cs
builder.Services.AddCustomConfiguration(builder.Configuration, "StorageConfig");
```
Thêm vào `appsettings.json`:
```json
{
"StorageConfig": {
"UsingLocal": true,
"LocalFolder": "Configs",
"Bucket": "",
"RetryCount": 3,
"MinioConfig": {
"Endpoint": "localhost:9000",
"User": "minioadmin",
"Password": "minioadmin",
"EnableSSL": false
}
}
}
```
**Cách 2: Trực tiếp trong code**
```csharp
var storageConfig = new StorageConfig
{
UsingLocal = true,
LocalFolder = "Configs",
Bucket = "",
RetryCount = 3
};
builder.Services.AddCustomConfiguration(storageConfig);
```
#### Bước 3: Đảm bảo đã map Controllers
```csharp
var app = builder.Build();
// ... middleware ...
app.MapControllers(); // Đảm bảo có dòng này
app.Run();
```
### 3. Cấu hình Frontend (Blazor)
#### Bước 1: Thêm Project Reference
```xml
<ItemGroup>
<ProjectReference Include="..\Components\RobotNet10.CustomConfigurationEditor\RobotNet10.CustomConfigurationEditor.csproj" />
</ItemGroup>
```
#### Bước 2: Đăng ký Services trong `Program.cs` hoặc `Client/Program.cs`
```csharp
using RobotNet10.CustomConfigurationEditor.Services.API;
using RobotNet10.CustomConfigurationEditor.Services.State;
// HttpClient (nếu chưa có)
builder.Services.AddScoped(sp => new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
// MudBlazor (nếu chưa có)
builder.Services.AddMudServices();
// CustomConfiguration Services
builder.Services.AddScoped<ConfigApiService>();
builder.Services.AddScoped<ConfigManagerState>();
```
#### Bước 3: Copy JavaScript file
Copy file `downloadFile.js` từ `RobotNet10.CustomConfigurationEditor/wwwroot/js/downloadFile.js` vào `wwwroot/js/` của project frontend.
Thêm vào `index.html` hoặc `App.razor`:
```html
<script src="js/downloadFile.js"></script>
```
#### Bước 4: Thêm using trong `_Imports.razor`
```razor
@using RobotNet10.CustomConfigurationEditor.Components.ConfigManager
```
## 📖 Hướng dẫn sử dụng Backend
### Sử dụng IConfigService
Inject `IConfigService` vào service hoặc controller của bạn:
```csharp
public class MyService
{
private readonly IConfigService _configService;
public MyService(IConfigService configService)
{
_configService = configService;
}
public async Task<ConfigFile> GetMqttConfigAsync()
{
return await _configService.GetConfigByTypeAsync("MQTTBrokerConfig");
}
}
```
### Các phương thức chính
```csharp
// Lấy tất cả configs (metadata)
var configs = await _configService.GetAllConfigsAsync();
// Lấy config theo ID
var config = await _configService.GetConfigByIdAsync(id);
// Lấy config theo ConfigType
var mqttConfig = await _configService.GetConfigByTypeAsync("MQTTBrokerConfig");
// Tạo config mới
var newConfig = await _configService.CreateConfigAsync(
configType: "MyConfig",
variables: variables,
description: "My configuration"
);
// Cập nhật config
await _configService.UpdateConfigAsync(id, variables, description);
// Xóa config
await _configService.DeleteConfigAsync(id);
// Import từ file
using var stream = File.OpenRead("config.json");
var imported = await _configService.ImportConfigAsync(stream, "config.json", "MyConfig");
// Export ra file
var exportStream = await _configService.ExportConfigAsync(id);
// Cập nhật variable
await _configService.UpdateVariableAsync(id, "port", 8080);
// Thêm variable
await _configService.AddVariableAsync(id, newVariable);
// Xóa variable
await _configService.RemoveVariableAsync(id, "variableName");
```
## 🎨 Hướng dẫn sử dụng Frontend
### Sử dụng Component
Tạo page mới hoặc thêm vào page hiện có:
```razor
@page "/config-manager"
@using RobotNet10.CustomConfigurationEditor.Components.ConfigManager
<ConfigManagerComponent />
```
### Sử dụng ConfigManagerState
Inject `ConfigManagerState` vào component của bạn:
```razor
@inject ConfigManagerState State
<MudButton OnClick="LoadConfigs">Load Configs</MudButton>
@code {
protected override async Task OnInitializedAsync()
{
await State.LoadConfigsAsync();
}
private async Task LoadConfigs()
{
await State.LoadConfigsAsync();
}
}
```
### Các phương thức State
```csharp
// Load tất cả configs
await State.LoadConfigsAsync();
// Load với search query
await State.LoadConfigsAsync("MQTT");
// Load config theo ID
await State.LoadConfigByIdAsync(id);
// Load config theo ConfigType
await State.LoadConfigByTypeAsync("MQTTBrokerConfig");
// Select config
await State.SelectConfigAsync(configMetadata);
// Tạo config mới
var config = await State.CreateConfigAsync(
configType: "MyConfig",
variables: variables,
description: "My config"
);
// Cập nhật config
await State.UpdateConfigAsync(variables, description);
// Xóa config
await State.DeleteConfigAsync(id);
// Import config
using var stream = file.OpenReadStream();
var imported = await State.ImportConfigAsync(stream, file.Name, "MyConfig");
// Export config
var stream = await State.ExportConfigAsync(id);
// Cập nhật variable
await State.UpdateVariableAsync("port", 8080);
// Thêm variable
await State.AddVariableAsync(newVariable);
// Xóa variable
await State.RemoveVariableAsync("variableName");
```
## 📄 Format JSON Config
### Cấu trúc cơ bản
File config là một mảng JSON chứa các variable:
```json
[
{
"name": "port",
"type": "int",
"value": 8080,
"Min": 0,
"Max": 65535,
"Roles": ""
},
{
"name": "host",
"type": "string",
"value": "localhost",
"Roles": ""
},
{
"name": "enableSSL",
"type": "bool",
"value": true,
"Roles": ""
}
]
```
### Các kiểu dữ liệu hỗ trợ
#### 1. String
```json
{
"name": "host",
"type": "string",
"value": "localhost",
"Roles": ""
}
```
#### 2. Int
```json
{
"name": "port",
"type": "int",
"value": 8080,
"Min": 0,
"Max": 65535,
"Roles": ""
}
```
#### 3. Double
```json
{
"name": "timeout",
"type": "double",
"value": 30.5,
"Min": 0.0,
"Max": 100.0,
"Roles": ""
}
```
#### 4. Bool
```json
{
"name": "enableSSL",
"type": "bool",
"value": true,
"Roles": ""
}
```
#### 5. Enum
```json
{
"name": "logLevel",
"type": "enum",
"value": "Info",
"EnumValues": ["Debug", "Info", "Warning", "Error"],
"Roles": ""
}
```
#### 6. Object
```json
{
"name": "database",
"type": "object",
"value": {
"host": "localhost",
"port": 5432,
"name": "mydb"
},
"Roles": ""
}
```
#### 7. Array
```json
{
"name": "allowedIPs",
"type": "array",
"value": ["192.168.1.1", "192.168.1.2", "10.0.0.1"],
"Roles": ""
}
```
### Các thuộc tính
| Thuộc tính | Bắt buộc | Mô tả |
|-----------|----------|-------|
| `name` | ✅ | Tên của variable (duy nhất trong config) |
| `type` | ✅ | Kiểu dữ liệu: `string`, `int`, `double`, `bool`, `enum`, `object`, `array` |
| `value` | ✅ | Giá trị của variable |
| `Min` | ❌ | Giá trị tối thiểu (cho `int``double`) |
| `Max` | ❌ | Giá trị tối đa (cho `int``double`) |
| `EnumValues` | ❌ | Danh sách giá trị cho phép (cho `enum`) |
| `Roles` | ❌ | Roles string (có thể để trống) |
## 🔌 API Endpoints
### Config File Management
#### GET `/api/configs`
Lấy tất cả configs (metadata only)
**Query Parameters:**
- `search` (optional): Tìm kiếm theo tên hoặc ConfigType
**Response:** `200 OK`
```json
[
{
"id": "guid",
"configType": "MQTTBrokerConfig",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"description": "MQTT Broker Configuration"
}
]
```
#### GET `/api/configs/{id}`
Lấy config theo ID
**Response:** `200 OK`
```json
{
"id": "guid",
"configType": "MQTTBrokerConfig",
"variables": [...],
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"description": "MQTT Broker Configuration"
}
```
#### GET `/api/configs/by-type/{configType}`
Lấy config theo ConfigType
**Response:** `200 OK` (same as GET by ID)
#### GET `/api/configs/exists/{configType}`
Kiểm tra ConfigType có tồn tại không
**Response:** `200 OK`
```json
true
```
#### POST `/api/configs`
Tạo config mới
**Request Body:**
```json
{
"configType": "MyConfig",
"variables": [
{
"name": "port",
"type": "int",
"value": 8080
}
],
"description": "My configuration"
}
```
**Response:** `201 Created`
#### PUT `/api/configs/{id}`
Cập nhật config
**Request Body:**
```json
{
"variables": [...],
"description": "Updated description"
}
```
**Response:** `200 OK`
#### DELETE `/api/configs/{id}`
Xóa config
**Response:** `204 No Content`
### Import/Export
#### POST `/api/configs/import`
Import config từ JSON file
**Request:** `multipart/form-data`
- `file`: JSON file
- `configType`: ConfigType name
**Response:** `200 OK`
#### GET `/api/configs/{id}/export`
Export config ra JSON file
**Response:** `200 OK` (application/json)
### Variable Management
#### PUT `/api/configs/{id}/variables/{variableName}`
Cập nhật giá trị variable
**Request Body:**
```json
{
"variableName": "port",
"value": 8080
}
```
**Response:** `200 OK`
#### POST `/api/configs/{id}/variables`
Thêm variable mới
**Request Body:**
```json
{
"name": "newVariable",
"type": "string",
"value": "value"
}
```
**Response:** `200 OK`
#### DELETE `/api/configs/{id}/variables/{variableName}`
Xóa variable
**Response:** `200 OK`
## 💡 Ví dụ sử dụng
### Ví dụ 1: Tạo MQTT Broker Config
```csharp
var variables = new List<ConfigVariable>
{
new ConfigVariable
{
Name = "host",
Type = ConfigVariableType.String,
Value = "localhost"
},
new ConfigVariable
{
Name = "port",
Type = ConfigVariableType.Int,
Value = 1883,
Min = 0,
Max = 65535
},
new ConfigVariable
{
Name = "enableSSL",
Type = ConfigVariableType.Bool,
Value = false
}
};
var config = await _configService.CreateConfigAsync(
configType: "MQTTBrokerConfig",
variables: variables,
description: "MQTT Broker Configuration"
);
```
### Ví dụ 2: Import Config từ File
```csharp
using var stream = File.OpenRead("mqtt-config.json");
var config = await _configService.ImportConfigAsync(
stream: stream,
fileName: "mqtt-config.json",
configType: "MQTTBrokerConfig"
);
```
### Ví dụ 3: Sử dụng Config trong Service
```csharp
public class MqttService
{
private readonly IConfigService _configService;
public MqttService(IConfigService configService)
{
_configService = configService;
}
public async Task ConnectAsync()
{
var config = await _configService.GetConfigByTypeAsync("MQTTBrokerConfig");
var host = config.Variables.First(v => v.Name == "host").Value?.ToString();
var port = (int)config.Variables.First(v => v.Name == "port").Value!;
// Connect to MQTT broker using host and port
}
}
```
### Ví dụ 4: Cập nhật Variable qua API
```csharp
// C# HttpClient
var client = new HttpClient();
var request = new
{
variableName = "port",
value = 8883
};
var response = await client.PutAsJsonAsync(
"https://api.example.com/api/configs/{id}/variables/port",
request
);
```
### Ví dụ 5: Frontend - Sử dụng Component
```razor
@page "/settings/config"
@using RobotNet10.CustomConfigurationEditor.Components.ConfigManager
<PageTitle>Configuration Manager</PageTitle>
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="mt-4">
<ConfigManagerComponent />
</MudContainer>
```
## 🔧 Troubleshooting
### Lỗi: "ConfigType already exists"
**Nguyên nhân:** ConfigType đã tồn tại trong hệ thống.
**Giải pháp:**
- Sử dụng ConfigType khác
- Xóa config cũ trước khi tạo mới
- Kiểm tra bằng `ConfigTypeExistsAsync()` trước khi tạo
### Lỗi: "Invalid variable type"
**Nguyên nhân:** Type của variable không hợp lệ.
**Giải pháp:**
- Kiểm tra type là một trong: `string`, `int`, `double`, `bool`, `enum`, `object`, `array`
- Đảm bảo value phù hợp với type
### Lỗi: "Value out of range"
**Nguyên nhân:** Giá trị vượt quá Min/Max.
**Giải pháp:**
- Kiểm tra giá trị nằm trong khoảng Min và Max
- Cập nhật Min/Max nếu cần
### Lỗi: "Invalid JSON format"
**Nguyên nhân:** File JSON không đúng format.
**Giải pháp:**
- Kiểm tra file là mảng JSON hợp lệ
- Đảm bảo mỗi variable có `name`, `type`, `value`
- Validate JSON trước khi import
### Lỗi: "StorageManager not initialized"
**Nguyên nhân:** StorageConfig chưa được cấu hình.
**Giải pháp:**
- Đảm bảo đã gọi `AddCustomConfiguration()` trong `Program.cs`
- Kiểm tra `StorageConfig` trong `appsettings.json`
### Frontend: Component không hiển thị
**Nguyên nhân:** Services chưa được đăng ký.
**Giải pháp:**
- Kiểm tra đã đăng ký `ConfigApiService``ConfigManagerState`
- Đảm bảo có `HttpClient` với `BaseAddress`
- Kiểm tra đã có `MudBlazor` services
### Frontend: Export không hoạt động
**Nguyên nhân:** JavaScript file chưa được thêm.
**Giải pháp:**
- Copy `downloadFile.js` vào `wwwroot/js/`
- Thêm script tag vào `index.html` hoặc `App.razor`
## 📝 Lưu ý
1. **ConfigType là duy nhất**: Mỗi ConfigType chỉ có thể tồn tại một lần trong hệ thống
2. **Validation**: Tất cả dữ liệu đều được validate trước khi lưu
3. **Storage**: Config files được lưu trong `configs/{ConfigType}.json` trong StorageManager
4. **Metadata**: Metadata được lưu trong `configs/_metadata.json`
5. **Thread Safety**: Services được đăng ký là `Scoped`, phù hợp cho web applications
## 📚 Tài liệu tham khảo
- [RobotNet10.StorageManager Documentation](../RobotNet10.StorageManager/README.md)
- [MudBlazor Documentation](https://mudblazor.com/)
- [ASP.NET Core Documentation](https://docs.microsoft.com/aspnet/core)
## 🤝 Đóng góp
Nếu bạn phát hiện lỗi hoặc có đề xuất cải thiện, vui lòng tạo issue hoặc pull request.
## 📄 License
[Thêm thông tin license nếu có]