mirror of
				https://gitee.com/ThingsGateway/ThingsGateway.git
				synced 2025-11-04 17:43:58 +08:00 
			
		
		
		
	Compare commits
	
		
			5 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a879edd68b | ||
| 
						 | 
					62e0a6ee9d | ||
| 
						 | 
					765e5564d4 | ||
| 
						 | 
					10eecac19b | ||
| 
						 | 
					59241b8faa | 
@@ -6,7 +6,7 @@
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.FontAwesome" Version="9.0.2" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor" Version="9.7.4-beta07" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor" Version="9.7.4-beta09" />
 | 
			
		||||
		<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
<Project>
 | 
			
		||||
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<PluginVersion>10.8.7</PluginVersion>
 | 
			
		||||
		<ProPluginVersion>10.8.7</ProPluginVersion>
 | 
			
		||||
		<PluginVersion>10.8.12</PluginVersion>
 | 
			
		||||
		<ProPluginVersion>10.8.12</ProPluginVersion>
 | 
			
		||||
		<AuthenticationVersion>2.8.0</AuthenticationVersion>
 | 
			
		||||
		<SourceGeneratorVersion>10.8.2</SourceGeneratorVersion>
 | 
			
		||||
		<NET8Version>8.0.17</NET8Version>
 | 
			
		||||
 
 | 
			
		||||
@@ -996,4 +996,6 @@ public abstract class DeviceBase : DisposableObject, IDevice
 | 
			
		||||
        }
 | 
			
		||||
        return a => { };
 | 
			
		||||
    }
 | 
			
		||||
    public abstract ValueTask<OperResult<byte[]>> ReadAsync(object state, CancellationToken cancellationToken = default);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -466,4 +466,5 @@ public interface IDevice : IDisposable
 | 
			
		||||
    /// <param name="channel">通道</param>
 | 
			
		||||
    /// <param name="deviceLog">单独设备日志</param>
 | 
			
		||||
    void InitChannel(IChannel channel, ILog? deviceLog = null);
 | 
			
		||||
    ValueTask<OperResult<byte[]>> ReadAsync(object state, CancellationToken cancellationToken = default);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,11 @@ public interface IVariableSource
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    string RegisterAddress { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 变量地址
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    object AddressObject { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// IntervalTime
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,8 @@ public class VariableSourceClass : IVariableSource
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public IEnumerable<IVariable> VariableRuntimes => _variableRuntimes;
 | 
			
		||||
 | 
			
		||||
    public object AddressObject { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public virtual void AddVariable(IVariable variable)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -213,7 +213,19 @@ public abstract class CollectBase : DriverBase, IRpcDriver
 | 
			
		||||
    {
 | 
			
		||||
        if (IsConnected())
 | 
			
		||||
        {
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now);
 | 
			
		||||
            if (CurrentDevice.DeviceStatus == DeviceStatusEnum.OffLine)
 | 
			
		||||
            {
 | 
			
		||||
                if (IdVariableRuntimes.Any(a => a.Value.IsOnline))
 | 
			
		||||
                    CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                CurrentDevice.SetDeviceStatus(TimerX.Now);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (IsStarted)
 | 
			
		||||
        {
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -258,7 +270,7 @@ public abstract class CollectBase : DriverBase, IRpcDriver
 | 
			
		||||
            // 方法调用成功时记录日志并增加成功计数器
 | 
			
		||||
            if (LogMessage?.LogLevel <= TouchSocket.Core.LogLevel.Trace)
 | 
			
		||||
                LogMessage?.Trace(string.Format("{0} - Execute method [{1}] - Succeeded {2}", DeviceName, readVariableMethods.MethodInfo.Name, readResult.Content?.ToSystemTextJsonString()));
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, null);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
@@ -281,7 +293,7 @@ public abstract class CollectBase : DriverBase, IRpcDriver
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            readVariableMethods.LastErrorMessage = readResult.ErrorMessage;
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
@@ -329,7 +341,7 @@ public abstract class CollectBase : DriverBase, IRpcDriver
 | 
			
		||||
            // 读取成功时记录日志并增加成功计数器
 | 
			
		||||
            if (LogMessage?.LogLevel <= TouchSocket.Core.LogLevel.Trace)
 | 
			
		||||
                LogMessage?.Trace(string.Format("{0} - Collection [{1} - {2}] data succeeded {3}", DeviceName, variableSourceRead?.RegisterAddress, variableSourceRead?.Length, readResult.Content?.ToHexString(' ')));
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, null);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
@@ -352,7 +364,7 @@ public abstract class CollectBase : DriverBase, IRpcDriver
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            variableSourceRead.LastErrorMessage = readResult.ErrorMessage;
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, true, readResult.ErrorMessage);
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, null, readResult.ErrorMessage);
 | 
			
		||||
            var time = DateTime.Now;
 | 
			
		||||
            variableSourceRead.VariableRuntimes.ForEach(a => a.SetValue(null, time, isOnline: false));
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -100,7 +100,7 @@ public abstract class CollectFoundationBase : CollectBase
 | 
			
		||||
                                LogMessage?.LogWarning(exception, string.Format(AppResource.CollectFail, DeviceName, item?.RegisterAddress, item?.Length, exception.Message));
 | 
			
		||||
                        }
 | 
			
		||||
                        item.LastErrorMessage = exception.Message;
 | 
			
		||||
                        CurrentDevice.SetDeviceStatus(TimerX.Now, true, exception.Message);
 | 
			
		||||
                        CurrentDevice.SetDeviceStatus(TimerX.Now, null, exception.Message);
 | 
			
		||||
                        var time = DateTime.Now;
 | 
			
		||||
                        item.VariableRuntimes.ForEach(a => a.SetValue(null, time, isOnline: false));
 | 
			
		||||
                    }
 | 
			
		||||
@@ -112,7 +112,7 @@ public abstract class CollectFoundationBase : CollectBase
 | 
			
		||||
                                LogMessage?.LogWarning(exception, string.Format(AppResource.MethodFail, DeviceName, item.MethodInfo.Name, exception.Message));
 | 
			
		||||
                        }
 | 
			
		||||
                        item.LastErrorMessage = exception.Message;
 | 
			
		||||
                        CurrentDevice.SetDeviceStatus(TimerX.Now, true, exception.Message);
 | 
			
		||||
                        CurrentDevice.SetDeviceStatus(TimerX.Now, null, exception.Message);
 | 
			
		||||
                        var time = DateTime.Now;
 | 
			
		||||
                        item.Variable.SetValue(null, time, isOnline: false);
 | 
			
		||||
                    }
 | 
			
		||||
