"第8天:同步引擎+区域匹配+设备Upsert+字段分治"
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Ibase_deviceRepository编写接口
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
namespace Warehouse.IRepositories
|
||||
{
|
||||
public partial interface Ibase_deviceRepository : IDependency,IRepository<base_device>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Igateway_nodesRepository编写接口
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
namespace Warehouse.IRepositories
|
||||
{
|
||||
public partial interface Igateway_nodesRepository : IDependency,IRepository<gateway_nodes>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Iiot_alarmRepository编写接口
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
namespace Warehouse.IRepositories
|
||||
{
|
||||
public partial interface Iiot_alarmRepository : IDependency,IRepository<iot_alarm>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Iiot_devicedataRepository编写接口
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
namespace Warehouse.IRepositories
|
||||
{
|
||||
public partial interface Iiot_devicedataRepository : IDependency,IRepository<iot_devicedata>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Ivideo_channelRepository编写接口
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
namespace Warehouse.IRepositories
|
||||
{
|
||||
public partial interface Ivideo_channelRepository : IDependency,IRepository<video_channel>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Ivideo_recordRepository编写接口
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
namespace Warehouse.IRepositories
|
||||
{
|
||||
public partial interface Ivideo_recordRepository : IDependency,IRepository<video_record>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Ibase_deviceService : IService<base_device>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Igateway_nodesService : IService<gateway_nodes>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Iiot_alarmService : IService<iot_alarm>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Iiot_devicedataService : IService<iot_devicedata>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Ivideo_channelService : IService<video_channel>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Ivideo_recordService : IService<video_record>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
*所有关于base_device类的业务代码接口应在此处编写
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Utilities;
|
||||
using System.Linq.Expressions;
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Ibase_deviceService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
*所有关于gateway_nodes类的业务代码接口应在此处编写
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Utilities;
|
||||
using System.Linq.Expressions;
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Igateway_nodesService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
*所有关于iot_alarm类的业务代码接口应在此处编写
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Utilities;
|
||||
using System.Linq.Expressions;
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Iiot_alarmService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
*所有关于iot_devicedata类的业务代码接口应在此处编写
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Utilities;
|
||||
using System.Linq.Expressions;
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Iiot_devicedataService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
*所有关于video_channel类的业务代码接口应在此处编写
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Utilities;
|
||||
using System.Linq.Expressions;
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Ivideo_channelService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
*所有关于video_record类的业务代码接口应在此处编写
|
||||
*/
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Core.Utilities;
|
||||
using System.Linq.Expressions;
|
||||
namespace Warehouse.IServices
|
||||
{
|
||||
public partial interface Ivideo_recordService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹base_deviceRepository编写代码
|
||||
*/
|
||||
using Warehouse.IRepositories;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Core.EFDbContext;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.Repositories
|
||||
{
|
||||
public partial class base_deviceRepository : RepositoryBase<base_device> , Ibase_deviceRepository
|
||||
{
|
||||
public base_deviceRepository(ServiceDbContext dbContext)
|
||||
: base(dbContext)
|
||||
{
|
||||
|
||||
}
|
||||
public static Ibase_deviceRepository Instance
|
||||
{
|
||||
get { return AutofacContainerModule.GetService<Ibase_deviceRepository>(); } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹gateway_nodesRepository编写代码
|
||||
*/
|
||||
using Warehouse.IRepositories;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Core.EFDbContext;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.Repositories
|
||||
{
|
||||
public partial class gateway_nodesRepository : RepositoryBase<gateway_nodes> , Igateway_nodesRepository
|
||||
{
|
||||
public gateway_nodesRepository(ServiceDbContext dbContext)
|
||||
: base(dbContext)
|
||||
{
|
||||
|
||||
}
|
||||
public static Igateway_nodesRepository Instance
|
||||
{
|
||||
get { return AutofacContainerModule.GetService<Igateway_nodesRepository>(); } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹iot_alarmRepository编写代码
|
||||
*/
|
||||
using Warehouse.IRepositories;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Core.EFDbContext;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.Repositories
|
||||
{
|
||||
public partial class iot_alarmRepository : RepositoryBase<iot_alarm> , Iiot_alarmRepository
|
||||
{
|
||||
public iot_alarmRepository(ServiceDbContext dbContext)
|
||||
: base(dbContext)
|
||||
{
|
||||
|
||||
}
|
||||
public static Iiot_alarmRepository Instance
|
||||
{
|
||||
get { return AutofacContainerModule.GetService<Iiot_alarmRepository>(); } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹iot_devicedataRepository编写代码
|
||||
*/
|
||||
using Warehouse.IRepositories;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Core.EFDbContext;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.Repositories
|
||||
{
|
||||
public partial class iot_devicedataRepository : RepositoryBase<iot_devicedata> , Iiot_devicedataRepository
|
||||
{
|
||||
public iot_devicedataRepository(ServiceDbContext dbContext)
|
||||
: base(dbContext)
|
||||
{
|
||||
|
||||
}
|
||||
public static Iiot_devicedataRepository Instance
|
||||
{
|
||||
get { return AutofacContainerModule.GetService<Iiot_devicedataRepository>(); } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹video_channelRepository编写代码
|
||||
*/
|
||||
using Warehouse.IRepositories;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Core.EFDbContext;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.Repositories
|
||||
{
|
||||
public partial class video_channelRepository : RepositoryBase<video_channel> , Ivideo_channelRepository
|
||||
{
|
||||
public video_channelRepository(ServiceDbContext dbContext)
|
||||
: base(dbContext)
|
||||
{
|
||||
|
||||
}
|
||||
public static Ivideo_channelRepository Instance
|
||||
{
|
||||
get { return AutofacContainerModule.GetService<Ivideo_channelRepository>(); } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
*代码由框架生成,任何更改都可能导致被代码生成器覆盖
|
||||
*Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹video_recordRepository编写代码
|
||||
*/
|
||||
using Warehouse.IRepositories;
|
||||
using VolPro.Core.BaseProvider;
|
||||
using VolPro.Core.EFDbContext;
|
||||
using VolPro.Core.Extensions.AutofacManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace Warehouse.Repositories
|
||||
{
|
||||
public partial class video_recordRepository : RepositoryBase<video_record> , Ivideo_recordRepository
|
||||
{
|
||||
public video_recordRepository(ServiceDbContext dbContext)
|
||||
: base(dbContext)
|
||||
{
|
||||
|
||||
}
|
||||
public static Ivideo_recordRepository Instance
|
||||
{
|
||||
get { return AutofacContainerModule.GetService<Ivideo_recordRepository>(); } }
|
||||
}
|
||||
}
|
||||
163
api_sqlsugar/Warehouse/Services/SyncEngine.cs
Normal file
163
api_sqlsugar/Warehouse/Services/SyncEngine.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
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.RegionsName == node.Name)
|
||||
.FirstOrDefaultAsync();
|
||||
if (region == null)
|
||||
{
|
||||
region = new warehouse_regions
|
||||
{
|
||||
RegionsName = node.Name ?? $"MC4_{node.Id}",
|
||||
ParentId = null,
|
||||
CreateDate = DateTime.Now
|
||||
};
|
||||
await regionSvc.AddAsync(region);
|
||||
}
|
||||
|
||||
// 在此区域下找/建点位
|
||||
var pointSvc = GetPointService();
|
||||
var point = await pointSvc.FindAsIQueryable(x => x.RegionId == region.RegionsId)
|
||||
.FirstOrDefaultAsync();
|
||||
if (point == null)
|
||||
{
|
||||
point = new warehouse_devicepoint
|
||||
{
|
||||
DevicePointName = node.Name ?? $"MC4_PT_{node.Id}",
|
||||
RegionId = region.RegionsId,
|
||||
CreateDate = DateTime.Now
|
||||
};
|
||||
await pointSvc.AddAsync(point);
|
||||
}
|
||||
return point.DevicePointId;
|
||||
}
|
||||
|
||||
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);
|
||||
await svc.UpdateAsync(existing);
|
||||
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,
|
||||
CreateDate = DateTime.Now,
|
||||
ExtraData = node.Option != null
|
||||
? System.Text.Json.JsonSerializer.Serialize(node.Option)
|
||||
: null
|
||||
};
|
||||
await svc.AddAsync(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();
|
||||
}
|
||||
Reference in New Issue
Block a user