#region copyright //------------------------------------------------------------------------------ // 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 // 此代码版权(除特别声明外的代码)归作者本人Diego所有 // 源代码使用协议遵循本仓库的开源协议及附加协议 // Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway // Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway // 使用文档:https://diego2098.gitee.io/thingsgateway-docs/ // QQ群:605534569 //------------------------------------------------------------------------------ #endregion using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Logging; using Microsoft.JSInterop; using System.IO; using System.Threading; using ThingsGateway.Admin.Blazor.Core; using ThingsGateway.Admin.Core; using ThingsGateway.Application.Extensions; using ThingsGateway.Foundation; namespace ThingsGateway.Application; /// /// 调试UI /// public abstract class DriverDebugUIBase : ComponentBase, IDisposable { /// /// 导出提示 /// public bool isDownExport; /// /// 日志缓存 /// public ConcurrentLinkedList<(LogLevel level, string message)> Messages = new(); IJSObjectReference _helper; readonly PeriodicTimer _periodicTimer = new(TimeSpan.FromSeconds(1)); /// /// 默认读写设备 /// public virtual IReadWriteDevice Plc { get; set; } /// /// 变量地址 /// public virtual string Address { get; set; } = "40001"; /// /// 数据类型 /// protected virtual DataTypeEnum DataTypeEnum { get; set; } = DataTypeEnum.Int16; /// [Inject] protected IJSRuntime JS { get; set; } /// /// 写入值 /// public virtual string WriteValue { get; set; } [Inject] private ICollectDeviceService CollectDeviceService { get; set; } [Inject] private IVariableService VariableService { get; set; } [Inject] private InitTimezone InitTimezone { get; set; } /// public virtual void Dispose() { _periodicTimer?.Dispose(); } /// public virtual async Task ReadAsync() { try { var data = await Plc.ReadAsync(Address, DataTypeEnum.GetSystemType()); if (data.IsSuccess) { Messages.Add((LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - 对应类型值:" + data.Content)); } else { Messages.Add((LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Message)); } } catch (Exception ex) { Messages.Add((LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + "错误:" + ex.Message)); } } /// public virtual async Task WriteAsync() { try { var data = await Plc.WriteAsync(Address, DataTypeEnum.GetSystemType(), WriteValue); if (data.IsSuccess) { Messages.Add((LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Message)); } else { Messages.Add((LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Message)); } } catch (Exception ex) { Messages.Add((LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "写入前失败:" + ex.Message)); } } /// /// 导入设备 /// /// public async Task DeviceImportAsync(CollectDevice data) { try { isDownExport = true; StateHasChanged(); await CollectDeviceService.AddAsync(data); } finally { isDownExport = false; } } /// /// 导入变量 /// /// public async Task DeviceVariableImportAsync(List data) { try { isDownExport = true; StateHasChanged(); await VariableService.AddBatchAsync(data); } finally { isDownExport = false; } } /// /// 导出 /// /// /// public async Task DownDeviceMessageExportAsync(IEnumerable values) { try { isDownExport = true; StateHasChanged(); using var memoryStream = new MemoryStream(); StreamWriter writer = new(memoryStream); foreach (var item in values) { writer.WriteLine(item); } writer.Flush(); memoryStream.Seek(0, SeekOrigin.Begin); using var streamRef = new DotNetStreamReference(stream: memoryStream); _helper ??= await JS.InvokeAsync("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js"); await _helper.InvokeVoidAsync("downloadFileFromStream", $"报文导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.txt", streamRef); } finally { isDownExport = false; } } /// /// 导出到excel /// /// public async Task DownDeviceExportAsync(CollectDevice data) { try { isDownExport = true; StateHasChanged(); using var memoryStream = await CollectDeviceService.ExportFileAsync(new List() { data }); memoryStream.Seek(0, SeekOrigin.Begin); using var streamRef = new DotNetStreamReference(stream: memoryStream); _helper ??= await JS.InvokeAsync("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js"); await _helper.InvokeVoidAsync("downloadFileFromStream", $"设备导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx", streamRef); } finally { isDownExport = false; } } /// /// 导出到excel /// /// public async Task DownDeviceVariableExportAsync(List data, string devName) { try { isDownExport = true; StateHasChanged(); using var memoryStream = await VariableService.ExportFileAsync(data, devName); memoryStream.Seek(0, SeekOrigin.Begin); using var streamRef = new DotNetStreamReference(stream: memoryStream); _helper ??= await JS.InvokeAsync("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js"); await _helper.InvokeVoidAsync("downloadFileFromStream", $"变量导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx", streamRef); } finally { isDownExport = false; } } /// public void LogOut(TouchSocket.Core.LogLevel logLevel, object source, string message, Exception exception) { Messages.Add(((LogLevel)logLevel, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + message + (exception != null ? exception.Message : ""))); if (Messages.Count > 2500) { Messages.Clear(); } } /// protected override void OnInitialized() { _ = RunTimerAsync(); base.OnInitialized(); } private async Task RunTimerAsync() { while (await _periodicTimer.WaitForNextTickAsync()) { await InvokeAsync(StateHasChanged); } } }