@@ -137,8 +137,9 @@ public abstract class CollectFoundationBase : CollectBase
 | 
			
		||||
 | 
			
		||||
            if (cancellationToken.IsCancellationRequested)
 | 
			
		||||
                return new(new OperationCanceledException());
 | 
			
		||||
 | 
			
		||||
            // 从协议读取数据
 | 
			
		||||
            var read = await FoundationDevice.ReadAsync(variableSourceRead.RegisterAddress, variableSourceRead.Length, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
            var read = await FoundationDevice.ReadAsync(variableSourceRead.AddressObject, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            // 如果读取成功且有有效内容,则解析结构化内容
 | 
			
		||||
            if (read.IsSuccess)
 | 
			
		||||
 
 | 
			
		||||
@@ -282,7 +282,7 @@ public abstract class DriverBase : DisposableObject, IDriver
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 设置设备状态为当前时间
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now);
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ public class VariableSourceRead : IVariableSource
 | 
			
		||||
    /// 读取地址
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string RegisterAddress { get; set; }
 | 
			
		||||
    public object AddressObject { get; set; }
 | 
			
		||||
 | 
			
		||||
    public string IntervalTime { get; set; }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,11 +15,8 @@ namespace ThingsGateway.Gateway.Application;
 | 
			
		||||
public sealed class ChannelThreadOptions : IConfigurableOptions
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    public int MinCycleInterval { get; set; } = 10;
 | 
			
		||||
    public int MaxCycleInterval { get; set; } = 200;
 | 
			
		||||
    public int CheckInterval { get; set; } = 1800000;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public int MaxChannelCount { get; set; } = 1000;
 | 
			
		||||
    public int MaxDeviceCount { get; set; } = 1000;
 | 
			
		||||
    public int MaxVariableCount { get; set; } = 1000000;
 | 
			
		||||
 
 | 
			
		||||
@@ -30,60 +30,6 @@ namespace ThingsGateway.Gateway.Application;
 | 
			
		||||
internal sealed class DeviceThreadManage : IAsyncDisposable, IDeviceThreadManage
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    #region 动态配置
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 线程等待间隔时间
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static volatile int CycleInterval = ManageHelper.ChannelThreadOptions.MaxCycleInterval;
 | 
			
		||||
 | 
			
		||||
    static DeviceThreadManage()
 | 
			
		||||
    {
 | 
			
		||||
        Task.Factory.StartNew(SetCycleInterval, TaskCreationOptions.LongRunning);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static async Task SetCycleInterval()
 | 
			
		||||
    {
 | 
			
		||||
        var appLifetime = App.RootServices!.GetService<IHostApplicationLifetime>()!;
 | 
			
		||||
        var hardwareJob = GlobalData.HardwareJob;
 | 
			
		||||
 | 
			
		||||
        List<float> cpus = new();
 | 
			
		||||
        while (!appLifetime.ApplicationStopping.IsCancellationRequested)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (hardwareJob?.HardwareInfo?.MachineInfo?.CpuRate == null) continue;
 | 
			
		||||
                cpus.Add((float)(hardwareJob.HardwareInfo.MachineInfo.CpuRate * 100));
 | 
			
		||||
                if (cpus.Count == 1 || cpus.Count > 5)
 | 
			
		||||
                {
 | 
			
		||||
                    var avg = cpus.Average();
 | 
			
		||||
                    cpus.RemoveAt(0);
 | 
			
		||||
                    //Console.WriteLine($"CPU平均值:{avg}");
 | 
			
		||||
                    if (avg > 80)
 | 
			
		||||
                    {
 | 
			
		||||
                        CycleInterval = Math.Max(CycleInterval, (int)(ManageHelper.ChannelThreadOptions.MaxCycleInterval * avg / 100));
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (avg < 50)
 | 
			
		||||
                    {
 | 
			
		||||
                        CycleInterval = Math.Min(CycleInterval, ManageHelper.ChannelThreadOptions.MinCycleInterval);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (OperationCanceledException)
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                NewLife.Log.XTrace.WriteException(ex);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(30000, appLifetime?.ApplicationStopping ?? default).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #endregion 动态配置
 | 
			
		||||
    Microsoft.Extensions.Logging.ILogger? _logger;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
    <span style="color:var(--bs-body-color)" class="text-h6 mb-2">@GatewayLocalizer["DeviceList"]</span>
 | 
			
		||||
 | 
			
		||||
    <ContextMenuZone title="Right click operation">
 | 
			
		||||
        <TreeView TItem="ChannelDeviceTreeItem" Items="Items" ShowIcon="false" ShowSearch IsAccordion=false IsVirtualize="true" OnTreeItemClick="OnTreeItemClick" OnSearchAsync="OnClickSearch" ModelEqualityComparer=ModelEqualityComparer>
 | 
			
		||||
        <TreeView TItem="ChannelDeviceTreeItem" Items="Items" ShowIcon="false" ShowSearch IsAccordion=false IsVirtualize="true" OnTreeItemClick="OnTreeItemClick" OnSearchAsync="OnClickSearch"  ModelEqualityComparer=ModelEqualityComparer>
 | 
			
		||||
 | 
			
		||||
        </TreeView>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1469,27 +1469,22 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
 | 
			
		||||
 | 
			
		||||
    private static bool ModelEqualityComparer(ChannelDeviceTreeItem x, ChannelDeviceTreeItem y)
 | 
			
		||||
    {
 | 
			
		||||
        if (x.ChannelDevicePluginType == y.ChannelDevicePluginType)
 | 
			
		||||
        {
 | 
			
		||||
            if (x.ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Device)
 | 
			
		||||
            {
 | 
			
		||||
                return x.DeviceRuntime.Id == y.DeviceRuntime.Id; ;
 | 
			
		||||
            }
 | 
			
		||||
            else if (x.ChannelDevicePluginType == ChannelDevicePluginTypeEnum.PluginType)
 | 
			
		||||
            {
 | 
			
		||||
                return x.PluginType == y.PluginType;
 | 
			
		||||
        if (x.ChannelDevicePluginType != y.ChannelDevicePluginType)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            else if (x.ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Channel)
 | 
			
		||||
            {
 | 
			
		||||
        switch (x.ChannelDevicePluginType)
 | 
			
		||||
        {
 | 
			
		||||
            case ChannelDevicePluginTypeEnum.Device:
 | 
			
		||||
                return x.DeviceRuntime.Id == y.DeviceRuntime.Id;
 | 
			
		||||
            case ChannelDevicePluginTypeEnum.PluginType:
 | 
			
		||||
                return x.PluginType == y.PluginType;
 | 
			
		||||
            case ChannelDevicePluginTypeEnum.Channel:
 | 
			
		||||
                return x.ChannelRuntime.Id == y.ChannelRuntime.Id;
 | 
			
		||||
            }
 | 
			
		||||
            else if (x.ChannelDevicePluginType == ChannelDevicePluginTypeEnum.PluginName)
 | 
			
		||||
            {
 | 
			
		||||
            case ChannelDevicePluginTypeEnum.PluginName:
 | 
			
		||||
                return x.PluginName == y.PluginName;
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    private bool Disposed;
 | 
			
		||||
    protected override ValueTask DisposeAsync(bool disposing)
 | 
			
		||||
 
 | 
			
		||||
@@ -31,27 +31,22 @@ public class ChannelDeviceTreeItem : IEqualityComparer<ChannelDeviceTreeItem>
 | 
			
		||||
    {
 | 
			
		||||
        if (obj is ChannelDeviceTreeItem item)
 | 
			
		||||
        {
 | 
			
		||||
            if (ChannelDevicePluginType == item.ChannelDevicePluginType)
 | 
			
		||||
            if (ChannelDevicePluginType != item.ChannelDevicePluginType)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            switch (ChannelDevicePluginType)
 | 
			
		||||
            {
 | 
			
		||||
                if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Device)
 | 
			
		||||
                {
 | 
			
		||||
                case ChannelDevicePluginTypeEnum.Device:
 | 
			
		||||
                    return DeviceRuntime == item.DeviceRuntime;
 | 
			
		||||
                }
 | 
			
		||||
                else if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.PluginType)
 | 
			
		||||
                {
 | 
			
		||||
                case ChannelDevicePluginTypeEnum.PluginType:
 | 
			
		||||
                    return PluginType == item.PluginType;
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
                else if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Channel)
 | 
			
		||||
                {
 | 
			
		||||
                case ChannelDevicePluginTypeEnum.Channel:
 | 
			
		||||
                    return ChannelRuntime == item.ChannelRuntime;
 | 
			
		||||
                }
 | 
			
		||||
                else if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.PluginName)
 | 
			
		||||
                {
 | 
			
		||||
                case ChannelDevicePluginTypeEnum.PluginName:
 | 
			
		||||
                    return PluginName == item.PluginName;
 | 
			
		||||
                }
 | 
			
		||||
                default:
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,10 +6,6 @@
 | 
			
		||||
        "Url": "/",
 | 
			
		||||
        "Text": "首页"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "Url": "/des",
 | 
			
		||||
        "Text": "DES"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "Text": "Modbus",
 | 
			
		||||
        "Items": [
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ public class Dlt645_2007Master : DtuServiceDeviceBase
 | 
			
		||||
    /// <param name="dateTime">时间</param>
 | 
			
		||||
    /// <param name="cancellationToken">取消令箭</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public async ValueTask<OperResult> BroadcastTimeAsync(DateTime dateTime, CancellationToken cancellationToken = default)
 | 
			
		||||
    public ValueTask<OperResult> BroadcastTimeAsync(DateTime dateTime, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
@@ -53,40 +53,30 @@ public class Dlt645_2007Master : DtuServiceDeviceBase
 | 
			
		||||
            dAddress.Station = str.HexStringToBytes();
 | 
			
		||||
            dAddress.DataId = "999999999999".HexStringToBytes();
 | 
			
		||||
 | 
			
		||||
            return await Dlt645SendAsync(dAddress, ControlCode.BroadcastTime, FEHead, cancellationToken: cancellationToken).ConfigureAwait(false);
 | 
			
		||||
            return Dlt645SendAsync(dAddress, ControlCode.BroadcastTime, FEHead, cancellationToken: cancellationToken);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult(ex);
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async ValueTask<OperResult<byte[]>> Dlt645RequestAsync(Dlt645_2007Address dAddress, ControlCode controlCode, string feHead, byte[] codes = default, string[] datas = default, CancellationToken cancellationToken = default)
 | 
			
		||||
    public ValueTask<OperResult<byte[]>> Dlt645RequestAsync(Dlt645_2007Address dAddress, ControlCode controlCode, string feHead, byte[] codes = default, string[] datas = default, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return await SendThenReturnAsync(GetSendMessage(dAddress, controlCode, feHead, codes, datas), cancellationToken).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return SendThenReturnAsync(GetSendMessage(dAddress, controlCode, feHead, codes, datas), cancellationToken);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async ValueTask<OperResult> Dlt645SendAsync(Dlt645_2007Address dAddress, ControlCode controlCode, string feHead, byte[] codes = default, string[] datas = default, CancellationToken cancellationToken = default)
 | 
			
		||||
    public ValueTask<OperResult> Dlt645SendAsync(Dlt645_2007Address dAddress, ControlCode controlCode, string feHead, byte[] codes = default, string[] datas = default, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            return await SendAsync(GetSendMessage(dAddress, controlCode, feHead, codes, datas), cancellationToken).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
        return SendAsync(GetSendMessage(dAddress, controlCode, feHead, codes, datas), cancellationToken);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -147,7 +137,7 @@ public class Dlt645_2007Master : DtuServiceDeviceBase
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, string defaultIntervalTime)
 | 
			
		||||
    {
 | 
			
		||||
        return PackHelper.LoadSourceRead<T>(this, deviceVariables, maxPack, defaultIntervalTime);
 | 
			
		||||
        return PackHelper.LoadSourceRead<T>(this, deviceVariables, maxPack, Station, defaultIntervalTime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -163,7 +153,19 @@ public class Dlt645_2007Master : DtuServiceDeviceBase
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult<byte[]>(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public override ValueTask<OperResult<byte[]>> ReadAsync(object state, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        if (state is Dlt645_2007Address dlt645_2007Address)
 | 
			
		||||
        {
 | 
			
		||||
            return Dlt645RequestAsync(dlt645_2007Address, ControlCode.Read, FEHead, cancellationToken: cancellationToken);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw new ArgumentException("State must be of type Dlt645_2007Address", nameof(state));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 读取通信地址
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -231,16 +233,16 @@ public class Dlt645_2007Master : DtuServiceDeviceBase
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override async ValueTask<OperResult> WriteAsync(string address, string value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
 | 
			
		||||
    public override ValueTask<OperResult> WriteAsync(string address, string value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            string[] strArray = value.SplitStringBySemicolon();
 | 
			
		||||
            return await WriteAsync(address, value, bitConverter, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
            return WriteAsync(address, value, bitConverter, cancellationToken);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,10 @@ internal static class PackHelper
 | 
			
		||||
    /// <param name="device"></param>
 | 
			
		||||
    /// <param name="deviceVariables"></param>
 | 
			
		||||
    /// <param name="maxPack">最大打包长度</param>
 | 
			
		||||
    /// <param name="station">station</param>
 | 
			
		||||
    /// <param name="defaultIntervalTime">默认间隔时间</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public static List<T> LoadSourceRead<T>(IDevice device, IEnumerable<IVariable> deviceVariables, int maxPack, string defaultIntervalTime) where T : IVariableSource, new()
 | 
			
		||||
    public static List<T> LoadSourceRead<T>(IDevice device, IEnumerable<IVariable> deviceVariables, int maxPack, string station, string defaultIntervalTime) where T : IVariableSource, new()
 | 
			
		||||
    {
 | 
			
		||||
        var byteConverter = device.ThingsGatewayBitConverter;
 | 
			
		||||
        var result = new List<T>();
 | 
			
		||||
@@ -42,6 +43,7 @@ internal static class PackHelper
 | 
			
		||||
            var r = new T()
 | 
			
		||||
            {
 | 
			
		||||
                RegisterAddress = item.Key!,
 | 
			
		||||
                AddressObject = Dlt645_2007Address.ParseFrom(item.Key, station),
 | 
			
		||||
                Length = 1,
 | 
			
		||||
                IntervalTime = string.IsNullOrWhiteSpace(item.FirstOrDefault().IntervalTime) ? defaultIntervalTime : item.FirstOrDefault().IntervalTime,
 | 
			
		||||
            };
 | 
			
		||||
 
 | 
			
		||||
@@ -167,6 +167,7 @@ public static class PackHelper
 | 
			
		||||
                IntervalTime = intervalTime,
 | 
			
		||||
                // 将当前组打包地址中的起始地址作为实际打包报文中的起始地址
 | 
			
		||||
                RegisterAddress = startAddress.ToString(),
 | 
			
		||||
                AddressObject = new ModbusAddress(startAddress) { Length = (ushort)sourceLen },
 | 
			
		||||
                Length = sourceLen.ToInt()
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -98,31 +98,64 @@ public partial class ModbusMaster : DtuServiceDeviceBase, IModbusAddress
 | 
			
		||||
        return PackHelper.LoadSourceRead<T>(this, deviceVariables, maxPack, defaultIntervalTime, Station);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<OperResult<byte[]>> ModbusRequestAsync(ModbusAddress mAddress, bool read, CancellationToken cancellationToken = default)
 | 
			
		||||
    public override ValueTask<OperResult<byte[]>> ReadAsync(object state, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return await SendThenReturnAsync(GetSendMessage(mAddress, read),
 | 
			
		||||
             cancellationToken).ConfigureAwait(false);
 | 
			
		||||
            if (state is ModbusAddress mAddress)
 | 
			
		||||
            {
 | 
			
		||||
                return ModbusReadAsync(mAddress, cancellationToken);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException("State must be of type ModbusAddress", nameof(state));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult<byte[]>(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ValueTask<OperResult<byte[]>> ModbusReadAsync(ModbusAddress mAddress, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return SendThenReturnAsync(GetSendMessage(mAddress, true),
 | 
			
		||||
             cancellationToken);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult<byte[]>(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public ValueTask<OperResult<byte[]>> ModbusRequestAsync(ModbusAddress mAddress, bool read, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return SendThenReturnAsync(GetSendMessage(mAddress, read),
 | 
			
		||||
             cancellationToken);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult<byte[]>(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override async ValueTask<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
 | 
			
		||||
    public override ValueTask<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var mAddress = GetModbusAddress(address, Station);
 | 
			
		||||
            mAddress.Length = (ushort)length;
 | 
			
		||||
            return await ModbusRequestAsync(mAddress, true, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
            return ModbusRequestAsync(mAddress, true, cancellationToken);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult<byte[]>(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -310,6 +310,34 @@ public class ModbusSlave : DeviceBase, IModbusAddress
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult<byte[]>(result));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override ValueTask<OperResult<byte[]>> ReadAsync(object state, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            if (state is ModbusAddress mAddress)
 | 
			
		||||
            {
 | 
			
		||||
                var result = ModbusRequest(mAddress, true, cancellationToken);
 | 
			
		||||
                if (result.IsSuccess)
 | 
			
		||||
                {
 | 
			
		||||
                    return EasyValueTask.FromResult(new OperResult<byte[]>() { Content = result.Content.ToArray() });
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    return EasyValueTask.FromResult(new OperResult<byte[]>(result));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException("State must be of type ModbusAddress", nameof(state));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult<byte[]>(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public virtual ModbusAddress GetModbusAddress(string address, byte? station, bool isCache = true)
 | 
			
		||||
    {
 | 
			
		||||
        var mAddress = ModbusAddress.ParseFrom(address, station, isCache);
 | 
			
		||||
 
 | 
			
		||||
@@ -230,6 +230,7 @@ internal static class PackHelper
 | 
			
		||||
            {
 | 
			
		||||
                IntervalTime = intervalTime, // 设置时间戳
 | 
			
		||||
                RegisterAddress = tempAddresses.OrderBy(it => it.AddressStart).First().ToString(), // 获取地址并按地址排序
 | 
			
		||||
                AddressObject = new SiemensS7Address(tempAddresses.OrderBy(it => it.AddressStart).First()) { Length = sourceLen },
 | 
			
		||||
                Length = sourceLen // 设置源长度
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -298,6 +298,26 @@ public partial class SiemensS7Master : DeviceBase
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override ValueTask<OperResult<byte[]>> ReadAsync(object state, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            if (state is SiemensS7Address sAddress)
 | 
			
		||||
            {
 | 
			
		||||
                return S7ReadAsync([sAddress], cancellationToken);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException("State must be of type SiemensS7Address", nameof(state));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return EasyValueTask.FromResult(new OperResult<byte[]>(ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override async ValueTask<OperResult> WriteAsync(string address, byte[] value, DataTypeEnum dataType, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ namespace ThingsGateway.Plugin.QuestDB;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// QuestDBProducer
 | 
			
		||||
/// </summary>
 | 
			
		||||
public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableModel<QuestDBHistoryValue>, IDBHistoryValueService
 | 
			
		||||
public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>, IDBHistoryValueService
 | 
			
		||||
{
 | 
			
		||||
    internal readonly RealDBProducerProperty _driverPropertys = new();
 | 
			
		||||
    private readonly QuestDBProducerVariableProperty _variablePropertys = new();
 | 
			
		||||
 
 | 
			
		||||
@@ -23,11 +23,11 @@ namespace ThingsGateway.Plugin.QuestDB;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// RabbitMQProducer
 | 
			
		||||
/// </summary>
 | 
			
		||||
public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableModel<QuestDBHistoryValue>
 | 
			
		||||
public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>
 | 
			
		||||
{
 | 
			
		||||
    private TypeAdapterConfig _config;
 | 
			
		||||
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModel(IEnumerable<CacheDBItem<QuestDBHistoryValue>> item, CancellationToken cancellationToken)
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModel(IEnumerable<CacheDBItem<VariableBasicData>> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return UpdateVarModel(item.Select(a => a.Value).OrderBy(a => a.Id), cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
@@ -41,7 +41,7 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
 | 
			
		||||
        UpdateVariable(variableRuntime, variable);
 | 
			
		||||
        base.VariableChange(variableRuntime, variable);
 | 
			
		||||
    }
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModels(IEnumerable<QuestDBHistoryValue> item, CancellationToken cancellationToken)
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModels(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return UpdateVarModel(item, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
@@ -56,18 +56,18 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
 | 
			
		||||
 | 
			
		||||
            foreach (var group in varGroup)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<List<QuestDBHistoryValue>>(group.Adapt<List<QuestDBHistoryValue>>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.ToList()));
 | 
			
		||||
            }
 | 
			
		||||
            foreach (var variable in varList)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<QuestDBHistoryValue>(variable.Adapt<QuestDBHistoryValue>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var variable in variables)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<QuestDBHistoryValue>(variable.Adapt<QuestDBHistoryValue>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -78,15 +78,15 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
 | 
			
		||||
        if (_driverPropertys.GroupUpdate && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            AddQueueVarModel(new CacheDBItem<List<QuestDBHistoryValue>>(variableRuntimeGroup.Adapt<List<QuestDBHistoryValue>>(_config)));
 | 
			
		||||
            AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>(_config)));
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            AddQueueVarModel(new CacheDBItem<QuestDBHistoryValue>(variableRuntime.Adapt<QuestDBHistoryValue>(_config)));
 | 
			
		||||
            AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private async ValueTask<OperResult> UpdateVarModel(IEnumerable<QuestDBHistoryValue> item, CancellationToken cancellationToken)
 | 
			
		||||
    private async ValueTask<OperResult> UpdateVarModel(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        var result = await InserableAsync(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true).ToList(), cancellationToken).ConfigureAwait(false);
 | 
			
		||||
        if (success != result.IsSuccess)
 | 
			
		||||
@@ -101,7 +101,7 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
 | 
			
		||||
 | 
			
		||||
    #region 方法
 | 
			
		||||
 | 
			
		||||
    private async ValueTask<OperResult> InserableAsync(List<QuestDBHistoryValue> dbInserts, CancellationToken cancellationToken)
 | 
			
		||||
    private async ValueTask<OperResult> InserableAsync(List<VariableBasicData> dbInserts, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
@@ -118,8 +118,8 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
 | 
			
		||||
            {
 | 
			
		||||
                Stopwatch stopwatch = new();
 | 
			
		||||
                stopwatch.Start();
 | 
			
		||||
 | 
			
		||||
                var result = await _db.Insertable(dbInserts).AS(_driverPropertys.TableName).ExecuteCommandAsync(cancellationToken).ConfigureAwait(false);//不要加分表
 | 
			
		||||
                var data = dbInserts.Adapt<List<QuestDBHistoryValue>>();
 | 
			
		||||
                var result = await _db.Insertable(data).AS(_driverPropertys.TableName).ExecuteCommandAsync(cancellationToken).ConfigureAwait(false);//不要加分表
 | 
			
		||||
                stopwatch.Stop();
 | 
			
		||||
 | 
			
		||||
                //var result = await db.Insertable(dbInserts).SplitTable().ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ namespace ThingsGateway.Plugin.SqlDB;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// SqlDBProducer
 | 
			
		||||
/// </summary>
 | 
			
		||||
public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<SQLHistoryValue>, IDBHistoryValueService
 | 
			
		||||
public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>, IDBHistoryValueService
 | 
			
		||||
{
 | 
			
		||||
    internal readonly SqlDBProducerProperty _driverPropertys = new();
 | 
			
		||||
    private readonly SqlDBProducerVariableProperty _variablePropertys = new();
 | 
			
		||||
@@ -236,7 +236,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
                var varList = RealTimeVariables.ToListWithDequeue();
 | 
			
		||||
                if (varList.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    var result = await UpdateAsync(varList.Adapt<List<SQLRealValue>>(), cancellationToken).ConfigureAwait(false);
 | 
			
		||||
                    var result = await UpdateAsync(varList, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
                    if (success != result.IsSuccess)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!result.IsSuccess)
 | 
			
		||||
 
 | 
			
		||||
@@ -24,13 +24,13 @@ namespace ThingsGateway.Plugin.SqlDB;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// SqlDBProducer
 | 
			
		||||
/// </summary>
 | 
			
		||||
public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<SQLHistoryValue>
 | 
			
		||||
public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>
 | 
			
		||||
{
 | 
			
		||||
    private TypeAdapterConfig _config;
 | 
			
		||||
    private volatile bool _initRealData;
 | 
			
		||||
    private ConcurrentDictionary<long, VariableBasicData> RealTimeVariables { get; } = new ConcurrentDictionary<long, VariableBasicData>();
 | 
			
		||||
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModel(IEnumerable<CacheDBItem<SQLHistoryValue>> item, CancellationToken cancellationToken)
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModel(IEnumerable<CacheDBItem<VariableBasicData>> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return UpdateVarModel(item.Select(a => a.Value).OrderBy(a => a.Id), cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
@@ -48,7 +48,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
        UpdateVariable(variableRuntime, variable);
 | 
			
		||||
        base.VariableChange(variableRuntime, variable);
 | 
			
		||||
    }
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModels(IEnumerable<SQLHistoryValue> item, CancellationToken cancellationToken)
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModels(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return UpdateVarModel(item, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
@@ -62,18 +62,18 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
 | 
			
		||||
            foreach (var group in varGroup)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<List<SQLHistoryValue>>(group.Adapt<List<SQLHistoryValue>>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.ToList()));
 | 
			
		||||
            }
 | 
			
		||||
            foreach (var variable in varList)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<SQLHistoryValue>(variable.Adapt<SQLHistoryValue>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var variable in variables)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<SQLHistoryValue>(variable.Adapt<SQLHistoryValue>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -85,12 +85,12 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
            if (_driverPropertys.GroupUpdate && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<List<SQLHistoryValue>>(variableRuntimeGroup.Adapt<List<SQLHistoryValue>>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>(_config)));
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<SQLHistoryValue>(variableRuntime.Adapt<SQLHistoryValue>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -101,7 +101,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private async ValueTask<OperResult> UpdateVarModel(IEnumerable<SQLHistoryValue> item, CancellationToken cancellationToken)
 | 
			
		||||
    private async ValueTask<OperResult> UpdateVarModel(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        var result = await InserableAsync(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true).ToList(), cancellationToken).ConfigureAwait(false);
 | 
			
		||||
        if (success != result.IsSuccess)
 | 
			
		||||
@@ -116,7 +116,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
 | 
			
		||||
    #region 方法
 | 
			
		||||
 | 
			
		||||
    private async ValueTask<OperResult> InserableAsync(List<SQLHistoryValue> dbInserts, CancellationToken cancellationToken)
 | 
			
		||||
    private async ValueTask<OperResult> InserableAsync(List<VariableBasicData> dbInserts, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
@@ -134,8 +134,8 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
            {
 | 
			
		||||
                Stopwatch stopwatch = new();
 | 
			
		||||
                stopwatch.Start();
 | 
			
		||||
                var result = await _db.Fastest<SQLHistoryValue>().PageSize(50000).SplitTable().BulkCopyAsync(dbInserts).ConfigureAwait(false);
 | 
			
		||||
                //var result = await db.Insertable(dbInserts).SplitTable().ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
                var data = dbInserts.Adapt<List<SQLHistoryValue>>(_config);
 | 
			
		||||
                var result = await _db.Fastest<SQLHistoryValue>().PageSize(50000).SplitTable().BulkCopyAsync(data).ConfigureAwait(false);
 | 
			
		||||
                stopwatch.Stop();
 | 
			
		||||
                if (result > 0)
 | 
			
		||||
                {
 | 
			
		||||
@@ -152,7 +152,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async ValueTask<OperResult> UpdateAsync(List<SQLRealValue> datas, CancellationToken cancellationToken)
 | 
			
		||||
    private async ValueTask<OperResult> UpdateAsync(List<VariableBasicData> datas, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
@@ -190,7 +190,8 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
 | 
			
		||||
                        Stopwatch stopwatch = new();
 | 
			
		||||
                        stopwatch.Start();
 | 
			
		||||
 | 
			
		||||
                        var result = await _db.Fastest<SQLRealValue>().AS(_driverPropertys.ReadDBTableName).PageSize(100000).BulkUpdateAsync(datas).ConfigureAwait(false);
 | 
			
		||||
                        var data = datas.Adapt<List<SQLRealValue>>(_config);
 | 
			
		||||
                        var result = await _db.Fastest<SQLRealValue>().AS(_driverPropertys.ReadDBTableName).PageSize(100000).BulkUpdateAsync(data).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                        stopwatch.Stop();
 | 
			
		||||
                        if (result > 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheVariableModel<Histor
 | 
			
		||||
 | 
			
		||||
    protected override async Task InitChannelAsync(IChannel? channel, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        _db = BusinessDatabaseUtil.GetDb(_driverPropertys.DbType, _driverPropertys.BigTextConnectStr);
 | 
			
		||||
        _db = BusinessDatabaseUtil.GetDb((DbType)_driverPropertys.DbType, _driverPropertys.BigTextConnectStr);
 | 
			
		||||
 | 
			
		||||
        _config.ForType<AlarmVariable, HistoryAlarm>().Map(dest => dest.Id, (src) => CommonUtils.GetSingleId());
 | 
			
		||||
        GlobalData.AlarmChangedEvent -= AlarmWorker_OnAlarmChanged;
 | 
			
		||||
@@ -112,7 +112,7 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheVariableModel<Histor
 | 
			
		||||
 | 
			
		||||
    internal ISugarQueryable<HistoryAlarm> Query(DBHistoryAlarmPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        using var db = BusinessDatabaseUtil.GetDb(_driverPropertys.DbType, _driverPropertys.BigTextConnectStr);
 | 
			
		||||
        using var db = BusinessDatabaseUtil.GetDb((DbType)_driverPropertys.DbType, _driverPropertys.BigTextConnectStr);
 | 
			
		||||
        var query = db.Queryable<HistoryAlarm>().AS(_driverPropertys.TableName)
 | 
			
		||||
                             .WhereIF(input.StartTime != null, a => a.EventTime >= input.StartTime)
 | 
			
		||||
                           .WhereIF(input.EndTime != null, a => a.EventTime <= input.EndTime)
 | 
			
		||||
@@ -132,7 +132,7 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheVariableModel<Histor
 | 
			
		||||
 | 
			
		||||
    internal async Task<QueryData<HistoryAlarm>> QueryData(QueryPageOptions option)
 | 
			
		||||
    {
 | 
			
		||||
        using var db = BusinessDatabaseUtil.GetDb(_driverPropertys.DbType, _driverPropertys.BigTextConnectStr);
 | 
			
		||||
        using var db = BusinessDatabaseUtil.GetDb((DbType)_driverPropertys.DbType, _driverPropertys.BigTextConnectStr);
 | 
			
		||||
        var ret = new QueryData<HistoryAlarm>()
 | 
			
		||||
        {
 | 
			
		||||
            IsSorted = option.SortOrder != SortOrder.Unset,
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ using Mapster;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation;
 | 
			
		||||
using ThingsGateway.NewLife.Threading;
 | 
			
		||||
using ThingsGateway.Plugin.DB;
 | 
			
		||||
 | 
			
		||||
using TouchSocket.Core;
 | 
			
		||||
 | 
			
		||||
@@ -56,38 +56,6 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheVariableModel<Histor
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async ValueTask<OperResult> InserableAsync(List<HistoryAlarm> dbInserts, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            int result = 0;
 | 
			
		||||
            //.SplitTable()
 | 
			
		||||
            Stopwatch stopwatch = new();
 | 
			
		||||
            stopwatch.Start();
 | 
			
		||||
 | 
			
		||||
            if (_db.CurrentConnectionConfig.DbType == SqlSugar.DbType.QuestDB)
 | 
			
		||||
                result = await _db.Insertable(dbInserts).AS(_driverPropertys.TableName).ExecuteCommandAsync(cancellationToken).ConfigureAwait(false);//不要加分表
 | 
			
		||||
            else
 | 
			
		||||
                result = await _db.Fastest<HistoryAlarm>().AS(_driverPropertys.TableName).PageSize(50000).BulkCopyAsync(dbInserts).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            stopwatch.Stop();
 | 
			
		||||
            //var result = await db.Insertable(dbInserts).SplitTable().ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
            if (result > 0)
 | 
			
		||||
            {
 | 
			
		||||
                CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
                LogMessage?.Trace($"Count:{dbInserts.Count},watchTime:  {stopwatch.ElapsedMilliseconds} ms");
 | 
			
		||||
            }
 | 
			
		||||
            return OperResult.Success;
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, true);
 | 
			
		||||
            return new OperResult(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async ValueTask<OperResult> UpdateT(IEnumerable<HistoryAlarm> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        var result = await InserableAsync(item.ToList(), cancellationToken).ConfigureAwait(false);
 | 
			
		||||
@@ -100,4 +68,51 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheVariableModel<Histor
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async ValueTask<OperResult> InserableAsync(List<HistoryAlarm> dbInserts, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            _db.Ado.CancellationToken = cancellationToken;
 | 
			
		||||
            if (!_driverPropertys.BigTextScriptHistoryTable.IsNullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                var getDeviceModel = CSharpScriptEngineExtension.Do<DynamicSQLBase>(_driverPropertys.BigTextScriptHistoryTable);
 | 
			
		||||
 | 
			
		||||
                getDeviceModel.Logger = LogMessage;
 | 
			
		||||
 | 
			
		||||
                await getDeviceModel.DBInsertable(_db, dbInserts, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                int result = 0;
 | 
			
		||||
                //.SplitTable()
 | 
			
		||||
                Stopwatch stopwatch = new();
 | 
			
		||||
                stopwatch.Start();
 | 
			
		||||
 | 
			
		||||
                if (_db.CurrentConnectionConfig.DbType == SqlSugar.DbType.QuestDB)
 | 
			
		||||
                    result = await _db.Insertable(dbInserts).AS(_driverPropertys.TableName).ExecuteCommandAsync(cancellationToken).ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    result = await _db.Fastest<HistoryAlarm>().AS(_driverPropertys.TableName).PageSize(50000).BulkCopyAsync(dbInserts).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                stopwatch.Stop();
 | 
			
		||||
                //var result = await db.Insertable(dbInserts).SplitTable().ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
                if (result > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    LogMessage?.Trace($"Count:{dbInserts.Count},watchTime:  {stopwatch.ElapsedMilliseconds} ms");
 | 
			
		||||
                }
 | 
			
		||||
                return OperResult.Success;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            return OperResult.Success;
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult(ex);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,8 @@ using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
using ThingsGateway.Plugin.SqlDB;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Plugin.SqlHistoryAlarm;
 | 
			
		||||
 | 
			
		||||
@@ -23,15 +24,21 @@ public class SqlHistoryAlarmProperty : BusinessPropertyWithCache
 | 
			
		||||
{
 | 
			
		||||
    [DynamicProperty]
 | 
			
		||||
    public DbType DbType { get; set; } = DbType.SqlServer;
 | 
			
		||||
 | 
			
		||||
    [DynamicProperty]
 | 
			
		||||
    [Required]
 | 
			
		||||
    public string TableName { get; set; } = "historyAlarm";
 | 
			
		||||
    [DynamicProperty]
 | 
			
		||||
    [Required]
 | 
			
		||||
    [AutoGenerateColumn(ComponentType = typeof(Textarea), Rows = 1)]
 | 
			
		||||
    public string BigTextConnectStr { get; set; } = "server=.;uid=sa;pwd=111111;database=test;";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 历史表脚本
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [DynamicProperty]
 | 
			
		||||
    [Required]
 | 
			
		||||
    public string TableName { get; set; } = "historyAlarm";
 | 
			
		||||
    [AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
 | 
			
		||||
    public string? BigTextScriptHistoryTable { get; set; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public override bool OnlineFilter { get; set; } = false;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ namespace ThingsGateway.Plugin.TDengineDB;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// TDengineDBProducer
 | 
			
		||||
/// </summary>
 | 
			
		||||
public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableModel<TDengineDBHistoryValue>, IDBHistoryValueService
 | 
			
		||||
public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>, IDBHistoryValueService
 | 
			
		||||
{
 | 
			
		||||
    internal readonly RealDBProducerProperty _driverPropertys = new()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,11 +26,11 @@ namespace ThingsGateway.Plugin.TDengineDB;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// RabbitMQProducer
 | 
			
		||||
/// </summary>
 | 
			
		||||
public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableModel<TDengineDBHistoryValue>
 | 
			
		||||
public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>
 | 
			
		||||
{
 | 
			
		||||
    private TypeAdapterConfig _config;
 | 
			
		||||
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModel(IEnumerable<CacheDBItem<TDengineDBHistoryValue>> item, CancellationToken cancellationToken)
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModel(IEnumerable<CacheDBItem<VariableBasicData>> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return UpdateVarModel(item.Select(a => a.Value).OrderBy(a => a.Id), cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
@@ -46,7 +46,7 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableM
 | 
			
		||||
        UpdateVariable(variableRuntime, variable);
 | 
			
		||||
        base.VariableChange(variableRuntime, variable);
 | 
			
		||||
    }
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModels(IEnumerable<TDengineDBHistoryValue> item, CancellationToken cancellationToken)
 | 
			
		||||
    protected override ValueTask<OperResult> UpdateVarModels(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return UpdateVarModel(item, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
@@ -59,18 +59,18 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableM
 | 
			
		||||
 | 
			
		||||
            foreach (var group in varGroup)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<List<TDengineDBHistoryValue>>(group.Adapt<List<TDengineDBHistoryValue>>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.ToList()));
 | 
			
		||||
            }
 | 
			
		||||
            foreach (var variable in varList)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<TDengineDBHistoryValue>(variable.Adapt<TDengineDBHistoryValue>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var variable in variables)
 | 
			
		||||
            {
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<TDengineDBHistoryValue>(variable.Adapt<TDengineDBHistoryValue>(_config)));
 | 
			
		||||
                AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -80,15 +80,15 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableM
 | 
			
		||||
        if (_driverPropertys.GroupUpdate && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            AddQueueVarModel(new CacheDBItem<List<TDengineDBHistoryValue>>(variableRuntimeGroup.Adapt<List<TDengineDBHistoryValue>>(_config)));
 | 
			
		||||
            AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>(_config)));
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            AddQueueVarModel(new CacheDBItem<TDengineDBHistoryValue>(variableRuntime.Adapt<TDengineDBHistoryValue>(_config)));
 | 
			
		||||
            AddQueueVarModel(new CacheDBItem<VariableBasicData>(variable));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private async ValueTask<OperResult> UpdateVarModel(IEnumerable<TDengineDBHistoryValue> item, CancellationToken cancellationToken)
 | 
			
		||||
    private async ValueTask<OperResult> UpdateVarModel(IEnumerable<VariableBasicData> item, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        var result = await InserableAsync(item.WhereIf(_driverPropertys.OnlineFilter, a => a.IsOnline == true).ToList(), cancellationToken).ConfigureAwait(false);
 | 
			
		||||
        if (success != result.IsSuccess)
 | 
			
		||||
@@ -103,7 +103,7 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableM
 | 
			
		||||
 | 
			
		||||
    #region 方法
 | 
			
		||||
 | 
			
		||||
    private async ValueTask<OperResult> InserableAsync(List<TDengineDBHistoryValue> dbInserts, CancellationToken cancellationToken)
 | 
			
		||||
    private async ValueTask<OperResult> InserableAsync(List<VariableBasicData> dbInserts, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@ using ThingsGateway.Gateway.Application;
 | 
			
		||||
using ThingsGateway.NewLife;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
using ThingsGateway.NewLife.Json.Extension;
 | 
			
		||||
using ThingsGateway.NewLife.Threading;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
using TouchSocket.Core;
 | 
			
		||||
@@ -153,14 +152,8 @@ public class ModbusSlave : BusinessBase
 | 
			
		||||
    protected override async Task ProtectedExecuteAsync(object? state, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        //获取设备连接状态
 | 
			
		||||
        if (IsConnected())
 | 
			
		||||
        if (!IsConnected())
 | 
			
		||||
        {
 | 
			
		||||
            //更新设备活动时间
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, true);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (cancellationToken.IsCancellationRequested)
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ using MQTTnet.Client;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation;
 | 
			
		||||
using ThingsGateway.NewLife.Threading;
 | 
			
		||||
 | 
			
		||||
using TouchSocket.Core;
 | 
			
		||||
 | 
			
		||||
@@ -287,17 +286,6 @@ public partial class MqttCollect : CollectBase
 | 
			
		||||
            await Task.Delay(10000, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
            //return;
 | 
			
		||||
        }
 | 
			
		||||
        //获取设备连接状态
 | 
			
		||||
        if (IsConnected())
 | 
			
		||||
        {
 | 
			
		||||
            //更新设备活动时间
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            CurrentDevice.SetDeviceStatus(TimerX.Now, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -108,17 +108,23 @@ public class OpcUaMaster : CollectBase
 | 
			
		||||
 | 
			
		||||
        var check = ScheduledTaskHelper.GetTask("3000", CheckAsync, null, LogMessage, cancellationToken);
 | 
			
		||||
        list.Add(check);
 | 
			
		||||
        var checkConnec = ScheduledTaskHelper.GetTask("3000", CheckConnectAsync, null, LogMessage, cancellationToken);
 | 
			
		||||
        var checkConnec = ScheduledTaskHelper.GetTask("10000", CheckConnectAsync, null, LogMessage, cancellationToken);
 | 
			
		||||
        list.Add(checkConnec);
 | 
			
		||||
        return list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override async Task ProtectedStartAsync(CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        await CheckConnectAsync(null, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
        await base.ProtectedStartAsync(cancellationToken).ConfigureAwait(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async Task CheckConnectAsync(object? state, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        if (_plc.Session == null)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(100, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
                if (_plc.Session == null)
 | 
			
		||||
                    await _plc.ConnectAsync(cancellationToken).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
@@ -128,14 +134,13 @@ public class OpcUaMaster : CollectBase
 | 
			
		||||
                    LogMessage?.LogWarning(ex, "Connect Fail");
 | 
			
		||||
 | 
			
		||||
                connectFirstFailLoged = true;
 | 
			
		||||
                CurrentDevice.SetDeviceStatus(TimerX.Now, true, ex.Message);
 | 
			
		||||
                await Task.Delay(10000, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
                CurrentDevice.SetDeviceStatus(TimerX.Now, null, ex.Message);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private async Task CheckAsync(object? state, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        if (_plc.Session == null)
 | 
			
		||||
        if (_plc.Session != null)
 | 
			
		||||
        {
 | 
			
		||||
            if (_driverProperties.ActiveSubscribe)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@ using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
using ThingsGateway.Gateway.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
using ThingsGateway.NewLife.Threading;
 | 
			
		||||
 | 
			
		||||
using TouchSocket.Core;
 | 
			
		||||
 | 
			
		||||
@@ -157,14 +156,8 @@ public partial class OpcUaServer : BusinessBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            if (IsConnected())
 | 
			
		||||
            if (!IsConnected())
 | 
			
		||||
            {
 | 
			
		||||
                //更新设备活动时间
 | 
			
		||||
                CurrentDevice.SetDeviceStatus(TimerX.Now, false);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                CurrentDevice.SetDeviceStatus(TimerX.Now, true);
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await Task.Delay(3000, cancellationToken).ConfigureAwait(false);
 | 
			
		||||
 
 | 
			
		||||
@@ -261,9 +261,9 @@ public partial class OpcUaImportVariable
 | 
			
		||||
                await ToastService.Warning(OpcUaPropertyLocalizer["NoVariablesAvailable"], OpcUaPropertyLocalizer["NoVariablesAvailable"]);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await App.RootServices.GetRequiredService<IChannelRuntimeService>().SaveChannelAsync(data.Item1, ItemChangedType.Add, false);
 | 
			
		||||
            await App.RootServices.GetRequiredService<IDeviceRuntimeService>().SaveDeviceAsync(data.Item2, ItemChangedType.Add, false);
 | 
			
		||||
            await App.RootServices.GetRequiredService<IVariableRuntimeService>().BatchSaveVariableAsync(data.Item3.ToList(), ItemChangedType.Add, false, default);
 | 
			
		||||
            await App.RootServices.GetRequiredService<IChannelRuntimeService>().SaveChannelAsync(data.Item1, ItemChangedType.Add, true);
 | 
			
		||||
            await App.RootServices.GetRequiredService<IDeviceRuntimeService>().SaveDeviceAsync(data.Item2, ItemChangedType.Add, true);
 | 
			
		||||
            await App.RootServices.GetRequiredService<IVariableRuntimeService>().BatchSaveVariableAsync(data.Item3.ToList(), ItemChangedType.Add, true, default);
 | 
			
		||||
            await ToastService.Default();
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "ChannelThread": {
 | 
			
		||||
    "MinCycleInterval": 10, //最小循环间隔
 | 
			
		||||
    "MaxCycleInterval": 200, //最大循环间隔
 | 
			
		||||
    "CheckInterval": 1800000, //检查间隔
 | 
			
		||||
    "MaxChannelCount": 50, //最大通道数量
 | 
			
		||||
    "MaxDeviceCount": 50, //最大设备数量
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "ChannelThread": {
 | 
			
		||||
    "MinCycleInterval": 10, //最小循环间隔
 | 
			
		||||
    "MaxCycleInterval": 200, //最大循环间隔
 | 
			
		||||
    "CheckInterval": 1800000, //检查间隔
 | 
			
		||||
    "MaxChannelCount": 5000, //最大通道数量
 | 
			
		||||
    "MaxDeviceCount": 5000, //最大设备数量
 | 
			
		||||
    "MaxVariableCount": 2000000 //最大变量数量
 | 
			
		||||
    "MaxChannelCount": 50000, //最大通道数量
 | 
			
		||||
    "MaxDeviceCount": 50000, //最大设备数量
 | 
			
		||||
    "MaxVariableCount": 10000000 //最大变量数量
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@
 | 
			
		||||
                    @if(WebsiteOption.Value.Demo)
 | 
			
		||||
                    {
 | 
			
		||||
                        <Button class="btn-block mt-5" IsAsync OnClick=GithubLogin>@Localizer["GithubLogin"]</Button>
 | 
			
		||||
                        <Button class="btn-block mt-5" IsAsync OnClick=GiteeLogin>@Localizer["GiteeLogin"]</Button>
 | 
			
		||||
                        @* <Button class="btn-block mt-5" IsAsync OnClick=GiteeLogin>@Localizer["GiteeLogin"]</Button> *@
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
 
 | 
			
		||||
@@ -325,8 +325,8 @@ Global
 | 
			
		||||
		{4C412EC1-8501-8211-5A57-3CEEE7EEA6B3} = {72C65578-92A5-4E99-9779-27835B12B32F}
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(ExtensibilityGlobals) = postSolution
 | 
			
		||||
		RESX_Rules = {"EnabledRules":[]}
 | 
			
		||||
		RESX_NeutralResourcesLanguage = zh-Hans
 | 
			
		||||
		SolutionGuid = {199B1B96-4F56-4828-9531-813BA02DB282}
 | 
			
		||||
		RESX_NeutralResourcesLanguage = zh-Hans
 | 
			
		||||
		RESX_Rules = {"EnabledRules":[]}
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
EndGlobal
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<Project>
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <Version>10.8.7</Version>
 | 
			
		||||
    <Version>10.8.12</Version>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user