Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ce843182f | ||
|
|
a4aa000cf0 | ||
|
|
01aa6ca066 |
@@ -13,7 +13,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.6" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
<PackageReference Include="BootstrapBlazor" Version="9.8.1" />
|
||||
<PackageReference Include="BootstrapBlazor" Version="9.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -62,7 +62,7 @@ public class SugarAopService : ISugarAopService
|
||||
if (ex.Parameters == null) return;
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
DbContext.WriteLog($"{config.ConfigId}库操作异常");
|
||||
DbContext.WriteErrorLogWithSql(UtilMethods.GetNativeSql(ex.Sql, (SugarParameter[])ex.Parameters));
|
||||
DbContext.WriteErrorLogWithSql(UtilMethods.GetNativeSql(ex.Sql, (IReadOnlyList<SugarParameter>)ex.Parameters));
|
||||
NewLife.Log.XTrace.WriteException(ex);
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor.FontAwesome" Version="9.0.2" />
|
||||
<PackageReference Include="BootstrapBlazor.FontAwesome" Version="9.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<PluginVersion>10.9.64</PluginVersion>
|
||||
<ProPluginVersion>10.9.64</ProPluginVersion>
|
||||
<DefaultVersion>10.9.64</DefaultVersion>
|
||||
<AuthenticationVersion>2.9.24</AuthenticationVersion>
|
||||
<PluginVersion>10.9.67</PluginVersion>
|
||||
<ProPluginVersion>10.9.67</ProPluginVersion>
|
||||
<DefaultVersion>10.9.67</DefaultVersion>
|
||||
<AuthenticationVersion>2.9.27</AuthenticationVersion>
|
||||
<SourceGeneratorVersion>10.9.24</SourceGeneratorVersion>
|
||||
<NET8Version>8.0.18</NET8Version>
|
||||
<NET9Version>9.0.7</NET9Version>
|
||||
|
||||
@@ -18,46 +18,71 @@
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-sm-6 col-md-4">
|
||||
<Select SkipValidate="true" @bind-Value="@value.ChannelType" OnSelectedItemChanged=@((a)=>
|
||||
{
|
||||
return InvokeAsync(StateHasChanged);
|
||||
}) />
|
||||
{
|
||||
return InvokeAsync(StateHasChanged);
|
||||
}) />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
|
||||
</EditorItem>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.RemoteUrl" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.BindUrl" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession&&context.ChannelType!=ChannelTypeEnum.TcpService) />
|
||||
<EditorItem @bind-Field="@context.RemoteUrl" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.BindUrl" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession && context.ChannelType != ChannelTypeEnum.TcpService) />
|
||||
|
||||
<EditorItem @bind-Field="@context.PortName" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.BaudRate" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.DataBits" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.Parity" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.StopBits" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.DtrEnable" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.RtsEnable" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.StreamAsync" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.PortName" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.BaudRate" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.DataBits" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.Parity" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.StopBits" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.DtrEnable" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.RtsEnable" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.StreamAsync" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.CacheTimeout" Ignore=@(context.ChannelType==ChannelTypeEnum.UdpSession||context.ChannelType==ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.ConnectTimeout" Ignore=@(context.ChannelType==ChannelTypeEnum.UdpSession||context.ChannelType==ChannelTypeEnum.TcpService||context.ChannelType==ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.MaxConcurrentCount" Ignore=@(context.ChannelType==ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.CacheTimeout" Ignore=@(context.ChannelType == ChannelTypeEnum.UdpSession || context.ChannelType == ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.ConnectTimeout" Ignore=@(context.ChannelType == ChannelTypeEnum.UdpSession || context.ChannelType == ChannelTypeEnum.TcpService || context.ChannelType == ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.MaxConcurrentCount" Ignore=@(context.ChannelType == ChannelTypeEnum.Other) />
|
||||
|
||||
<EditorItem @bind-Field="@context.MaxClientCount" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpService) />
|
||||
<EditorItem @bind-Field="@context.CheckClearTime" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpService) />
|
||||
<EditorItem @bind-Field="@context.Heartbeat" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpService&&context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.HeartbeatTime" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.DtuId" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.DtuSeviceType" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpService&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.MaxClientCount" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService) />
|
||||
<EditorItem @bind-Field="@context.CheckClearTime" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService) />
|
||||
|
||||
</FieldItems>
|
||||
<Buttons>
|
||||
<Button IsAsync class="mx-2" Color=Color.Primary OnClick="ConnectClick">@Localizer["Connect"]</Button>
|
||||
<Button IsAsync class="mx-2" Color=Color.Warning OnClick="DisconnectClick">@Localizer["Disconnect"]</Button>
|
||||
</Buttons>
|
||||
</EditorFormObject>
|
||||
|
||||
</ValidateForm>
|
||||
<EditorItem @bind-Field="@context.Heartbeat" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService && context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession)>
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-sm-6 col-md-4">
|
||||
<BootstrapInput @bind-Value=value.Heartbeat ShowLabel="true" class="me-2"></BootstrapInput>
|
||||
<Checkbox @bind-Value=value.HeartbeatHex ShowAfterLabel DisplayText="hex"></Checkbox>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
</BodyTemplate>
|
||||
</Card>
|
||||
|
||||
<EditorItem @bind-Field="@context.HeartbeatTime" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.DtuId" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession)>
|
||||
|
||||
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-sm-6 col-md-4">
|
||||
<BootstrapInput @bind-Value=value.DtuId ShowLabel="true" class="me-2"></BootstrapInput>
|
||||
<Checkbox @bind-Value=value.DtuIdHex ShowAfterLabel DisplayText="hex"></Checkbox>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.DtuIdHex" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService) />
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.DtuSeviceType" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService && context.ChannelType != ChannelTypeEnum.UdpSession) />
|
||||
|
||||
</FieldItems>
|
||||
<Buttons>
|
||||
<Button IsAsync class="mx-2" Color=Color.Primary OnClick="ConnectClick">@Localizer["Connect"]</Button>
|
||||
<Button IsAsync class="mx-2" Color=Color.Warning OnClick="DisconnectClick">@Localizer["Disconnect"]</Button>
|
||||
</Buttons>
|
||||
</EditorFormObject>
|
||||
|
||||
</ValidateForm>
|
||||
|
||||
</BodyTemplate>
|
||||
</Card>
|
||||
|
||||
@@ -72,6 +72,8 @@
|
||||
"DtuId": "DtuId",
|
||||
"DtuSeviceType": "DtuSeviceType",
|
||||
"Heartbeat": "Heartbeat",
|
||||
"DtuIdHex": "DtuIdHex",
|
||||
"HeartbeatHex": "HeartbeatHex",
|
||||
"HeartbeatTime": "HeartbeatTime",
|
||||
"MaxClientCount": "MaxClientCount",
|
||||
"MaxConcurrentCount": "MaxConcurrentCount",
|
||||
|
||||
@@ -69,9 +69,11 @@
|
||||
"ConnectTimeout": "连接超时",
|
||||
"DataBits": "数据位",
|
||||
"DtrEnable": "Dtr",
|
||||
"DtuId": "Dtu终端注册包(utf-8)",
|
||||
"DtuId": "Dtu终端注册包",
|
||||
"DtuSeviceType": "DTU服务类型",
|
||||
"Heartbeat": "心跳内容(utf8)",
|
||||
"Heartbeat": "心跳内容",
|
||||
"DtuIdHex": "Dtu终端注册包是否Hex",
|
||||
"HeartbeatHex": "心跳内容是否Hex",
|
||||
"HeartbeatTime": "心跳间隔",
|
||||
"MaxClientCount": "最大连接数",
|
||||
"MaxConcurrentCount": "最大并发数",
|
||||
|
||||
@@ -94,10 +94,12 @@ namespace ThingsGateway.Foundation
|
||||
public virtual int MaxClientCount { get; set; }
|
||||
public virtual int CheckClearTime { get; set; }
|
||||
public virtual string Heartbeat { get; set; }
|
||||
public virtual bool HeartbeatHex { get; set; }
|
||||
|
||||
#region dtu终端
|
||||
public virtual int HeartbeatTime { get; set; }
|
||||
public virtual string DtuId { get; set; }
|
||||
public virtual bool DtuIdHex { get; set; }
|
||||
#endregion
|
||||
public virtual DtuSeviceType DtuSeviceType { get; set; }
|
||||
|
||||
|
||||
@@ -54,20 +54,29 @@ public static class ChannelOptionsExtensions
|
||||
/// <returns></returns>
|
||||
internal static async Task OnChannelEvent(this IClientChannel clientChannel, ChannelEventHandler funcs)
|
||||
{
|
||||
clientChannel.ThrowIfNull(nameof(IClientChannel));
|
||||
funcs.ThrowIfNull(nameof(ChannelEventHandler));
|
||||
|
||||
if (funcs.Count > 0)
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < funcs.Count; i++)
|
||||
|
||||
clientChannel.ThrowIfNull(nameof(IClientChannel));
|
||||
funcs.ThrowIfNull(nameof(ChannelEventHandler));
|
||||
|
||||
if (funcs.Count > 0)
|
||||
{
|
||||
var func = funcs[i];
|
||||
var handled = await func.Invoke(clientChannel, i == funcs.Count - 1).ConfigureAwait(false);
|
||||
if (handled)
|
||||
for (int i = 0; i < funcs.Count; i++)
|
||||
{
|
||||
break;
|
||||
var func = funcs[i];
|
||||
var handled = await func.Invoke(clientChannel, i == funcs.Count - 1).ConfigureAwait(false);
|
||||
if (handled)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
clientChannel.Logger?.LogWarning(ex, "fail ChannelEvent");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,10 +111,13 @@ public interface IChannelOptions
|
||||
int CheckClearTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 心跳检测(utf8)
|
||||
/// 心跳检测
|
||||
/// </summary>
|
||||
string Heartbeat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 心跳检测是否hex
|
||||
/// </summary>
|
||||
bool HeartbeatHex { get; set; }
|
||||
#region dtu终端
|
||||
/// <summary>
|
||||
/// 心跳时间
|
||||
@@ -122,10 +125,13 @@ public interface IChannelOptions
|
||||
public int HeartbeatTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认Dtu注册包(utf-8)
|
||||
/// 默认Dtu注册包
|
||||
/// </summary>
|
||||
public string DtuId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认Dtu注册包是否hex
|
||||
/// </summary>
|
||||
bool DtuIdHex { get; set; }
|
||||
#endregion
|
||||
|
||||
public DtuSeviceType DtuSeviceType { get; set; }
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.String;
|
||||
|
||||
namespace ThingsGateway.Foundation;
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -28,13 +30,34 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
|
||||
set
|
||||
{
|
||||
_heartbeat = value;
|
||||
if (!_heartbeat.IsNullOrEmpty())
|
||||
HeartbeatByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(value));
|
||||
if (!heartbeatHex)
|
||||
HeartbeatByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
|
||||
else
|
||||
HeartbeatByte = new ArraySegment<byte>(_heartbeat?.HexStringToBytes() ?? Array.Empty<byte>());
|
||||
}
|
||||
}
|
||||
private string _heartbeat;
|
||||
private ArraySegment<byte> HeartbeatByte = new();
|
||||
|
||||
|
||||
private bool heartbeatHex;
|
||||
public bool HeartbeatHex
|
||||
{
|
||||
get
|
||||
{
|
||||
return heartbeatHex;
|
||||
}
|
||||
set
|
||||
{
|
||||
heartbeatHex = value;
|
||||
if (!heartbeatHex)
|
||||
HeartbeatByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
|
||||
else
|
||||
HeartbeatByte = new ArraySegment<byte>(_heartbeat?.HexStringToBytes() ?? Array.Empty<byte>());
|
||||
}
|
||||
}
|
||||
public bool DtuIdHex { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task OnTcpReceiving(ITcpSession client, ByteBlockEventArgs e)
|
||||
{
|
||||
@@ -43,7 +66,7 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
|
||||
{
|
||||
if (!socket.Id.StartsWith("ID="))
|
||||
{
|
||||
var id = $"ID={e.ByteBlock}";
|
||||
var id = DtuIdHex ? $"ID={e.ByteBlock.Span.ToHexString()}" : $"ID={e.ByteBlock.ToString(0, e.ByteBlock.Length)}";
|
||||
if (tcpServiceChannel.TryGetClient(id, out var oldClient))
|
||||
{
|
||||
try
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.String;
|
||||
|
||||
namespace ThingsGateway.Foundation;
|
||||
|
||||
[PluginOption(Singleton = true)]
|
||||
@@ -24,7 +26,10 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
|
||||
set
|
||||
{
|
||||
_dtuId = value;
|
||||
DtuIdByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(value));
|
||||
if (!dtuIdHex)
|
||||
DtuIdByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(_dtuId ?? string.Empty));
|
||||
else
|
||||
DtuIdByte = new ArraySegment<byte>(_dtuId?.HexStringToBytes() ?? Array.Empty<byte>());
|
||||
}
|
||||
}
|
||||
private string _dtuId;
|
||||
@@ -42,15 +47,64 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
|
||||
set
|
||||
{
|
||||
_heartbeat = value;
|
||||
if (!_heartbeat.IsNullOrEmpty())
|
||||
{
|
||||
HeartbeatByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(value));
|
||||
}
|
||||
if (!heartbeatHex)
|
||||
HeartbeatByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
|
||||
else
|
||||
HeartbeatByte = new ArraySegment<byte>(_heartbeat?.HexStringToBytes() ?? Array.Empty<byte>());
|
||||
}
|
||||
}
|
||||
private string _heartbeat;
|
||||
private ArraySegment<byte> HeartbeatByte;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private bool heartbeatHex;
|
||||
public bool HeartbeatHex
|
||||
{
|
||||
get
|
||||
{
|
||||
return heartbeatHex;
|
||||
}
|
||||
set
|
||||
{
|
||||
heartbeatHex = value;
|
||||
if (!heartbeatHex)
|
||||
{
|
||||
HeartbeatByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HeartbeatByte = new ArraySegment<byte>(_heartbeat?.HexStringToBytes() ?? Array.Empty<byte>());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool dtuIdHex;
|
||||
public bool DtuIdHex
|
||||
{
|
||||
get
|
||||
{
|
||||
return dtuIdHex;
|
||||
}
|
||||
set
|
||||
{
|
||||
dtuIdHex = value;
|
||||
if (!dtuIdHex)
|
||||
{
|
||||
DtuIdByte = new ArraySegment<byte>(Encoding.UTF8.GetBytes(_dtuId ?? string.Empty));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
DtuIdByte = new ArraySegment<byte>(_dtuId?.HexStringToBytes() ?? Array.Empty<byte>());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
private Task Task;
|
||||
private bool SendHeartbeat;
|
||||
public int HeartbeatTime { get; set; } = 3000;
|
||||
|
||||
@@ -25,6 +25,8 @@ public static class PluginUtil
|
||||
action += a =>
|
||||
{
|
||||
var plugin = a.Add<HeartbeatAndReceivePlugin>();
|
||||
plugin.HeartbeatHex = channelOptions.HeartbeatHex;
|
||||
plugin.DtuIdHex = channelOptions.DtuIdHex;
|
||||
plugin.Heartbeat = channelOptions.Heartbeat;
|
||||
plugin.DtuId = channelOptions.DtuId;
|
||||
plugin.HeartbeatTime = channelOptions.HeartbeatTime;
|
||||
@@ -52,7 +54,9 @@ public static class PluginUtil
|
||||
action += a =>
|
||||
{
|
||||
var plugin = a.Add<DtuPlugin>();
|
||||
plugin.HeartbeatHex = channelOptions.HeartbeatHex;
|
||||
plugin.Heartbeat = channelOptions.Heartbeat;
|
||||
plugin.DtuIdHex = channelOptions.DtuIdHex;
|
||||
};
|
||||
}
|
||||
return action;
|
||||
|
||||
@@ -238,7 +238,7 @@ public abstract class TcpCustomDataHandlingAdapter<TRequest> : SingleStreamDataH
|
||||
// 如果缓存的数据长度超过设定的最大包大小,则抛出异常。
|
||||
if (this.m_tempByteBlock.Length > this.MaxPackageSize)
|
||||
{
|
||||
throw new Exception("缓存的数据长度大于设定值的情况下未收到解析信号");
|
||||
throw new Exception($"The parsed signal was not received when the cached data length {m_tempByteBlock.Length} exceeds the set value {MaxPackageSize}");
|
||||
}
|
||||
|
||||
// 将字节块指针移到末尾。
|
||||
@@ -306,7 +306,7 @@ public abstract class TcpCustomDataHandlingAdapter<TRequest> : SingleStreamDataH
|
||||
|
||||
if (this.m_tempByteBlock.Length > this.MaxPackageSize)
|
||||
{
|
||||
this.OnError(default, "缓存的数据长度大于设定值的情况下未收到解析信号", true, true);
|
||||
this.OnError(default, $"The parsed signal was not received when the cached data length {m_tempByteBlock.Length} exceeds the set value {MaxPackageSize}", true, true);
|
||||
}
|
||||
}
|
||||
if (this.UpdateCacheTimeWhenRev)
|
||||
|
||||
@@ -142,7 +142,20 @@ public static partial class DeviceExtension
|
||||
return new();
|
||||
|
||||
case WaitDataStatus.Canceled: return new(new OperationCanceledException());
|
||||
case WaitDataStatus.Overtime: return waitDataAsync.WaitResult == null ? new(new TimeoutException()) : new(waitDataAsync.WaitResult);
|
||||
case WaitDataStatus.Overtime:
|
||||
{
|
||||
if (waitDataAsync.WaitResult != null)
|
||||
{
|
||||
waitDataAsync.WaitResult.Exception = new TimeoutException();
|
||||
if (waitDataAsync.WaitResult.IsSuccess) waitDataAsync.WaitResult.OperCode = 999;
|
||||
if (waitDataAsync.WaitResult.ErrorMessage.IsNullOrEmpty()) waitDataAsync.WaitResult.ErrorMessage = "Timeout";
|
||||
return new(waitDataAsync.WaitResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(new TimeoutException());
|
||||
}
|
||||
}
|
||||
case WaitDataStatus.Disposed:
|
||||
case WaitDataStatus.Default:
|
||||
default:
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
"DtuSeviceType": "DtuSeviceType",
|
||||
"Heartbeat": "Heartbeat",
|
||||
"HeartbeatTime": "HeartbeatTime",
|
||||
"DtuIdHex": "DtuIdHex",
|
||||
"HeartbeatHex": "HeartbeatHex",
|
||||
"MaxClientCount": "MaxClientCount",
|
||||
"MaxConcurrentCount": "MaxConcurrentCount",
|
||||
"Name": "Name",
|
||||
@@ -73,7 +75,7 @@
|
||||
"Timeout": "Timeout"
|
||||
},
|
||||
"ThingsGateway.Foundation.DtuServiceDeviceBase": {
|
||||
"DtuId": "DtuId(UTF8)"
|
||||
"DtuId": "DtuId"
|
||||
},
|
||||
"ThingsGateway.Foundation.VariableClass": {
|
||||
"RegisterAddress": "RegisterAddress"
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
"ConnectTimeout": "连接超时",
|
||||
"DataBits": "数据位",
|
||||
"DtrEnable": "Dtr",
|
||||
"DtuId": "Dtu终端注册包(utf-8)",
|
||||
"DtuId": "Dtu终端注册包",
|
||||
"DtuSeviceType": "DTU服务类型",
|
||||
"Heartbeat": "心跳内容(utf8)",
|
||||
"Heartbeat": "心跳内容",
|
||||
"DtuIdHex": "Dtu终端注册包是否Hex",
|
||||
"HeartbeatHex": "心跳内容是否Hex",
|
||||
"HeartbeatTime": "心跳间隔",
|
||||
"MaxClientCount": "最大连接数",
|
||||
"MaxConcurrentCount": "最大并发数",
|
||||
@@ -73,7 +75,7 @@
|
||||
"Timeout": "读写超时"
|
||||
},
|
||||
"ThingsGateway.Foundation.DtuServiceDeviceBase": {
|
||||
"DtuId": "Dtu注册包(UTF8)"
|
||||
"DtuId": "Dtu注册包"
|
||||
},
|
||||
"ThingsGateway.Foundation.VariableClass": {
|
||||
"RegisterAddress": "寄存器地址"
|
||||
|
||||
@@ -177,6 +177,10 @@ public class Channel : ChannelOptionsBase, IPrimaryIdEntity, IBaseDataEntity, IB
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
public override string Heartbeat { get; set; }
|
||||
|
||||
[SugarColumn(ColumnDescription = "心跳内容是否Hex", IsNullable = true)]
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
public override bool HeartbeatHex { get; set; }
|
||||
|
||||
#region dtu终端
|
||||
|
||||
[SugarColumn(ColumnDescription = "心跳间隔", IsNullable = true)]
|
||||
@@ -187,6 +191,9 @@ public class Channel : ChannelOptionsBase, IPrimaryIdEntity, IBaseDataEntity, IB
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
public override string DtuId { get; set; }
|
||||
|
||||
[SugarColumn(ColumnDescription = "DtuId是否Hex", IsNullable = true)]
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
public override bool DtuIdHex { get; set; }
|
||||
#endregion
|
||||
|
||||
[SugarColumn(ColumnDescription = "Dtu类型", IsNullable = true)]
|
||||
|
||||
@@ -18,7 +18,7 @@ public enum EventTypeEnum
|
||||
/// <summary>
|
||||
/// 准备报警
|
||||
/// </summary>
|
||||
Prepare,
|
||||
PrepareAlarm,
|
||||
|
||||
/// <summary>
|
||||
/// 报警产生
|
||||
@@ -34,4 +34,9 @@ public enum EventTypeEnum
|
||||
/// 报警恢复
|
||||
/// </summary>
|
||||
Finish,
|
||||
|
||||
/// <summary>
|
||||
/// 准备恢复
|
||||
/// </summary>
|
||||
PrepareFinish,
|
||||
}
|
||||
|
||||
@@ -242,6 +242,8 @@
|
||||
"ExportChannel": "Export Channel",
|
||||
"Heartbeat": "Heartbeat",
|
||||
"HeartbeatTime": "HeartbeatTime",
|
||||
"DtuIdHex": "DtuIdHex",
|
||||
"HeartbeatHex": "HeartbeatHex",
|
||||
"ImportChannel": "Import Channel",
|
||||
"ImportNullError": "Unable to recognize",
|
||||
"LogEnable": "LogEnable",
|
||||
@@ -274,10 +276,10 @@
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationDtuPackPropertyBase": {
|
||||
"DtuId": "DtuId(UTF8)"
|
||||
"DtuId": "DtuId"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationDtuPropertyBase": {
|
||||
"DtuId": "DtuId(UTF8)"
|
||||
"DtuId": "DtuId"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationPackPropertyBase": {
|
||||
"MaxPack": "MaxPack"
|
||||
|
||||
@@ -235,11 +235,13 @@
|
||||
"DeleteChannel": "删除通道",
|
||||
"Disconnect": "断开",
|
||||
"DtrEnable": "Dtr",
|
||||
"DtuId": "Dtu终端注册包(utf-8)",
|
||||
"DtuId": "Dtu终端注册包",
|
||||
"DtuSeviceType": "DTU服务类型",
|
||||
"Enable": "启用",
|
||||
"ExportChannel": "导出通道",
|
||||
"Heartbeat": "心跳内容(utf8)",
|
||||
"Heartbeat": "心跳内容",
|
||||
"DtuIdHex": "Dtu终端注册包是否Hex",
|
||||
"HeartbeatHex": "心跳内容是否Hex",
|
||||
"HeartbeatTime": "心跳间隔",
|
||||
"ImportChannel": "导入通道",
|
||||
"ImportNullError": "无法识别",
|
||||
@@ -273,10 +275,10 @@
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationDtuPackPropertyBase": {
|
||||
"DtuId": "Dtu注册包(UTF8)"
|
||||
"DtuId": "Dtu注册包"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationDtuPropertyBase": {
|
||||
"DtuId": "Dtu注册包(UTF8)"
|
||||
"DtuId": "Dtu注册包"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.CollectFoundationPackPropertyBase": {
|
||||
"MaxPack": "最大打包长度"
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace ThingsGateway.Gateway.Application;
|
||||
/// </summary>
|
||||
public partial class VariableRuntime : Variable, IVariable, IDisposable
|
||||
{
|
||||
private DateTime? prepareEventTime;
|
||||
private DateTime? prepareAlarmEventTime;
|
||||
private DateTime? prepareFinishEventTime;
|
||||
private EventTypeEnum? eventType;
|
||||
|
||||
private AlarmTypeEnum? alarmType { get; set; }
|
||||
|
||||
@@ -55,7 +55,12 @@ public partial class VariableRuntime : Variable, IVariable, IDisposable
|
||||
/// 事件时间
|
||||
/// </summary>
|
||||
[AutoGenerateColumn(Ignore = true)]
|
||||
internal DateTime? PrepareEventTime { get => prepareEventTime; set => prepareEventTime = value; }
|
||||
internal DateTime? PrepareAlarmEventTime { get => prepareAlarmEventTime; set => prepareAlarmEventTime = value; }
|
||||
/// <summary>
|
||||
/// 事件时间
|
||||
/// </summary>
|
||||
[AutoGenerateColumn(Ignore = true)]
|
||||
internal DateTime? PrepareFinishEventTime { get => prepareFinishEventTime; set => prepareFinishEventTime = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 变化时间
|
||||
|
||||
@@ -284,16 +284,16 @@ internal sealed class AlarmTask : IDisposable
|
||||
//添加报警延时策略
|
||||
if (delay > 0)
|
||||
{
|
||||
if (item.EventType != EventTypeEnum.Alarm && item.EventType != EventTypeEnum.Prepare)
|
||||
if (item.EventType != EventTypeEnum.Alarm && item.EventType != EventTypeEnum.PrepareAlarm)
|
||||
{
|
||||
item.EventType = EventTypeEnum.Prepare;//准备报警
|
||||
item.PrepareEventTime = now;
|
||||
item.EventType = EventTypeEnum.PrepareAlarm;//准备报警
|
||||
item.PrepareAlarmEventTime = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.EventType == EventTypeEnum.Prepare)
|
||||
if (item.EventType == EventTypeEnum.PrepareAlarm)
|
||||
{
|
||||
if ((now - item.PrepareEventTime!.Value).TotalSeconds > delay)
|
||||
if ((now - item.PrepareAlarmEventTime!.Value).TotalMilliseconds > delay)
|
||||
{
|
||||
//超过延时时间,触发报警
|
||||
item.EventType = EventTypeEnum.Alarm;
|
||||
@@ -304,7 +304,7 @@ internal sealed class AlarmTask : IDisposable
|
||||
item.AlarmCode = item.Value.ToString();
|
||||
item.RecoveryCode = string.Empty;
|
||||
item.AlarmText = text;
|
||||
item.PrepareEventTime = null;
|
||||
item.PrepareAlarmEventTime = null;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
@@ -312,9 +312,9 @@ internal sealed class AlarmTask : IDisposable
|
||||
else if (item.EventType == EventTypeEnum.Alarm && item.AlarmType != alarmEnum)
|
||||
{
|
||||
//报警类型改变,重新计时
|
||||
if (item.PrepareEventTime == null)
|
||||
item.PrepareEventTime = now;
|
||||
if ((now - item.PrepareEventTime!.Value).TotalSeconds > delay)
|
||||
if (item.PrepareAlarmEventTime == null)
|
||||
item.PrepareAlarmEventTime = now;
|
||||
if ((now - item.PrepareAlarmEventTime!.Value).TotalMilliseconds > delay)
|
||||
{
|
||||
//超过延时时间,触发报警
|
||||
item.EventType = EventTypeEnum.Alarm;
|
||||
@@ -325,7 +325,7 @@ internal sealed class AlarmTask : IDisposable
|
||||
item.AlarmCode = item.Value.ToString();
|
||||
item.RecoveryCode = string.Empty;
|
||||
item.AlarmText = text;
|
||||
item.PrepareEventTime = null;
|
||||
item.PrepareAlarmEventTime = null;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -346,24 +346,64 @@ internal sealed class AlarmTask : IDisposable
|
||||
item.AlarmCode = item.Value.ToString();
|
||||
item.RecoveryCode = string.Empty;
|
||||
item.AlarmText = text;
|
||||
item.PrepareAlarmEventTime = null;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (eventEnum == EventTypeEnum.Finish)
|
||||
{
|
||||
// 如果是需恢复报警事件
|
||||
// 获取旧的报警信息
|
||||
if (GlobalData.RealAlarmIdVariables.TryGetValue(item.Id, out var oldAlarm))
|
||||
var now = DateTime.Now;
|
||||
//添加报警延时策略
|
||||
if (delay > 0)
|
||||
{
|
||||
item.AlarmType = oldAlarm.AlarmType;
|
||||
item.EventType = eventEnum;
|
||||
item.AlarmLimit = oldAlarm.AlarmLimit;
|
||||
item.AlarmCode = oldAlarm.AlarmCode;
|
||||
item.RecoveryCode = item.Value.ToString();
|
||||
item.AlarmText = oldAlarm.AlarmText;
|
||||
item.EventTime = DateTime.Now;
|
||||
if (item.EventType != EventTypeEnum.Finish && item.EventType != EventTypeEnum.PrepareFinish)
|
||||
{
|
||||
item.EventType = EventTypeEnum.PrepareFinish;//准备报警
|
||||
item.PrepareFinishEventTime = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.EventType == EventTypeEnum.PrepareFinish)
|
||||
{
|
||||
if ((now - item.PrepareFinishEventTime!.Value).TotalMilliseconds > delay)
|
||||
{
|
||||
if (GlobalData.RealAlarmIdVariables.TryGetValue(item.Id, out var oldAlarm))
|
||||
{
|
||||
item.AlarmType = oldAlarm.AlarmType;
|
||||
item.EventType = eventEnum;
|
||||
item.AlarmLimit = oldAlarm.AlarmLimit;
|
||||
item.AlarmCode = oldAlarm.AlarmCode;
|
||||
item.RecoveryCode = item.Value.ToString();
|
||||
item.AlarmText = oldAlarm.AlarmText;
|
||||
item.EventTime = DateTime.Now;
|
||||
item.PrepareFinishEventTime = null;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果是需恢复报警事件
|
||||
// 获取旧的报警信息
|
||||
if (GlobalData.RealAlarmIdVariables.TryGetValue(item.Id, out var oldAlarm))
|
||||
{
|
||||
item.AlarmType = oldAlarm.AlarmType;
|
||||
item.EventType = eventEnum;
|
||||
item.AlarmLimit = oldAlarm.AlarmLimit;
|
||||
item.AlarmCode = oldAlarm.AlarmCode;
|
||||
item.RecoveryCode = item.Value.ToString();
|
||||
item.AlarmText = oldAlarm.AlarmText;
|
||||
item.EventTime = DateTime.Now;
|
||||
item.PrepareFinishEventTime = null;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// 触发报警变化事件
|
||||
@@ -333,6 +333,8 @@ internal sealed class DeviceThreadManage : IAsyncDisposable, IDeviceThreadManage
|
||||
}
|
||||
}
|
||||
|
||||
driver.IdVariableRuntimes.ForEach(a => a.Value.SetErrorMessage(null));
|
||||
|
||||
CancellationTokenSources.TryAdd(driver.DeviceId, cts);
|
||||
|
||||
_ = Task.Factory.StartNew((state) => DriverStart(state, token), driver, token);
|
||||
@@ -395,17 +397,21 @@ internal sealed class DeviceThreadManage : IAsyncDisposable, IDeviceThreadManage
|
||||
// 查找具有指定设备ID的驱动程序对象
|
||||
if (Drivers.TryRemove(deviceId, out var driver))
|
||||
{
|
||||
driver.CurrentDevice.SetDeviceStatus(now, false, "Communication connection has been removed");
|
||||
if (IsCollectChannel == true)
|
||||
{
|
||||
foreach (var a in driver.IdVariableRuntimes)
|
||||
{
|
||||
a.Value.SetValue(a.Value.Value, now, false);
|
||||
a.Value.SetErrorMessage("Communication connection has been removed");
|
||||
if (a.Value.SaveValue && !a.Value.DynamicVariable)
|
||||
{
|
||||
saveVariableRuntimes.Add(a.Value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 取消驱动程序的操作
|
||||
|
||||
@@ -33,102 +33,125 @@
|
||||
RenderFragment renderFragment =>
|
||||
@<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=200 Model="Model">
|
||||
|
||||
<FieldItems>
|
||||
<EditorItem TValue="string" TModel="Channel" @bind-Field="@context.Name">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@GatewayLocalizer["BasicInformation"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<FieldItems>
|
||||
<EditorItem TValue="string" TModel="Channel" @bind-Field="@context.Name">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@GatewayLocalizer["BasicInformation"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.Name" Readonly=BatchEditEnable />
|
||||
<EditorItem @bind-Field="@context.Name" Readonly=BatchEditEnable />
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.PluginName">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select @bind-Value="@value.PluginName"
|
||||
Items="@PluginNames" IsDisabled=BatchEditEnable
|
||||
ShowSearch="true">
|
||||
<ItemTemplate Context="name">
|
||||
@if (PluginDcit.TryGetValue(name.Value, out var pluginOutput))
|
||||
{
|
||||
if (pluginOutput.EducationPlugin)
|
||||
{
|
||||
<div class="d-flex">
|
||||
<span>@name.Text</span>
|
||||
<div style="flex-grow: 1;"></div>
|
||||
<Tag Color="Color.Primary">PRO</Tag>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
<EditorItem @bind-Field="@context.PluginName">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select @bind-Value="@value.PluginName"
|
||||
Items="@PluginNames" IsDisabled=BatchEditEnable
|
||||
ShowSearch="true">
|
||||
<ItemTemplate Context="name">
|
||||
@if (PluginDcit.TryGetValue(name.Value, out var pluginOutput))
|
||||
{
|
||||
if (pluginOutput.EducationPlugin)
|
||||
{
|
||||
<div class="d-flex">
|
||||
<span>@name.Text</span>
|
||||
<div style="flex-grow: 1;"></div>
|
||||
<Tag Color="Color.Primary">PRO</Tag>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@name.Text</span>
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@name.Value</span>
|
||||
}
|
||||
</ItemTemplate>
|
||||
</Select>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
</ItemTemplate>
|
||||
</Select>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.Enable" />
|
||||
<EditorItem @bind-Field="@context.LogLevel" />
|
||||
<EditorItem @bind-Field="@context.Enable" />
|
||||
<EditorItem @bind-Field="@context.LogLevel" />
|
||||
|
||||
<EditorItem TValue="string" TModel="Channel" @bind-Field="@context.Name">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@GatewayLocalizer["Connection"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem TValue="string" TModel="Channel" @bind-Field="@context.Name">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@GatewayLocalizer["Connection"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.ChannelType">
|
||||
<EditorItem @bind-Field="@context.ChannelType">
|
||||
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-sm-6 col-md-6">
|
||||
<Select SkipValidate="true" @bind-Value="@value.ChannelType" OnSelectedItemChanged=@((a)=>
|
||||
{
|
||||
return InvokeAsync(StateHasChanged);
|
||||
}) />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-sm-6 col-md-6">
|
||||
<Select SkipValidate="true" @bind-Value="@value.ChannelType" OnSelectedItemChanged=@((a)=>
|
||||
{
|
||||
return InvokeAsync(StateHasChanged);
|
||||
}) />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
|
||||
</EditorItem>
|
||||
</EditorItem>
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.RemoteUrl" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.BindUrl" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession&&context.ChannelType!=ChannelTypeEnum.TcpService) />
|
||||
<EditorItem @bind-Field="@context.RemoteUrl" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.BindUrl" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession && context.ChannelType != ChannelTypeEnum.TcpService) />
|
||||
|
||||
<EditorItem @bind-Field="@context.PortName" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.BaudRate" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.DataBits" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.Parity" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.StopBits" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.DtrEnable" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.RtsEnable" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.StreamAsync" Ignore=@(context.ChannelType!=ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.PortName" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.BaudRate" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.DataBits" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.Parity" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.StopBits" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.DtrEnable" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.RtsEnable" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
<EditorItem @bind-Field="@context.StreamAsync" Ignore=@(context.ChannelType != ChannelTypeEnum.SerialPort) />
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.CacheTimeout" Ignore=@(context.ChannelType==ChannelTypeEnum.UdpSession||context.ChannelType==ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.ConnectTimeout" Ignore=@(context.ChannelType==ChannelTypeEnum.UdpSession||context.ChannelType==ChannelTypeEnum.TcpService||context.ChannelType==ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.MaxConcurrentCount" Ignore=@(context.ChannelType==ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.CacheTimeout" Ignore=@(context.ChannelType == ChannelTypeEnum.UdpSession || context.ChannelType == ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.ConnectTimeout" Ignore=@(context.ChannelType == ChannelTypeEnum.UdpSession || context.ChannelType == ChannelTypeEnum.TcpService || context.ChannelType == ChannelTypeEnum.Other) />
|
||||
<EditorItem @bind-Field="@context.MaxConcurrentCount" Ignore=@(context.ChannelType == ChannelTypeEnum.Other) />
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.MaxClientCount" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpService) />
|
||||
<EditorItem @bind-Field="@context.CheckClearTime" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpService) />
|
||||
<EditorItem @bind-Field="@context.Heartbeat" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpService&&context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.HeartbeatTime" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.DtuId" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpClient&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.DtuSeviceType" Ignore=@(context.ChannelType!=ChannelTypeEnum.TcpService&&context.ChannelType!=ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.MaxClientCount" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService) />
|
||||
<EditorItem @bind-Field="@context.CheckClearTime" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService) />
|
||||
|
||||
</FieldItems>
|
||||
<EditorItem @bind-Field="@context.Heartbeat" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService && context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession)>
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<BootstrapInput @bind-Value=value.Heartbeat ShowLabel="true" class="me-2"></BootstrapInput>
|
||||
<Checkbox @bind-Value=value.HeartbeatHex ShowAfterLabel DisplayText="hex"></Checkbox>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
</EditorForm>;
|
||||
|
||||
<EditorItem @bind-Field="@context.HeartbeatTime" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession) />
|
||||
<EditorItem @bind-Field="@context.DtuId" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpClient && context.ChannelType != ChannelTypeEnum.UdpSession)>
|
||||
|
||||
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<BootstrapInput @bind-Value=value.DtuId ShowLabel="true" class="me-2"></BootstrapInput>
|
||||
<Checkbox @bind-Value=value.DtuIdHex ShowAfterLabel DisplayText="hex"></Checkbox>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.DtuIdHex" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService) />
|
||||
|
||||
<EditorItem @bind-Field="@context.DtuSeviceType" Ignore=@(context.ChannelType != ChannelTypeEnum.TcpService && context.ChannelType != ChannelTypeEnum.UdpSession) />
|
||||
|
||||
</FieldItems>
|
||||
|
||||
</EditorForm>;
|
||||
|
||||
}
|
||||
@@ -53,6 +53,8 @@
|
||||
<TableColumn Field="@context.BindUrl" FieldExpression=@(() => context.BindUrl) ShowTips=true Filterable=true Sortable=true Visible=false />
|
||||
<TableColumn Field="@context.MaxClientCount" FieldExpression=@(() => context.MaxClientCount) ShowTips=true Filterable=true Sortable=true Visible=false />
|
||||
<TableColumn Field="@context.MaxConcurrentCount" FieldExpression=@(() => context.MaxConcurrentCount) ShowTips=true Filterable=true Sortable=true Visible=false />
|
||||
<TableColumn Field="@context.DtuIdHex" FieldExpression=@(() => context.DtuIdHex) ShowTips=true Filterable=true Sortable=true Visible=false />
|
||||
<TableColumn Field="@context.HeartbeatHex" FieldExpression=@(() => context.HeartbeatHex) ShowTips=true Filterable=true Sortable=true Visible=false />
|
||||
|
||||
<TableColumn @bind-Field="@context.Id" Filterable=true Sortable=true Visible="false" DefaultSort=true DefaultSortOrder="SortOrder.Asc" />
|
||||
|
||||
|
||||
@@ -138,9 +138,8 @@ public partial class VariableEditComponent
|
||||
AddressDynamicComponent = new BootstrapDynamicComponent(AddressUIType, new Dictionary<string, object?>
|
||||
{
|
||||
[nameof(IAddressUIBase.Model)] = Model.RegisterAddress,
|
||||
|
||||
[nameof(IAddressUIBase.ModelChanged)] =
|
||||
(string address) => Model.RegisterAddress = address
|
||||
(Action<string>)(address => Model.RegisterAddress = address)
|
||||
});
|
||||
}
|
||||
else
|
||||
|
||||
@@ -59,7 +59,7 @@ public partial class ModbusMaster : ComponentBase, IDisposable
|
||||
|
||||
op.Component = BootstrapDynamicComponent.CreateComponent<ModbusAddressComponent>(new Dictionary<string, object?>
|
||||
{
|
||||
{nameof(ModbusAddressComponent.ModelChanged), (string a) => DeviceComponent?.SetRegisterAddress(a)},
|
||||
{nameof(ModbusAddressComponent.ModelChanged), (Action<string>)(a => DeviceComponent?.SetRegisterAddress(a))},
|
||||
{nameof(ModbusAddressComponent.Model),address },
|
||||
});
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public partial class ModbusSlave : ComponentBase, IDisposable
|
||||
|
||||
op.Component = BootstrapDynamicComponent.CreateComponent<ModbusAddressComponent>(new Dictionary<string, object?>
|
||||
{
|
||||
{nameof(ModbusAddressComponent.ModelChanged), (string a) => DeviceComponent?.SetRegisterAddress(a)},
|
||||
{nameof(ModbusAddressComponent.ModelChanged), (Action<string>)(a => DeviceComponent?.SetRegisterAddress(a))},
|
||||
{nameof(ModbusAddressComponent.Model),address },
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user