165 lines
4.9 KiB
Markdown
165 lines
4.9 KiB
Markdown
|
|
# 软件开发文档 - 03. DMS.Infrastructure 详细设计
|
|||
|
|
|
|||
|
|
`DMS.Infrastructure` 层是所有外部技术和服务的具体实现地。它实现了 `DMS.Core` 定义的接口,为 `DMS.Application` 层提供数据和功能支持。
|
|||
|
|
|
|||
|
|
## 1. 目录结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
DMS.Infrastructure/
|
|||
|
|
├── Data/
|
|||
|
|
│ └── SqlSugarDbContext.cs
|
|||
|
|
├── Entities/
|
|||
|
|
│ ├── DbDevice.cs
|
|||
|
|
│ ├── DbMqttServer.cs
|
|||
|
|
│ ├── DbVariable.cs
|
|||
|
|
│ └── ... (所有数据库表对应的实体)
|
|||
|
|
├── Repositories/
|
|||
|
|
│ ├── BaseRepository.cs
|
|||
|
|
│ ├── DeviceRepository.cs
|
|||
|
|
│ └── ... (所有仓储接口的实现)
|
|||
|
|
├── Services/
|
|||
|
|
│ ├── Communication/
|
|||
|
|
│ │ ├── S7CommunicationService.cs
|
|||
|
|
│ │ └── MqttPublishService.cs
|
|||
|
|
│ ├── Processing/
|
|||
|
|
│ │ ├── ChangeDetectionProcessor.cs
|
|||
|
|
│ │ ├── HistoryStorageProcessor.cs
|
|||
|
|
│ │ └── MqttPublishProcessor.cs
|
|||
|
|
│ └── DatabaseInitializerService.cs
|
|||
|
|
└── DMS.Infrastructure.csproj
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 2. 文件详解
|
|||
|
|
|
|||
|
|
### 2.1. 数据库实体 (`Entities/`)
|
|||
|
|
|
|||
|
|
#### `DbDevice.cs`
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 文件: DMS.Infrastructure/Entities/DbDevice.cs
|
|||
|
|
using SqlSugar;
|
|||
|
|
|
|||
|
|
namespace DMS.Infrastructure.Entities;
|
|||
|
|
|
|||
|
|
[SugarTable("Devices")]
|
|||
|
|
public class DbDevice
|
|||
|
|
{
|
|||
|
|
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
|||
|
|
public int Id { get; set; }
|
|||
|
|
public string Name { get; set; }
|
|||
|
|
public int Protocol { get; set; }
|
|||
|
|
public string IpAddress { get; set; }
|
|||
|
|
public int Port { get; set; }
|
|||
|
|
public bool IsActive { get; set; }
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
... (其他实体 `DbVariableTable`, `DbVariable`, `DbMqttServer`, `DbVariableHistory`, `DbVariableMqttMap` 结构类似) ...
|
|||
|
|
|
|||
|
|
### 2.2. 仓储实现 (`Repositories/`)
|
|||
|
|
|
|||
|
|
#### `BaseRepository.cs`
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 文件: DMS.Infrastructure/Repositories/BaseRepository.cs
|
|||
|
|
// 注意:这里需要一个从领域模型到数据库实体的映射,实际项目中通常使用AutoMapper的ProjectTo或手动映射。
|
|||
|
|
// 为简化示例,此处仅做基础实现。
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### `DeviceRepository.cs`
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 文件: DMS.Infrastructure/Repositories/DeviceRepository.cs
|
|||
|
|
using AutoMapper;
|
|||
|
|
using DMS.Core.Interfaces;
|
|||
|
|
using DMS.Core.Models;
|
|||
|
|
using DMS.Infrastructure.Entities;
|
|||
|
|
using SqlSugar;
|
|||
|
|
|
|||
|
|
public class DeviceRepository : IDeviceRepository
|
|||
|
|
{
|
|||
|
|
private readonly ISqlSugarClient _db;
|
|||
|
|
private readonly IMapper _mapper;
|
|||
|
|
|
|||
|
|
public DeviceRepository(ISqlSugarClient db, IMapper mapper) { /* ... */ }
|
|||
|
|
|
|||
|
|
public async Task<List<Device>> GetActiveDevicesWithDetailsAsync()
|
|||
|
|
{
|
|||
|
|
var dbResult = await _db.Queryable<DbDevice>()
|
|||
|
|
.Where(d => d.IsActive)
|
|||
|
|
.ToListAsync();
|
|||
|
|
// 此处需要手动或通过AutoMapper加载关联的变量表和变量
|
|||
|
|
return _mapper.Map<List<Device>>(dbResult);
|
|||
|
|
}
|
|||
|
|
// ... 其他方法的实现
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.3. 外部服务 (`Services/`)
|
|||
|
|
|
|||
|
|
#### `S7CommunicationService.cs`
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 文件: DMS.Infrastructure/Services/Communication/S7CommunicationService.cs
|
|||
|
|
using S7.Net;
|
|||
|
|
using System.Collections.Concurrent;
|
|||
|
|
|
|||
|
|
public class S7CommunicationService : IS7CommunicationService
|
|||
|
|
{
|
|||
|
|
private readonly ConcurrentDictionary<int, Plc> _clients = new();
|
|||
|
|
|
|||
|
|
public async Task<object> ReadVariableAsync(Device device, Variable variable)
|
|||
|
|
{
|
|||
|
|
if (!_clients.TryGetValue(device.Id, out var plc))
|
|||
|
|
{
|
|||
|
|
plc = new Plc(CpuType.S71500, device.IpAddress, 0, 1);
|
|||
|
|
await plc.OpenAsync();
|
|||
|
|
_clients[device.Id] = plc;
|
|||
|
|
}
|
|||
|
|
return await plc.ReadAsync(variable.Address);
|
|||
|
|
}
|
|||
|
|
// ... 其他连接、断开等管理方法
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### `MqttPublishService.cs`
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 文件: DMS.Infrastructure/Services/Communication/MqttPublishService.cs
|
|||
|
|
using MQTTnet;
|
|||
|
|
using MQTTnet.Client;
|
|||
|
|
|
|||
|
|
public class MqttPublishService : IMqttPublishService
|
|||
|
|
{
|
|||
|
|
private readonly IMqttClient _mqttClient;
|
|||
|
|
|
|||
|
|
public MqttPublishService() {
|
|||
|
|
var factory = new MqttFactory();
|
|||
|
|
_mqttClient = factory.CreateMqttClient();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public async Task PublishAsync(MqttServer server, string topic, string payload)
|
|||
|
|
{
|
|||
|
|
if (!_mqttClient.IsConnected)
|
|||
|
|
{
|
|||
|
|
var options = new MqttClientOptionsBuilder()
|
|||
|
|
.WithTcpServer(server.BrokerAddress, server.Port)
|
|||
|
|
.WithCredentials(server.Username, server.Password)
|
|||
|
|
.Build();
|
|||
|
|
await _mqttClient.ConnectAsync(options, CancellationToken.None);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var message = new MqttApplicationMessageBuilder()
|
|||
|
|
.WithTopic(topic)
|
|||
|
|
.WithPayload(payload)
|
|||
|
|
.WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce)
|
|||
|
|
.Build();
|
|||
|
|
|
|||
|
|
await _mqttClient.PublishAsync(message, CancellationToken.None);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.4. 数据处理器 (`Services/Processing/`)
|
|||
|
|
|
|||
|
|
(此处包含 `ChangeDetectionProcessor`, `HistoryStorageProcessor`, `MqttPublishProcessor` 的完整实现,如之前文档所示,但会更加细化,并注入 `ILogger`)
|