Files
SecMPS/api_sqlsugar/Warehouse/Services/SyncEngine.cs
2026-05-17 00:57:03 +08:00

166 lines
5.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}