update driver messagesui
This commit is contained in:
@@ -7,10 +7,11 @@
|
||||
|
||||
基于Net6/7+Blazor Server的跨平台边缘采集网关,支持南北端插件式开发,
|
||||
并拥有较完善的北端Rpc权限管理。
|
||||
|
||||
[Github地址](https://github.com/kimdiego2098/ThingsGateway)
|
||||
|
||||
<div >
|
||||
<font color="#ffcc00">
|
||||
如果对您有帮助,请点击右上角⭐Star关注,感谢支持开源!
|
||||
</font>
|
||||
</div>
|
||||
|
||||
#### 功能亮点
|
||||
|
@@ -101,9 +101,9 @@
|
||||
@{
|
||||
var item = Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div title=@itemMessage.message class=@(itemMessage.isRed==null?" black--text ":itemMessage.isRed==true?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
<div title=@itemMessage.message class=@(itemMessage.level<Microsoft.Extensions.Logging.LogLevel.Information?" black--text ":itemMessage.level>=Microsoft.Extensions.Logging.LogLevel.Warning?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
@itemMessage.message
|
||||
</div>
|
||||
|
||||
|
@@ -101,9 +101,9 @@
|
||||
@{
|
||||
var item = Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div title=@itemMessage.message class=@(itemMessage.isRed==null?" black--text ":itemMessage.isRed==true?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
<div title=@itemMessage.message class=@(itemMessage.level<Microsoft.Extensions.Logging.LogLevel.Information?" black--text ":itemMessage.level>=Microsoft.Extensions.Logging.LogLevel.Warning?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
@itemMessage.message
|
||||
</div>
|
||||
|
||||
|
@@ -100,9 +100,9 @@
|
||||
@{
|
||||
var item = Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div title=@itemMessage.message class=@(itemMessage.isRed==null?" black--text ":itemMessage.isRed==true?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
<div title=@itemMessage.message class=@(itemMessage.level<Microsoft.Extensions.Logging.LogLevel.Information?" black--text ":itemMessage.level>=Microsoft.Extensions.Logging.LogLevel.Warning?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
@itemMessage.message
|
||||
</div>
|
||||
|
||||
|
@@ -99,9 +99,9 @@
|
||||
@{
|
||||
var item = Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div title=@itemMessage.message class=@(itemMessage.isRed==null?" black--text ":itemMessage.isRed==true?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
<div title=@itemMessage.message class=@(itemMessage.level<Microsoft.Extensions.Logging.LogLevel.Information?" black--text ":itemMessage.level>=Microsoft.Extensions.Logging.LogLevel.Warning?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
@itemMessage.message
|
||||
</div>
|
||||
|
||||
|
@@ -101,9 +101,9 @@
|
||||
@{
|
||||
var item = Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div title=@itemMessage.message class=@(itemMessage.isRed==null?" black--text ":itemMessage.isRed==true?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
<div title=@itemMessage.message class=@(itemMessage.level<Microsoft.Extensions.Logging.LogLevel.Information?" black--text ":itemMessage.level>=Microsoft.Extensions.Logging.LogLevel.Warning?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
@itemMessage.message
|
||||
</div>
|
||||
|
||||
|
@@ -100,9 +100,9 @@
|
||||
@{
|
||||
var item = Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div title=@itemMessage.message class=@(itemMessage.isRed==null?" black--text ":itemMessage.isRed==true?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
<div title=@itemMessage.message class=@(itemMessage.level<Microsoft.Extensions.Logging.LogLevel.Information?" black--text ":itemMessage.level>=Microsoft.Extensions.Logging.LogLevel.Warning?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
@itemMessage.message
|
||||
</div>
|
||||
|
||||
|
@@ -92,9 +92,9 @@
|
||||
@{
|
||||
var item = Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="200" Items="item.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="200" Items="item">
|
||||
<ItemContent>
|
||||
<div title=@itemMessage.message class=@(itemMessage.isRed==null?" black--text ":itemMessage.isRed==true?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
<div title=@itemMessage.message class=@(itemMessage.level<Microsoft.Extensions.Logging.LogLevel.Information?" black--text ":itemMessage.level>=Microsoft.Extensions.Logging.LogLevel.Warning?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
@itemMessage.message
|
||||
</div>
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
</MButton>
|
||||
</SaveContent>
|
||||
</PModal>
|
||||
@code{
|
||||
@code {
|
||||
bool IsShowImportVariableList;
|
||||
private ImportVariable importVariable { get; set; }
|
||||
}
|
||||
@@ -137,7 +137,7 @@
|
||||
private async Task DownDeviceExport()
|
||||
{
|
||||
var data = importVariable?.GetImportVariableList();
|
||||
if(data!=null)
|
||||
if (data != null)
|
||||
{
|
||||
await DownDeviceExport(data?.Item1);
|
||||
await DownDeviceExport(data?.Item2);
|
||||
@@ -158,10 +158,10 @@
|
||||
}
|
||||
private void ValueOut(List<ItemReadResult> values)
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), null, values.ToJson().FormatJson()));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, values.ToJson().FormatJson()));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.RemoveRange(0, 2000);
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -196,16 +196,16 @@
|
||||
var data = _plc.Write(address, writeValue);
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), false, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 写入" + data.Message));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 写入" + data.Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + "写入失败:" + ex.Message));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + "写入失败:" + ex.Message));
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
@@ -67,9 +67,9 @@
|
||||
|
||||
<MRow NoGutters>
|
||||
|
||||
<MButton Class="mx-1 my-3" Color="primary" OnClick="()=>IsShowImportVariableList=!IsShowImportVariableList">
|
||||
<span>导入变量</span>
|
||||
</MButton>
|
||||
<MButton Class="mx-1 my-3" Color="primary" OnClick="()=>IsShowImportVariableList=!IsShowImportVariableList">
|
||||
<span>导入变量</span>
|
||||
</MButton>
|
||||
|
||||
</MRow>
|
||||
</MCol>
|
||||
@@ -104,9 +104,9 @@
|
||||
@{
|
||||
var item = Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="200" Items="item.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 500px)") OverscanCount=2 ItemSize="200" Items="item">
|
||||
<ItemContent>
|
||||
<div title=@itemMessage.message class=@(itemMessage.isRed==null?" black--text ":itemMessage.isRed==true?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
<div title=@itemMessage.message class=@(itemMessage.level<Microsoft.Extensions.Logging.LogLevel.Information?" black--text ":itemMessage.level>=Microsoft.Extensions.Logging.LogLevel.Warning?" red--text ":"green--text ") style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;">
|
||||
@itemMessage.message
|
||||
</div>
|
||||
|
||||
@@ -177,10 +177,10 @@
|
||||
_plc.AddSubscription("", address, callback);
|
||||
else
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), null, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + "未连接"));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + "未连接"));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.RemoveRange(0, 2000);
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,10 +195,10 @@
|
||||
type = data.Value.WrappedValue.TypeInfo.ToString(),
|
||||
value = data.Value.Value,
|
||||
};
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), null, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + t.ToJson().FormatJson()));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + t.ToJson().FormatJson()));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.RemoveRange(0, 2000);
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,10 +208,10 @@
|
||||
_plc.RemoveSubscription("");
|
||||
else
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), null, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + "未连接"));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + "未连接"));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.RemoveRange(0, 2000);
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,7 +220,7 @@
|
||||
if (_plc.Connected)
|
||||
{
|
||||
var data = await _plc.ReadNodeAsync(address);
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), null, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + data.Select(a =>
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + data.Select(a =>
|
||||
{
|
||||
return new
|
||||
{
|
||||
@@ -230,15 +230,15 @@
|
||||
}).ToJson().FormatJson()));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.RemoveRange(0, 2000);
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), null, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + "未连接"));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + "未连接"));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.RemoveRange(0, 2000);
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,25 +252,25 @@
|
||||
var data = await _plc.WriteNodeAsync(address, Convert.ChangeType(writeValue, dataTypeEnum.GetNetType()));
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), false, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 写入成功"));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 写入成功"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 写入失败 " + data.Message));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 写入失败 " + data.Message));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), null, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + "未连接"));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + "未连接"));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.RemoveRange(0, 2000);
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add((Yitter.IdGenerator.YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + "写入失败:" + ex.Message));
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + "写入失败:" + ex.Message));
|
||||
}
|
||||
}
|
||||
public override void Dispose()
|
||||
|
@@ -0,0 +1,118 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
//https://github.com/dotnet-campus/AsyncWorkerCollection
|
||||
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
|
||||
namespace ThingsGateway.Foundation;
|
||||
|
||||
/// <summary>
|
||||
/// 线程安全的LinkedList,简化版
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ConcurrentLinkedList<T> : ICollection<T>
|
||||
{
|
||||
private readonly LinkedList<T> _list = new LinkedList<T>();
|
||||
/// <inheritdoc cref="LinkedList{T}.AddFirst(T)"/>
|
||||
private void AddFirst(T value)
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
_list.AddFirst(value);
|
||||
}
|
||||
}
|
||||
/// <inheritdoc cref="LinkedList{T}.Count"/>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
return _list.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
/// <inheritdoc cref="LinkedList{T}.AddLast(T)"/>
|
||||
private void AddLast(T value)
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
_list.AddLast(value);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="LinkedList{T}.Clear"/>
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
_list.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Add(T item)
|
||||
{
|
||||
AddFirst(item);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Contains(T item)
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
return _list.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
_list.CopyTo(array, arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Remove(T item)
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
return _list.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
return _list.ToList().GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
lock (((ICollection)_list).SyncRoot)
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
@@ -24,12 +24,12 @@ namespace ThingsGateway.Web.Foundation;
|
||||
public class TGRunTimeDatabaseLoggingWriter : IDatabaseLoggingWriter
|
||||
{
|
||||
private readonly SqlSugarScope _db;
|
||||
|
||||
private readonly GlobalCollectDeviceData _globalCollectDeviceData;
|
||||
/// <inheritdoc cref="TGRunTimeDatabaseLoggingWriter"/>
|
||||
public TGRunTimeDatabaseLoggingWriter()
|
||||
public TGRunTimeDatabaseLoggingWriter(GlobalCollectDeviceData globalCollectDeviceData)
|
||||
{
|
||||
_db = DbContext.Db;
|
||||
|
||||
_globalCollectDeviceData = globalCollectDeviceData;
|
||||
Task.Factory.StartNew(LogInsertAsync);
|
||||
}
|
||||
private ConcurrentQueue<RuntimeLog> _logQueues = new();
|
||||
@@ -71,6 +71,7 @@ public class TGRunTimeDatabaseLoggingWriter : IDatabaseLoggingWriter
|
||||
};
|
||||
//_db.InsertableWithAttr(logRuntime).ExecuteCommand();//入库
|
||||
_logQueues.Enqueue(logRuntime);
|
||||
//_globalCollectDeviceData.RunTimeLogs.Add((logRuntime.LogLevel, logRuntime.LogMessage));
|
||||
}
|
||||
|
||||
|
||||
|
@@ -67,7 +67,7 @@ public abstract class DriverBase : DisposableObject
|
||||
/// <summary>
|
||||
/// 报文信息
|
||||
/// </summary>
|
||||
public ConcurrentList<(long id, string message)> Messages { get; set; } = new();
|
||||
public ConcurrentLinkedList<string> Messages { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否连接成功
|
||||
@@ -91,7 +91,7 @@ public abstract class DriverBase : DisposableObject
|
||||
{
|
||||
if (arg1 == LogType.Trace && arg3.StartsWith("报文-"))
|
||||
{
|
||||
Messages.Add(new(YitIdHelper.NextId(), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff zz") + "-" + arg3));
|
||||
Messages.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff zz") + "-" + arg3);
|
||||
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#endregion
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
using System.IO;
|
||||
@@ -50,7 +51,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
/// <summary>
|
||||
/// 日志缓存
|
||||
/// </summary>
|
||||
protected ConcurrentList<(long id, bool? isRed, string message)> Messages = new();
|
||||
protected ConcurrentLinkedList<(LogLevel level, string message)> Messages = new();
|
||||
|
||||
/// <summary>
|
||||
/// 默认读写设备
|
||||
@@ -71,6 +72,12 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
[Inject]
|
||||
protected IJSRuntime JS { get; set; }
|
||||
|
||||
[Inject]
|
||||
ICollectDeviceService CollectDeviceService { get; set; }
|
||||
|
||||
[Inject]
|
||||
IVariableService VariableService { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
@@ -87,16 +94,16 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
{
|
||||
var byteConverter = ByteConverterHelper.GetTransByAddress(ref address, plc.ThingsGatewayBitConverter, out int length, out BcdFormat bcdFormat);
|
||||
var value = plc.ThingsGatewayBitConverter.GetDynamicData(dataTypeEnum.GetNetType(), data.Content).ToString();
|
||||
Messages.Add((YitIdHelper.NextId(), false, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 对应类型值:" + value + " - 原始字节:" + data.Content.ToHexString(" ")));
|
||||
Messages.Add((LogLevel.Information, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 对应类型值:" + value + " - 原始字节:" + data.Content.ToHexString(" ")));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add((YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 操作成功,但转换数据类型失败 - 原因:" + ex.Message + " - 原始字节:" + data.Content.ToHexString(" ")));
|
||||
Messages.Add((LogLevel.Warning, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - 操作成功,但转换数据类型失败 - 原因:" + ex.Message + " - 原始字节:" + data.Content.ToHexString(" ")));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
Messages.Add((LogLevel.Error, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,51 +116,19 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
var data = await plc.WriteAsync(dataTypeEnum.GetNetType(), address, writeValue, dataTypeEnum == DataTypeEnum.Bcd);
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Messages.Add((YitIdHelper.NextId(), false, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
Messages.Add((LogLevel.Information, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
Messages.Add((LogLevel.Warning, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + data.Message));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add((YitIdHelper.NextId(), true, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + "写入前失败:" + ex.Message));
|
||||
Messages.Add((LogLevel.Error, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + " - " + "写入前失败:" + ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task DownDeviceMessageExport(IEnumerable<string> values)
|
||||
{
|
||||
try
|
||||
{
|
||||
isDownExport = true;
|
||||
StateHasChanged();
|
||||
var memoryStream = new MemoryStream();
|
||||
StreamWriter writer = new StreamWriter(memoryStream);
|
||||
foreach (var item in values)
|
||||
{
|
||||
writer.WriteLine(item);
|
||||
}
|
||||
writer.Flush();
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
using var streamRef = new DotNetStreamReference(stream: memoryStream);
|
||||
await JS.InvokeVoidAsync("downloadFileFromStream", $"导出{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}.txt", streamRef);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isDownExport = false;
|
||||
}
|
||||
}
|
||||
[Inject]
|
||||
IVariableService VariableService { get; set; }
|
||||
[Inject]
|
||||
ICollectDeviceService CollectDeviceService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导入变量导出到excel
|
||||
/// </summary>
|
||||
@@ -174,6 +149,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
isDownExport = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入变量导出到excel
|
||||
/// </summary>
|
||||
@@ -194,13 +170,41 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
isDownExport = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task DownDeviceMessageExport(IEnumerable<string> values)
|
||||
{
|
||||
try
|
||||
{
|
||||
isDownExport = true;
|
||||
StateHasChanged();
|
||||
using var memoryStream = new MemoryStream();
|
||||
StreamWriter writer = new StreamWriter(memoryStream);
|
||||
foreach (var item in values)
|
||||
{
|
||||
writer.WriteLine(item);
|
||||
}
|
||||
writer.Flush();
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
using var streamRef = new DotNetStreamReference(stream: memoryStream);
|
||||
await JS.InvokeVoidAsync("downloadFileFromStream", $"导出{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}.txt", streamRef);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isDownExport = false;
|
||||
}
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
protected void LogOut(string str)
|
||||
{
|
||||
Messages.Add((YitIdHelper.NextId(), null, str));
|
||||
Messages.Add((LogLevel.Debug, str));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.RemoveRange(0, 2000);
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -270,8 +270,9 @@ public class VariableService : DbRepository<CollectDeviceVariable>, IVariableSer
|
||||
List<Dictionary<string, object>> devExports = new();
|
||||
//设备附加属性,转成Dict<表名,List<Dict<列名,列数据>>>的形式
|
||||
Dictionary<string, List<Dictionary<string, object>>> devicePropertys = new();
|
||||
|
||||
foreach (var devData in devDatas)
|
||||
ParallelOptions options = new ParallelOptions();
|
||||
options.MaxDegreeOfParallelism = Environment.ProcessorCount / 2;
|
||||
Parallel.ForEach(devDatas, options, devData =>
|
||||
{
|
||||
|
||||
//设备页
|
||||
@@ -325,7 +326,7 @@ public class VariableService : DbRepository<CollectDeviceVariable>, IVariableSer
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
//添加设备页
|
||||
sheets.Add(CollectDeviceSheetName, devExports);
|
||||
@@ -455,11 +456,11 @@ public class VariableService : DbRepository<CollectDeviceVariable>, IVariableSer
|
||||
|
||||
var uploadDevice = _uploadDeviceService.GetCacheList().FirstOrDefault(a => a.Name == uploadDevName);
|
||||
|
||||
if (deviceImportPreview.Data?.Any(it => it.Name == variableName) == true)
|
||||
if (deviceImportPreview.Data?.Any(it => it.Name == variableName) == true && uploadDevice != null)
|
||||
{
|
||||
var id = this.GetIdByName(variableName);
|
||||
var deviceId = id != 0 ? id : deviceImportPreview.Data.FirstOrDefault(it => it.Name == variableName).Id;
|
||||
deviceImportPreview.Data.FirstOrDefault(a => a.Id == deviceId).VariablePropertys.AddOrUpdate(uploadDevice.Id, devices);
|
||||
deviceImportPreview?.Data?.FirstOrDefault(a => a.Id == deviceId)?.VariablePropertys?.AddOrUpdate(uploadDevice.Id, devices);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -88,7 +88,6 @@ public class CollectDeviceWorker : BackgroundService
|
||||
/// </summary>
|
||||
public async Task RestartDeviceThreadAsync()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
await easyLock.LockAsync();
|
||||
@@ -161,7 +160,9 @@ public class CollectDeviceWorker : BackgroundService
|
||||
{
|
||||
if (!_stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
_logger.LogInformation("正在获取采集组态信息");
|
||||
var collectDeviceRunTimes = (await _collectDeviceService.GetCollectDeviceRuntimeAsync());
|
||||
_logger.LogInformation("获取采集组态信息完成");
|
||||
foreach (var collectDeviceRunTime in collectDeviceRunTimes)
|
||||
{
|
||||
if (!_stoppingToken.IsCancellationRequested)
|
||||
@@ -411,10 +412,9 @@ public class CollectDeviceWorker : BackgroundService
|
||||
/// <inheritdoc/>
|
||||
public override async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var stoppingToken = new CancellationTokenSource();
|
||||
using var stoppingToken = new CancellationTokenSource();
|
||||
_stoppingToken = stoppingToken.Token;
|
||||
stoppingToken.Cancel();
|
||||
stoppingToken?.SafeDispose();
|
||||
await Task.Delay(2000);
|
||||
StopOtherHostService();
|
||||
RemoveAllDeviceThread();
|
||||
@@ -423,6 +423,7 @@ public class CollectDeviceWorker : BackgroundService
|
||||
/// <inheritdoc/>
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
await RestartDeviceThreadAsync();
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
|
@@ -35,5 +35,8 @@ public class GlobalCollectDeviceData : ISingleton
|
||||
return CollectDevices?.SelectMany(it => it.DeviceVariableRunTimes).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// 后台实时日志
|
||||
///// </summary>
|
||||
//public ConcurrentLinkedList<(LogLevel level, string data)> RunTimeLogs { get; set; } = new();
|
||||
}
|
||||
|
@@ -314,10 +314,10 @@ public class UploadDeviceWorker : BackgroundService
|
||||
/// <inheritdoc/>
|
||||
public override async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var stoppingToken = new CancellationTokenSource();
|
||||
using var stoppingToken = new CancellationTokenSource();
|
||||
_stoppingToken = stoppingToken.Token;
|
||||
stoppingToken.Cancel();
|
||||
stoppingToken?.SafeDispose();
|
||||
await Task.Delay(2000);
|
||||
|
||||
RemoveAllDeviceThread();
|
||||
await base.StopAsync(cancellationToken);
|
||||
|
@@ -276,10 +276,10 @@
|
||||
{
|
||||
var item = CurMessages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 700px)") OverscanCount=2 ItemSize="100" Items="item?.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 700px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div>
|
||||
@itemMessage.message
|
||||
@itemMessage
|
||||
</div>
|
||||
</ItemContent>
|
||||
</MVirtualScroll>
|
||||
@@ -289,10 +289,10 @@
|
||||
{
|
||||
var item = collectDeviceInfoItem.Driver?.Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 700px)") OverscanCount=2 ItemSize="100" Items="item?.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" TItem="string" Height=@("calc(100vh - 700px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div>
|
||||
@itemMessage.message
|
||||
@itemMessage
|
||||
</div>
|
||||
</ItemContent>
|
||||
</MVirtualScroll>
|
||||
@@ -498,10 +498,10 @@
|
||||
{
|
||||
var item = CurMessages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 700px)") OverscanCount=2 ItemSize="100" Items="item?.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 700px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div>
|
||||
@itemMessage.message
|
||||
@itemMessage
|
||||
</div>
|
||||
</ItemContent>
|
||||
</MVirtualScroll>
|
||||
@@ -511,10 +511,10 @@
|
||||
{
|
||||
var item = uploadDeviceInfoItem.Driver?.Messages;
|
||||
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
|
||||
<MVirtualScroll Context="itemMessage" Height=@("calc(100vh - 700px)") OverscanCount=2 ItemSize="100" Items="item?.OrderByDescending(a=>a.id).ToList()">
|
||||
<MVirtualScroll Context="itemMessage" TItem="string" Height=@("calc(100vh - 700px)") OverscanCount=2 ItemSize="100" Items="item">
|
||||
<ItemContent>
|
||||
<div>
|
||||
@itemMessage.message
|
||||
@itemMessage
|
||||
</div>
|
||||
</ItemContent>
|
||||
</MVirtualScroll>
|
||||
@@ -580,19 +580,19 @@
|
||||
|
||||
@code {
|
||||
bool pauseMessage;
|
||||
List<(long id, string message)> CurMessages = new();
|
||||
async Task DownDeviceMessageExport(List<(long id, string message)> values)
|
||||
List<string> CurMessages = new();
|
||||
async Task DownDeviceMessageExport(List<string> values)
|
||||
{
|
||||
try
|
||||
{
|
||||
isDownExport = true;
|
||||
StateHasChanged();
|
||||
var memoryStream = new MemoryStream();
|
||||
using var memoryStream = new MemoryStream();
|
||||
StreamWriter writer = new StreamWriter(memoryStream);
|
||||
|
||||
foreach (var item in values)
|
||||
{
|
||||
writer.WriteLine(item.message);
|
||||
writer.WriteLine(item);
|
||||
}
|
||||
writer.Flush();
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
@@ -785,7 +785,7 @@
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -26,7 +26,6 @@
|
||||
@using ThingsGateway.Web.Rcl.Core;
|
||||
@using BlazorComponent;
|
||||
@using ThingsGateway.Web.Rcl;
|
||||
@using NewLife.Serialization;
|
||||
@using ThingsGateway.Web.Foundation;
|
||||
@using SqlSugar;
|
||||
@using Microsoft.Extensions.Options
|
||||
|
@@ -27,6 +27,13 @@
|
||||
</MIcon>
|
||||
</MButton>
|
||||
|
||||
@*<MButton Text Icon="@MasaBlazor.Breakpoint.SmAndDown"
|
||||
MaxHeight="@(UserResoures.Themes.LayoutPrpo.AppBarHeight-8)"
|
||||
OnClick=@OnSettingsClick>
|
||||
<MIcon>
|
||||
mdi-cog
|
||||
</MIcon>
|
||||
</MButton>*@
|
||||
|
||||
<UserMenu></UserMenu>
|
||||
|
||||
@@ -34,6 +41,9 @@
|
||||
{
|
||||
[Parameter]
|
||||
public EventCallback<string> LanguageChange { get; set; }
|
||||
|
||||
//[Parameter]
|
||||
//public EventCallback OnSettingsClick { get; set; }
|
||||
|
||||
[Inject]
|
||||
UserResoures UserResoures { get; set; }
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
<Configurations>Debug;Release;KINGVIEW</Configurations>
|
||||
<!--<ServerGarbageCollection>false</ServerGarbageCollection>-->
|
||||
<ServerGarbageCollection>false</ServerGarbageCollection>
|
||||
<!--切换为工作站GC策略-->
|
||||
</PropertyGroup>
|
||||
|
||||
|
Reference in New Issue
Block a user