166 lines
5.8 KiB
C#
166 lines
5.8 KiB
C#
using Microsoft.Extensions.DependencyInjection;
|
||
using VolPro.Core.DbSqlSugar;
|
||
using VolPro.Core.Extensions;
|
||
using VolPro.Entity.DomainModels;
|
||
using Warehouse.IServices;
|
||
|
||
namespace VolPro.Warehouse.Services;
|
||
|
||
/// <summary>
|
||
/// MC4.0 同步引擎:对象树 → 区域匹配 + 设备 Upsert
|
||
/// </summary>
|
||
public class SyncEngine
|
||
{
|
||
private readonly IServiceProvider _sp;
|
||
|
||
public SyncEngine(IServiceProvider sp) => _sp = sp;
|
||
|
||
private Iwarehouse_regionsService GetRegionService() =>
|
||
_sp.GetService<Iwarehouse_regionsService>()!;
|
||
private Iwarehouse_devicepointService GetPointService() =>
|
||
_sp.GetService<Iwarehouse_devicepointService>()!;
|
||
private Ibase_deviceService GetDeviceService() =>
|
||
_sp.GetService<Ibase_deviceService>()!;
|
||
|
||
/// <summary>处理 MC4.0 对象树,匹配区域并 Upsert 设备</summary>
|
||
public async Task<SyncStats> ProcessMc4TreeAsync(
|
||
int gatewayNodeId, string adapterCode, List<Mc4TreeNode> tree)
|
||
{
|
||
var stats = new SyncStats();
|
||
foreach (var node in tree)
|
||
await ProcessNodeAsync(gatewayNodeId, adapterCode, node, null, stats);
|
||
return stats;
|
||
}
|
||
|
||
private async Task ProcessNodeAsync(int gatewayNodeId, string adapterCode,
|
||
Mc4TreeNode node, int? parentDeviceId, SyncStats stats)
|
||
{
|
||
if (node.Type == 1) // 区域节点 → 匹配 warehouse_regions + warehouse_devicepoint
|
||
{
|
||
int pointId = await MatchOrCreatePoint(node);
|
||
// 递归处理子节点,子设备归属到此点位
|
||
foreach (var child in node.Children)
|
||
await ProcessNodeAsync(gatewayNodeId, adapterCode, child, null, stats);
|
||
}
|
||
else if (node.Type == 2) // 设备节点 → Upsert base_device
|
||
{
|
||
int deviceId = await UpsertDevice(gatewayNodeId, adapterCode, node, parentDeviceId);
|
||
if (stats.DeviceIds.TryGetValue(node.Id, out _))
|
||
stats.Updated++;
|
||
else
|
||
stats.Added++;
|
||
stats.DeviceIds[node.Id] = deviceId;
|
||
|
||
foreach (var child in node.Children)
|
||
await ProcessNodeAsync(gatewayNodeId, adapterCode, child, deviceId, stats);
|
||
}
|
||
}
|
||
|
||
private async Task<int> MatchOrCreatePoint(Mc4TreeNode node)
|
||
{
|
||
// 按名称匹配已有区域
|
||
var regionSvc = GetRegionService();
|
||
var region = await regionSvc.FindAsIQueryable(x => x.RegionName == node.Name)
|
||
.FirstOrDefaultAsync();
|
||
if (region == null)
|
||
{
|
||
region = new warehouse_regions
|
||
{
|
||
RegionName = node.Name ?? $"MC4_{node.Id}",
|
||
ParentId = null,
|
||
|
||
};
|
||
regionSvc.Add<object>(region);
|
||
}
|
||
|
||
// 在此区域下找/建点位
|
||
var pointSvc = GetPointService();
|
||
var point = await pointSvc.FindAsIQueryable(x => x.RegionId == region.Id)
|
||
.FirstOrDefaultAsync();
|
||
if (point == null)
|
||
{
|
||
point = new warehouse_devicepoint
|
||
{
|
||
PointName = node.Name ?? $"MC4_PT_{node.Id}",
|
||
RegionId = region.Id,
|
||
|
||
};
|
||
pointSvc.Add<object>(point);
|
||
}
|
||
return point.PointID;
|
||
}
|
||
|
||
private async Task<int> UpsertDevice(int gatewayNodeId, string adapterCode,
|
||
Mc4TreeNode node, int? parentDeviceId)
|
||
{
|
||
var svc = GetDeviceService();
|
||
var sourceId = node.Id.ToString();
|
||
var existing = await svc.FindAsIQueryable(
|
||
x => x.AdapterCode == adapterCode && x.SourceId == sourceId)
|
||
.FirstOrDefaultAsync();
|
||
|
||
if (existing != null)
|
||
{
|
||
existing.IsOnline = "在线";
|
||
existing.LastSyncTime = DateTime.Now;
|
||
existing.ParentDeviceId = parentDeviceId ?? existing.ParentDeviceId;
|
||
if (node.Option != null)
|
||
existing.ExtraData = System.Text.Json.JsonSerializer.Serialize(node.Option);
|
||
existing.SetModifyDefaultVal();
|
||
// 通过 ServiceBase 的基础方法更新;
|
||
return existing.DeviceId;
|
||
}
|
||
else
|
||
{
|
||
var device = new base_device
|
||
{
|
||
DeviceName = node.Name ?? $"MC4_DEV_{node.Id}",
|
||
AdapterCode = adapterCode,
|
||
SourceId = sourceId,
|
||
DeviceCategory = MapCategory(node.ObjectType, node.Tag),
|
||
DeviceGroup = "IoT设备",
|
||
GatewayNodeId = gatewayNodeId,
|
||
ParentDeviceId = parentDeviceId,
|
||
IsParent = node.Children?.Count > 0 ? "是" : "否",
|
||
IsOnline = "在线",
|
||
Enable = "启用",
|
||
LastSyncTime = DateTime.Now,
|
||
ExtraData = node.Option != null
|
||
? System.Text.Json.JsonSerializer.Serialize(node.Option)
|
||
: null
|
||
};
|
||
svc.Add<object>(device);
|
||
return device.DeviceId;
|
||
}
|
||
}
|
||
|
||
private static string MapCategory(int objectType, string? tag) =>
|
||
(objectType, tag) switch
|
||
{
|
||
(_, "温湿度") => "温湿度变送器",
|
||
(_, "烟雾") => "烟雾报警器",
|
||
(_, "气体") => "气体报警器",
|
||
(_, "门磁") => "门磁",
|
||
_ => "动环采集器"
|
||
};
|
||
}
|
||
|
||
public class SyncStats
|
||
{
|
||
public int Added { get; set; }
|
||
public int Updated { get; set; }
|
||
public Dictionary<int, int> DeviceIds { get; set; } = new();
|
||
}
|
||
|
||
/// <summary>简化的 MC4 树节点(网关→Vol.Pro 传输用)</summary>
|
||
public class Mc4TreeNode
|
||
{
|
||
public int Id { get; set; }
|
||
public string? Name { get; set; }
|
||
public int Type { get; set; }
|
||
public int ObjectType { get; set; }
|
||
public string? Tag { get; set; }
|
||
public Dictionary<string, object?>? Option { get; set; }
|
||
public List<Mc4TreeNode> Children { get; set; } = new();
|
||
}
|